| OLD | NEW |
| (Empty) |
| 1 // Copyright (c) 2017, the Dart project authors. Please see the AUTHORS file | |
| 2 // for details. All rights reserved. Use of this source code is governed by a | |
| 3 // BSD-style license that can be found in the LICENSE file. | |
| 4 | |
| 5 /// Additional data model classes used by the summary builder. | |
| 6 /// | |
| 7 /// The summary builder uses 4 pieces of data: | |
| 8 /// | |
| 9 /// * Unlinked**Builders: builder classes for each piece of output in the | |
| 10 /// summary (see format.dart). | |
| 11 /// | |
| 12 /// * A simplified expression syntax: model relevant pieces of initializers | |
| 13 /// and constants before serializing them (see expressions.dart). | |
| 14 /// | |
| 15 /// * Lazy references: a way to model references on the fly so we can build | |
| 16 /// summaries in a single pass. | |
| 17 /// | |
| 18 /// * Scopes: used to track the current context of the parser, used in great | |
| 19 /// part to easily resolve lazy references at the end of the build process. | |
| 20 library summary.src.scope; | |
| 21 | |
| 22 import 'package:analyzer/src/summary/format.dart'; | |
| 23 import 'package:analyzer/src/summary/idl.dart'; | |
| 24 | |
| 25 export 'package:analyzer/src/summary/format.dart'; | |
| 26 export 'package:analyzer/src/summary/idl.dart'; | |
| 27 export 'package:front_end/src/base/api_signature.dart'; | |
| 28 | |
| 29 export 'expressions.dart'; | |
| 30 export 'visitor.dart'; | |
| 31 | |
| 32 class ClassScope extends TypeParameterScope { | |
| 33 String className; | |
| 34 UnlinkedClassBuilder currentClass = new UnlinkedClassBuilder(); | |
| 35 UnlinkedPublicNameBuilder publicName = new UnlinkedPublicNameBuilder(); | |
| 36 Set<String> members = new Set<String>(); | |
| 37 ClassScope(Scope parent) : super(parent); | |
| 38 | |
| 39 void computeReference(LazyEntityRef ref) { | |
| 40 if (!members.contains(ref.name)) { | |
| 41 return super.computeReference(ref); | |
| 42 } | |
| 43 ref.reference = top.serializeReference( | |
| 44 top.serializeReference(null, className), ref.name); | |
| 45 } | |
| 46 | |
| 47 toString() => "<class-scope: $className>"; | |
| 48 } | |
| 49 | |
| 50 class EnumScope extends Scope { | |
| 51 final Scope parent; | |
| 52 UnlinkedEnumBuilder currentEnum = new UnlinkedEnumBuilder(); | |
| 53 | |
| 54 EnumScope(this.parent); | |
| 55 | |
| 56 void computeReference(LazyEntityRef ref) => throw "unexpected"; | |
| 57 } | |
| 58 | |
| 59 /// A lazily encoded reference. | |
| 60 /// | |
| 61 /// References in summaries are encoded based on the scope where they appear. | |
| 62 /// Most top-level references can be encoded eagerly, but references in the | |
| 63 /// scope of a class need to check whether a name is a member of such class. | |
| 64 /// Because we don't have such list of members available upfront, we create | |
| 65 /// these lazy references and finalize them after we finish going through the | |
| 66 /// program. | |
| 67 class LazyEntityRef extends EntityRefBuilder { | |
| 68 Scope scope; | |
| 69 String name; | |
| 70 bool wasExpanded = false; | |
| 71 | |
| 72 LazyEntityRef(this.name, this.scope) : super() { | |
| 73 scope.top._toExpand.add(this); | |
| 74 } | |
| 75 @override | |
| 76 int get paramReference { | |
| 77 expand(); | |
| 78 return super.paramReference; | |
| 79 } | |
| 80 | |
| 81 @override | |
| 82 int get reference { | |
| 83 expand(); | |
| 84 return super.reference; | |
| 85 } | |
| 86 | |
| 87 expand() { | |
| 88 if (!wasExpanded) { | |
| 89 scope.computeReference(this); | |
| 90 wasExpanded = true; | |
| 91 } | |
| 92 } | |
| 93 } | |
| 94 | |
| 95 /// A nested lazy reference, modeling something like `a.b.c`. | |
| 96 class NestedLazyEntityRef extends LazyEntityRef { | |
| 97 EntityRef prefix; | |
| 98 NestedLazyEntityRef(this.prefix, String name, Scope scope) | |
| 99 : super(name, scope.top); | |
| 100 | |
| 101 @override | |
| 102 expand() { | |
| 103 if (!wasExpanded) { | |
| 104 super.reference = scope.top.serializeReference(prefix.reference, name); | |
| 105 wasExpanded = true; | |
| 106 } | |
| 107 } | |
| 108 } | |
| 109 | |
| 110 /// A scope corresponding to a scope in the program like units, classes, or | |
| 111 /// enums. | |
| 112 /// | |
| 113 /// It is used to hold results that correspond to a given scope in the program | |
| 114 /// and to lazily resolve name references. | |
| 115 abstract class Scope { | |
| 116 Scope get parent; | |
| 117 | |
| 118 TopScope get top { | |
| 119 var s = this; | |
| 120 while (s.parent != null) s = s.parent; | |
| 121 return s; | |
| 122 } | |
| 123 | |
| 124 void computeReference(LazyEntityRef ref); | |
| 125 } | |
| 126 | |
| 127 /// Top scope, where the top-level unit is built. | |
| 128 class TopScope extends Scope { | |
| 129 /// Results of parsing the unit. | |
| 130 final UnlinkedUnitBuilder unit = new UnlinkedUnitBuilder( | |
| 131 classes: [], | |
| 132 enums: [], | |
| 133 executables: [], | |
| 134 exports: [], | |
| 135 imports: [], | |
| 136 parts: [], | |
| 137 references: [new UnlinkedReferenceBuilder()], | |
| 138 typedefs: [], | |
| 139 variables: []); | |
| 140 | |
| 141 /// Stores publicly visible names exported from the unit. | |
| 142 final UnlinkedPublicNamespaceBuilder publicNamespace = | |
| 143 new UnlinkedPublicNamespaceBuilder(names: [], exports: [], parts: []); | |
| 144 | |
| 145 /// Lazy references that need to be expanded after all scope information is | |
| 146 /// known. | |
| 147 List<LazyEntityRef> _toExpand = []; | |
| 148 | |
| 149 final Map<int, Map<String, int>> nameToReference = <int, Map<String, int>>{}; | |
| 150 | |
| 151 TopScope() { | |
| 152 unit.publicNamespace = publicNamespace; | |
| 153 } | |
| 154 | |
| 155 get parent => null; | |
| 156 | |
| 157 void computeReference(LazyEntityRef ref) { | |
| 158 ref.reference = serializeReference(null, ref.name); | |
| 159 } | |
| 160 | |
| 161 void expandLazyReferences() { | |
| 162 _toExpand.forEach((r) => r.expand()); | |
| 163 } | |
| 164 | |
| 165 int serializeReference(int prefixIndex, String name) => nameToReference | |
| 166 .putIfAbsent(prefixIndex, () => <String, int>{}) | |
| 167 .putIfAbsent(name, () { | |
| 168 int index = unit.references.length; | |
| 169 unit.references.add(new UnlinkedReferenceBuilder( | |
| 170 prefixReference: prefixIndex, name: name)); | |
| 171 return index; | |
| 172 }); | |
| 173 | |
| 174 toString() => "<top-scope>"; | |
| 175 } | |
| 176 | |
| 177 class TypeParameterScope extends Scope { | |
| 178 final Scope parent; | |
| 179 List<String> typeParameters = []; | |
| 180 | |
| 181 TypeParameterScope(this.parent); | |
| 182 | |
| 183 void computeReference(LazyEntityRef ref) { | |
| 184 var i = typeParameters.indexOf(ref.name); | |
| 185 if (i < 0) return parent.computeReference(ref); | |
| 186 // Note: there is no indexOffset here because we don't go into functions at | |
| 187 // all (so there is no nesting of type-parameter scopes). | |
| 188 ref.paramReference = typeParameters.length - i; | |
| 189 } | |
| 190 } | |
| OLD | NEW |