OLD | NEW |
1 // Copyright (c) 2016, the Dart project authors. Please see the AUTHORS file | 1 // Copyright (c) 2016, the Dart project authors. Please see the AUTHORS file |
2 // for details. All rights reserved. Use of this source code is governed by a | 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. | 3 // BSD-style license that can be found in the LICENSE file. |
4 | 4 |
5 library fasta.class_builder; | 5 library fasta.class_builder; |
6 | 6 |
7 import '../errors.dart' show internalError; | 7 import '../errors.dart' show internalError; |
8 | 8 |
9 import 'builder.dart' | 9 import 'builder.dart' |
10 show | 10 show |
11 Builder, | 11 Builder, |
12 ConstructorReferenceBuilder, | 12 ConstructorReferenceBuilder, |
13 LibraryBuilder, | 13 LibraryBuilder, |
14 MemberBuilder, | 14 MemberBuilder, |
15 MetadataBuilder, | 15 MetadataBuilder, |
16 MixinApplicationBuilder, | 16 MixinApplicationBuilder, |
17 NamedTypeBuilder, | 17 NamedTypeBuilder, |
| 18 Scope, |
| 19 ScopeBuilder, |
18 TypeBuilder, | 20 TypeBuilder, |
19 TypeDeclarationBuilder, | 21 TypeDeclarationBuilder, |
20 TypeVariableBuilder; | 22 TypeVariableBuilder; |
21 | 23 |
22 import '../scope.dart' show AccessErrorBuilder, AmbiguousBuilder, Scope; | |
23 | |
24 abstract class ClassBuilder<T extends TypeBuilder, R> | 24 abstract class ClassBuilder<T extends TypeBuilder, R> |
25 extends TypeDeclarationBuilder<T, R> { | 25 extends TypeDeclarationBuilder<T, R> { |
26 final List<TypeVariableBuilder> typeVariables; | 26 final List<TypeVariableBuilder> typeVariables; |
27 | 27 |
28 T supertype; | 28 T supertype; |
29 | 29 |
30 List<T> interfaces; | 30 List<T> interfaces; |
31 | 31 |
32 final Map<String, Builder> members; | 32 final Scope scope; |
| 33 |
| 34 final Scope constructors; |
| 35 |
| 36 final ScopeBuilder scopeBuilder; |
| 37 |
| 38 final ScopeBuilder constructorScopeBuilder; |
33 | 39 |
34 ClassBuilder( | 40 ClassBuilder( |
35 List<MetadataBuilder> metadata, | 41 List<MetadataBuilder> metadata, |
36 int modifiers, | 42 int modifiers, |
37 String name, | 43 String name, |
38 this.typeVariables, | 44 this.typeVariables, |
39 this.supertype, | 45 this.supertype, |
40 this.interfaces, | 46 this.interfaces, |
41 this.members, | 47 this.scope, |
| 48 this.constructors, |
42 LibraryBuilder parent, | 49 LibraryBuilder parent, |
43 int charOffset) | 50 int charOffset) |
44 : super(metadata, modifiers, name, parent, charOffset); | 51 : scopeBuilder = new ScopeBuilder(scope), |
| 52 constructorScopeBuilder = new ScopeBuilder(constructors), |
| 53 super(metadata, modifiers, name, parent, charOffset); |
45 | 54 |
46 /// Returns true if this class is the result of applying a mixin to its | 55 /// Returns true if this class is the result of applying a mixin to its |
47 /// superclass. | 56 /// superclass. |
48 bool get isMixinApplication => mixedInType != null; | 57 bool get isMixinApplication => mixedInType != null; |
49 | 58 |
50 T get mixedInType; | 59 T get mixedInType; |
51 | 60 |
52 List<ConstructorReferenceBuilder> get constructorReferences => null; | 61 List<ConstructorReferenceBuilder> get constructorReferences => null; |
53 | 62 |
54 Map<String, Builder> get constructors; | |
55 | |
56 Map<String, Builder> get membersInScope => members; | |
57 | |
58 LibraryBuilder get library { | 63 LibraryBuilder get library { |
59 LibraryBuilder library = parent; | 64 LibraryBuilder library = parent; |
60 return library.partOfLibrary ?? library; | 65 return library.partOfLibrary ?? library; |
61 } | 66 } |
62 | 67 |
63 int resolveConstructors(LibraryBuilder library) { | 68 int resolveConstructors(LibraryBuilder library) { |
64 if (constructorReferences == null) return 0; | 69 if (constructorReferences == null) return 0; |
65 Scope scope = computeInstanceScope(library.scope); | |
66 for (ConstructorReferenceBuilder ref in constructorReferences) { | 70 for (ConstructorReferenceBuilder ref in constructorReferences) { |
67 ref.resolveIn(scope); | 71 ref.resolveIn(scope); |
68 } | 72 } |
69 return constructorReferences.length; | 73 return constructorReferences.length; |
70 } | 74 } |
71 | 75 |
72 Scope computeInstanceScope(Scope parent) { | |
73 if (typeVariables != null) { | |
74 Map<String, Builder> local = <String, Builder>{}; | |
75 for (TypeVariableBuilder t in typeVariables) { | |
76 local[t.name] = t; | |
77 } | |
78 parent = new Scope(local, null, parent, isModifiable: false); | |
79 } | |
80 return new Scope(membersInScope, null, parent, isModifiable: false); | |
81 } | |
82 | |
83 /// Used to lookup a static member of this class. | 76 /// Used to lookup a static member of this class. |
84 Builder findStaticBuilder(String name, int charOffset, Uri fileUri, | 77 Builder findStaticBuilder(String name, int charOffset, Uri fileUri, |
85 {bool isSetter: false}) { | 78 {bool isSetter: false}) { |
86 Builder builder = members[name]; | 79 Builder builder = isSetter |
87 if (builder?.next != null) { | 80 ? scope.lookupSetter(name, charOffset, fileUri, isInstanceScope: false) |
88 Builder getterBuilder; | 81 : scope.lookup(name, charOffset, fileUri, isInstanceScope: false); |
89 Builder setterBuilder; | 82 return builder; |
90 Builder current = builder; | |
91 while (current != null) { | |
92 if (current.isGetter && getterBuilder == null) { | |
93 getterBuilder = current; | |
94 } else if (current.isSetter && setterBuilder == null) { | |
95 setterBuilder = current; | |
96 } else { | |
97 return new AmbiguousBuilder(name, builder, charOffset, fileUri); | |
98 } | |
99 current = current.next; | |
100 } | |
101 if (getterBuilder?.isInstanceMember ?? false) { | |
102 getterBuilder = null; | |
103 } | |
104 if (setterBuilder?.isInstanceMember ?? false) { | |
105 setterBuilder = null; | |
106 } | |
107 builder = isSetter ? setterBuilder : getterBuilder; | |
108 if (builder == null) { | |
109 if (isSetter && getterBuilder != null) { | |
110 return new AccessErrorBuilder( | |
111 name, getterBuilder, charOffset, fileUri); | |
112 } else if (!isSetter && setterBuilder != null) { | |
113 return new AccessErrorBuilder( | |
114 name, setterBuilder, charOffset, fileUri); | |
115 } | |
116 } | |
117 } | |
118 if (builder == null) { | |
119 return null; | |
120 } else if (isSetter && builder.isGetter) { | |
121 return null; | |
122 } else { | |
123 return builder.isInstanceMember ? null : builder; | |
124 } | |
125 } | 83 } |
126 | 84 |
127 Builder findConstructorOrFactory(String name, int charOffset, Uri uri) { | 85 Builder findConstructorOrFactory(String name, int charOffset, Uri uri) { |
128 return constructors[name]; | 86 return constructors.lookup(name, charOffset, uri); |
129 } | 87 } |
130 | 88 |
131 /// Returns a map which maps the type variables of [superclass] to their | 89 /// Returns a map which maps the type variables of [superclass] to their |
132 /// respective values as defined by the superclass clause of this class (and | 90 /// respective values as defined by the superclass clause of this class (and |
133 /// its superclasses). | 91 /// its superclasses). |
134 /// | 92 /// |
135 /// It's assumed that [superclass] is a superclass of this class. | 93 /// It's assumed that [superclass] is a superclass of this class. |
136 /// | 94 /// |
137 /// For example, given: | 95 /// For example, given: |
138 /// | 96 /// |
(...skipping 46 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
185 } | 143 } |
186 directSubstitutionMap[variables[i]] = argument; | 144 directSubstitutionMap[variables[i]] = argument; |
187 } | 145 } |
188 substitutionMap = directSubstitutionMap; | 146 substitutionMap = directSubstitutionMap; |
189 } | 147 } |
190 } | 148 } |
191 return substitutionMap; | 149 return substitutionMap; |
192 } | 150 } |
193 | 151 |
194 void forEach(void f(String name, MemberBuilder builder)) { | 152 void forEach(void f(String name, MemberBuilder builder)) { |
195 members.forEach(f); | 153 scope.forEach(f); |
196 } | 154 } |
197 | 155 |
198 /// Don't use for scope lookup. Only use when an element is known to exist | 156 /// Don't use for scope lookup. Only use when an element is known to exist |
199 /// (and not a setter). | 157 /// (and not a setter). |
200 MemberBuilder operator [](String name) { | 158 MemberBuilder operator [](String name) { |
201 return members[name] ?? internalError("Not found: '$name'."); | 159 return scope.local[name] ?? internalError("Not found: '$name'."); |
202 } | 160 } |
203 | 161 |
204 void addCompileTimeError(int charOffset, String message) { | 162 void addCompileTimeError(int charOffset, String message) { |
205 library.addCompileTimeError(charOffset, message, fileUri: fileUri); | 163 library.addCompileTimeError(charOffset, message, fileUri: fileUri); |
206 } | 164 } |
207 | 165 |
208 void addWarning(int charOffset, String message) { | 166 void addWarning(int charOffset, String message) { |
209 library.addWarning(charOffset, message, fileUri: fileUri); | 167 library.addWarning(charOffset, message, fileUri: fileUri); |
210 } | 168 } |
211 | 169 |
212 void addNit(int charOffset, String message) { | 170 void addNit(int charOffset, String message) { |
213 library.addNit(charOffset, message, fileUri: fileUri); | 171 library.addNit(charOffset, message, fileUri: fileUri); |
214 } | 172 } |
215 } | 173 } |
OLD | NEW |