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 |