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.kernel_library_builder; | 5 library fasta.kernel_library_builder; |
6 | 6 |
7 import 'package:kernel/ast.dart'; | 7 import 'package:kernel/ast.dart'; |
8 | 8 |
9 import 'package:kernel/clone.dart' show CloneVisitor; | 9 import 'package:kernel/clone.dart' show CloneVisitor; |
10 | 10 |
(...skipping 28 matching lines...) Expand all Loading... | |
39 KernelFunctionTypeBuilder, | 39 KernelFunctionTypeBuilder, |
40 KernelInvalidTypeBuilder, | 40 KernelInvalidTypeBuilder, |
41 KernelMixinApplicationBuilder, | 41 KernelMixinApplicationBuilder, |
42 KernelNamedMixinApplicationBuilder, | 42 KernelNamedMixinApplicationBuilder, |
43 KernelNamedTypeBuilder, | 43 KernelNamedTypeBuilder, |
44 KernelProcedureBuilder, | 44 KernelProcedureBuilder, |
45 KernelTypeBuilder, | 45 KernelTypeBuilder, |
46 KernelTypeVariableBuilder, | 46 KernelTypeVariableBuilder, |
47 MemberBuilder, | 47 MemberBuilder, |
48 MetadataBuilder, | 48 MetadataBuilder, |
49 MixedAccessor, | |
50 NamedMixinApplicationBuilder, | 49 NamedMixinApplicationBuilder, |
51 PrefixBuilder, | 50 PrefixBuilder, |
52 ProcedureBuilder, | 51 ProcedureBuilder, |
52 Scope, | |
53 TypeBuilder, | 53 TypeBuilder, |
54 TypeVariableBuilder, | 54 TypeVariableBuilder, |
55 compareProcedures; | 55 compareProcedures; |
56 | 56 |
57 class KernelLibraryBuilder | 57 class KernelLibraryBuilder |
58 extends SourceLibraryBuilder<KernelTypeBuilder, Library> { | 58 extends SourceLibraryBuilder<KernelTypeBuilder, Library> { |
59 final Library library; | 59 final Library library; |
60 | 60 |
61 final Map<String, SourceClassBuilder> mixinApplicationClasses = | 61 final Map<String, SourceClassBuilder> mixinApplicationClasses = |
62 <String, SourceClassBuilder>{}; | 62 <String, SourceClassBuilder>{}; |
(...skipping 33 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
96 void addClass( | 96 void addClass( |
97 List<MetadataBuilder> metadata, | 97 List<MetadataBuilder> metadata, |
98 int modifiers, | 98 int modifiers, |
99 String className, | 99 String className, |
100 List<TypeVariableBuilder> typeVariables, | 100 List<TypeVariableBuilder> typeVariables, |
101 KernelTypeBuilder supertype, | 101 KernelTypeBuilder supertype, |
102 List<KernelTypeBuilder> interfaces, | 102 List<KernelTypeBuilder> interfaces, |
103 int charOffset) { | 103 int charOffset) { |
104 assert(currentDeclaration.parent == libraryDeclaration); | 104 assert(currentDeclaration.parent == libraryDeclaration); |
105 Map<String, MemberBuilder> members = currentDeclaration.members; | 105 Map<String, MemberBuilder> members = currentDeclaration.members; |
106 Map<String, MemberBuilder> constructors = currentDeclaration.constructors; | |
107 Map<String, MemberBuilder> setters = currentDeclaration.setters; | |
108 | |
109 Scope classScope = new Scope( | |
110 members, setters, scope.withTypeVariables(typeVariables), | |
111 isModifiable: false); | |
112 | |
113 // When looking up a constructor, we don't consider type variables or the | |
114 // library scope. | |
115 Scope constructorScope = | |
116 new Scope(constructors, null, null, isModifiable: false); | |
106 ClassBuilder cls = new SourceClassBuilder( | 117 ClassBuilder cls = new SourceClassBuilder( |
107 metadata, | 118 metadata, |
108 modifiers, | 119 modifiers, |
109 className, | 120 className, |
110 typeVariables, | 121 typeVariables, |
111 supertype, | 122 supertype, |
112 interfaces, | 123 interfaces, |
113 members, | 124 classScope, |
125 constructorScope, | |
114 this, | 126 this, |
115 new List<ConstructorReferenceBuilder>.from(constructorReferences), | 127 new List<ConstructorReferenceBuilder>.from(constructorReferences), |
116 charOffset); | 128 charOffset); |
117 constructorReferences.clear(); | 129 constructorReferences.clear(); |
118 members.forEach((String name, MemberBuilder builder) { | 130 void setParent(String name, MemberBuilder member) { |
119 while (builder != null) { | 131 while (member != null) { |
120 builder.parent = cls; | 132 member.parent = cls; |
121 builder = builder.next; | 133 member = member.next; |
122 } | 134 } |
123 }); | 135 } |
136 | |
137 members.forEach(setParent); | |
138 constructors.forEach(setParent); | |
139 setters.forEach(setParent); | |
124 // Nested declaration began in `OutlineBuilder.beginClassDeclaration`. | 140 // Nested declaration began in `OutlineBuilder.beginClassDeclaration`. |
125 endNestedDeclaration().resolveTypes(typeVariables, this); | 141 endNestedDeclaration().resolveTypes(typeVariables, this); |
126 addBuilder(className, cls, charOffset); | 142 addBuilder(className, cls, charOffset); |
127 } | 143 } |
128 | 144 |
129 void addNamedMixinApplication( | 145 void addNamedMixinApplication( |
130 List<MetadataBuilder> metadata, | 146 List<MetadataBuilder> metadata, |
131 String name, | 147 String name, |
132 List<TypeVariableBuilder> typeVariables, | 148 List<TypeVariableBuilder> typeVariables, |
133 int modifiers, | 149 int modifiers, |
(...skipping 10 matching lines...) Expand all Loading... | |
144 | 160 |
145 void addField(List<MetadataBuilder> metadata, int modifiers, | 161 void addField(List<MetadataBuilder> metadata, int modifiers, |
146 KernelTypeBuilder type, String name, int charOffset) { | 162 KernelTypeBuilder type, String name, int charOffset) { |
147 addBuilder( | 163 addBuilder( |
148 name, | 164 name, |
149 new KernelFieldBuilder( | 165 new KernelFieldBuilder( |
150 metadata, type, name, modifiers, this, charOffset), | 166 metadata, type, name, modifiers, this, charOffset), |
151 charOffset); | 167 charOffset); |
152 } | 168 } |
153 | 169 |
154 String computeConstructorName(String name) { | 170 String computeAndValidateConstructorName(String name, int charOffset) { |
155 assert(isConstructorName(name, currentDeclaration.name)); | 171 String className = currentDeclaration.name; |
172 bool startsWithClassName = name.startsWith(className); | |
173 if (startsWithClassName && name.length == className.length) { | |
174 // Unnamed constructor or factory. | |
175 return ""; | |
176 } | |
156 int index = name.indexOf("."); | 177 int index = name.indexOf("."); |
157 return index == -1 ? "" : name.substring(index + 1); | 178 if (startsWithClassName && index == className.length) { |
179 // Named constructor or factory. | |
180 return name.substring(index + 1); | |
181 } | |
182 if (index == -1) { | |
183 // A legal name. | |
karlklose
2017/04/03 08:05:37
How about 'A legal name for a method, but not for
ahe
2017/04/04 09:54:51
Done.
| |
184 return null; | |
185 } | |
186 String suffix = name.substring(index + 1); | |
187 addCompileTimeError( | |
188 charOffset, | |
189 "'$name' isn't a legal method name.\n" | |
190 "Did you mean '$className.$suffix'?"); | |
191 return suffix; | |
158 } | 192 } |
159 | 193 |
160 void addProcedure( | 194 void addProcedure( |
161 List<MetadataBuilder> metadata, | 195 List<MetadataBuilder> metadata, |
162 int modifiers, | 196 int modifiers, |
163 KernelTypeBuilder returnType, | 197 KernelTypeBuilder returnType, |
164 String name, | 198 String name, |
165 List<TypeVariableBuilder> typeVariables, | 199 List<TypeVariableBuilder> typeVariables, |
166 List<FormalParameterBuilder> formals, | 200 List<FormalParameterBuilder> formals, |
167 AsyncMarker asyncModifier, | 201 AsyncMarker asyncModifier, |
168 ProcedureKind kind, | 202 ProcedureKind kind, |
169 int charOffset, | 203 int charOffset, |
170 int charOpenParenOffset, | 204 int charOpenParenOffset, |
171 int charEndOffset, | 205 int charEndOffset, |
172 String nativeMethodName, | 206 String nativeMethodName, |
173 {bool isTopLevel}) { | 207 {bool isTopLevel}) { |
174 // Nested declaration began in `OutlineBuilder.beginMethod` or | 208 // Nested declaration began in `OutlineBuilder.beginMethod` or |
175 // `OutlineBuilder.beginTopLevelMethod`. | 209 // `OutlineBuilder.beginTopLevelMethod`. |
176 endNestedDeclaration().resolveTypes(typeVariables, this); | 210 endNestedDeclaration().resolveTypes(typeVariables, this); |
177 ProcedureBuilder procedure; | 211 ProcedureBuilder procedure; |
178 if (!isTopLevel && isConstructorName(name, currentDeclaration.name)) { | 212 String constructorName = |
179 name = computeConstructorName(name); | 213 isTopLevel ? null : computeAndValidateConstructorName(name, charOffset); |
214 if (constructorName != null) { | |
215 name = constructorName; | |
180 procedure = new KernelConstructorBuilder( | 216 procedure = new KernelConstructorBuilder( |
181 metadata, | 217 metadata, |
182 modifiers & ~abstractMask, | 218 modifiers & ~abstractMask, |
183 returnType, | 219 returnType, |
184 name, | 220 name, |
185 typeVariables, | 221 typeVariables, |
186 formals, | 222 formals, |
187 this, | 223 this, |
188 charOffset, | 224 charOffset, |
189 charOpenParenOffset, | 225 charOpenParenOffset, |
(...skipping 17 matching lines...) Expand all Loading... | |
207 } | 243 } |
208 addBuilder(name, procedure, charOffset); | 244 addBuilder(name, procedure, charOffset); |
209 if (nativeMethodName != null) { | 245 if (nativeMethodName != null) { |
210 addNativeMethod(procedure); | 246 addNativeMethod(procedure); |
211 } | 247 } |
212 } | 248 } |
213 | 249 |
214 void addFactoryMethod( | 250 void addFactoryMethod( |
215 List<MetadataBuilder> metadata, | 251 List<MetadataBuilder> metadata, |
216 int modifiers, | 252 int modifiers, |
217 ConstructorReferenceBuilder constructorName, | 253 ConstructorReferenceBuilder constructorNameReference, |
218 List<FormalParameterBuilder> formals, | 254 List<FormalParameterBuilder> formals, |
219 AsyncMarker asyncModifier, | 255 AsyncMarker asyncModifier, |
220 ConstructorReferenceBuilder redirectionTarget, | 256 ConstructorReferenceBuilder redirectionTarget, |
221 int charOffset, | 257 int charOffset, |
222 int charOpenParenOffset, | 258 int charOpenParenOffset, |
223 int charEndOffset, | 259 int charEndOffset, |
224 String nativeMethodName) { | 260 String nativeMethodName) { |
225 // Nested declaration began in `OutlineBuilder.beginFactoryMethod`. | 261 // Nested declaration began in `OutlineBuilder.beginFactoryMethod`. |
226 DeclarationBuilder<KernelTypeBuilder> factoryDeclaration = | 262 DeclarationBuilder<KernelTypeBuilder> factoryDeclaration = |
227 endNestedDeclaration(); | 263 endNestedDeclaration(); |
228 String name = constructorName.name; | 264 String name = constructorNameReference.name; |
229 if (isConstructorName(name, currentDeclaration.name)) { | 265 String constructorName = |
230 name = computeConstructorName(name); | 266 computeAndValidateConstructorName(name, charOffset); |
267 if (constructorName != null) { | |
268 name = constructorName; | |
231 } | 269 } |
232 assert(constructorName.suffix == null); | 270 assert(constructorNameReference.suffix == null); |
233 KernelProcedureBuilder procedure = new KernelProcedureBuilder( | 271 KernelProcedureBuilder procedure = new KernelProcedureBuilder( |
234 metadata, | 272 metadata, |
235 staticMask | modifiers, | 273 staticMask | modifiers, |
236 null, | 274 null, |
237 name, | 275 name, |
238 <TypeVariableBuilder>[], | 276 <TypeVariableBuilder>[], |
239 formals, | 277 formals, |
240 asyncModifier, | 278 asyncModifier, |
241 ProcedureKind.Factory, | 279 ProcedureKind.Factory, |
242 this, | 280 this, |
(...skipping 85 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
328 super.build(); | 366 super.build(); |
329 library.name = name; | 367 library.name = name; |
330 library.procedures.sort(compareProcedures); | 368 library.procedures.sort(compareProcedures); |
331 return library; | 369 return library; |
332 } | 370 } |
333 | 371 |
334 @override | 372 @override |
335 Builder buildAmbiguousBuilder( | 373 Builder buildAmbiguousBuilder( |
336 String name, Builder builder, Builder other, int charOffset, | 374 String name, Builder builder, Builder other, int charOffset, |
337 {bool isExport: false, bool isImport: false}) { | 375 {bool isExport: false, bool isImport: false}) { |
376 // TODO(ahe): Can I move this to Scope or Prefix? | |
338 if (builder == other) return builder; | 377 if (builder == other) return builder; |
339 if (builder is InvalidTypeBuilder) return builder; | 378 if (builder is InvalidTypeBuilder) return builder; |
340 if (other is InvalidTypeBuilder) return other; | 379 if (other is InvalidTypeBuilder) return other; |
341 if (builder is AccessErrorBuilder) { | 380 if (builder is AccessErrorBuilder) { |
342 AccessErrorBuilder error = builder; | 381 AccessErrorBuilder error = builder; |
343 builder = error.builder; | 382 builder = error.builder; |
344 } | 383 } |
345 if (other is AccessErrorBuilder) { | 384 if (other is AccessErrorBuilder) { |
346 AccessErrorBuilder error = other; | 385 AccessErrorBuilder error = other; |
347 other = error.builder; | 386 other = error.builder; |
348 } | 387 } |
349 bool isLocal = false; | 388 bool isLocal = false; |
350 Builder preferred; | 389 Builder preferred; |
351 Uri uri; | 390 Uri uri; |
352 Uri otherUri; | 391 Uri otherUri; |
353 Uri preferredUri; | 392 Uri preferredUri; |
354 Uri hiddenUri; | 393 Uri hiddenUri; |
355 if (members[name] == builder) { | 394 if (scope.local[name] == builder) { |
356 isLocal = true; | 395 isLocal = true; |
357 preferred = builder; | 396 preferred = builder; |
358 hiddenUri = other.computeLibraryUri(); | 397 hiddenUri = other.computeLibraryUri(); |
359 } else { | 398 } else { |
360 uri = builder.computeLibraryUri(); | 399 uri = builder.computeLibraryUri(); |
361 otherUri = other.computeLibraryUri(); | 400 otherUri = other.computeLibraryUri(); |
362 if (otherUri?.scheme == "dart" && uri?.scheme != "dart") { | 401 if (otherUri?.scheme == "dart" && uri?.scheme != "dart") { |
363 preferred = builder; | 402 preferred = builder; |
364 preferredUri = uri; | 403 preferredUri = uri; |
365 hiddenUri = otherUri; | 404 hiddenUri = otherUri; |
(...skipping 21 matching lines...) Expand all Loading... | |
387 } else { | 426 } else { |
388 addNit( | 427 addNit( |
389 charOffset, | 428 charOffset, |
390 "Import of '$name' (from '${preferredUri}') hides import from " | 429 "Import of '$name' (from '${preferredUri}') hides import from " |
391 "'${hiddenUri}'."); | 430 "'${hiddenUri}'."); |
392 } | 431 } |
393 } | 432 } |
394 return preferred; | 433 return preferred; |
395 } | 434 } |
396 if (builder.next == null && other.next == null) { | 435 if (builder.next == null && other.next == null) { |
397 if (builder.isGetter && other.isSetter) { | |
398 return new MixedAccessor(builder, other, this); | |
399 } else if (builder.isSetter && other.isGetter) { | |
400 return new MixedAccessor(other, builder, this); | |
401 } | |
402 if (isImport && builder is PrefixBuilder && other is PrefixBuilder) { | 436 if (isImport && builder is PrefixBuilder && other is PrefixBuilder) { |
403 // Handles the case where the same prefix is used for different | 437 // Handles the case where the same prefix is used for different |
404 // imports. | 438 // imports. |
405 PrefixBuilder prefix = builder; | 439 return builder |
406 other.exports.forEach((String name, Builder member) { | 440 ..exports.merge(other.exports, |
407 Builder existing = exports[name]; | 441 (String name, Builder existing, Builder member) { |
408 if (existing != null) { | 442 return buildAmbiguousBuilder(name, existing, member, charOffset, |
409 if (existing != member) { | 443 isExport: isExport, isImport: isImport); |
410 member = buildAmbiguousBuilder(name, existing, member, charOffset, | 444 }); |
411 isExport: isExport, isImport: isImport); | |
412 } | |
413 } | |
414 prefix.exports[name] = member; | |
415 }); | |
416 return builder; | |
417 } | 445 } |
418 } | 446 } |
419 if (isExport) { | 447 if (isExport) { |
420 addNit(charOffset, | 448 addNit(charOffset, |
421 "'$name' is exported from both '${uri}' and '${otherUri}'."); | 449 "'$name' is exported from both '${uri}' and '${otherUri}'."); |
422 } else { | 450 } else { |
423 addNit(charOffset, | 451 addNit(charOffset, |
424 "'$name' is imported from both '${uri}' and '${otherUri}'."); | 452 "'$name' is imported from both '${uri}' and '${otherUri}'."); |
425 } | 453 } |
426 return new KernelInvalidTypeBuilder(name, charOffset, fileUri); | 454 return new KernelInvalidTypeBuilder(name, charOffset, fileUri); |
(...skipping 81 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
508 } | 536 } |
509 | 537 |
510 @override | 538 @override |
511 void includePart(covariant KernelLibraryBuilder part) { | 539 void includePart(covariant KernelLibraryBuilder part) { |
512 super.includePart(part); | 540 super.includePart(part); |
513 nativeMethods.addAll(part.nativeMethods); | 541 nativeMethods.addAll(part.nativeMethods); |
514 boundlessTypeVariables.addAll(part.boundlessTypeVariables); | 542 boundlessTypeVariables.addAll(part.boundlessTypeVariables); |
515 assert(mixinApplicationClasses.isEmpty); | 543 assert(mixinApplicationClasses.isEmpty); |
516 } | 544 } |
517 } | 545 } |
518 | |
519 bool isConstructorName(String name, String className) { | |
520 if (name.startsWith(className)) { | |
521 if (name.length == className.length) return true; | |
522 if (name.startsWith(".", className.length)) return true; | |
523 } | |
524 return false; | |
525 } | |
OLD | NEW |