Chromium Code Reviews
chromiumcodereview-hr@appspot.gserviceaccount.com (chromiumcodereview-hr) | Please choose your nickname with Settings | Help | Chromium Project | Gerrit Changes | Sign out
(150)

Side by Side Diff: pkg/front_end/lib/src/fasta/source/source_library_builder.dart

Issue 2788153002: Create separate scopes for constructors, setters, and other members. (Closed)
Patch Set: One more flaky standalone/io test. Created 3 years, 8 months ago
Use n/p to move between diff chunks; N/P to move between comments. Draft comments are only viewable by you.
Jump to:
View unified diff | Download patch
« no previous file with comments | « pkg/front_end/lib/src/fasta/source/source_class_builder.dart ('k') | samples/samples.status » ('j') | no next file with comments »
Toggle Intra-line Diffs ('i') | Expand Comments ('e') | Collapse Comments ('c') | Show Comments Hide Comments ('s')
OLDNEW
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.source_library_builder; 5 library fasta.source_library_builder;
6 6
7 import 'package:kernel/ast.dart' show AsyncMarker, ProcedureKind; 7 import 'package:kernel/ast.dart' show AsyncMarker, ProcedureKind;
8 8
9 import '../combinator.dart' show Combinator; 9 import '../combinator.dart' show Combinator;
10 10
(...skipping 20 matching lines...) Expand all
31 Scope, 31 Scope,
32 TypeBuilder, 32 TypeBuilder,
33 TypeDeclarationBuilder, 33 TypeDeclarationBuilder,
34 TypeVariableBuilder, 34 TypeVariableBuilder,
35 Unhandled; 35 Unhandled;
36 36
37 abstract class SourceLibraryBuilder<T extends TypeBuilder, R> 37 abstract class SourceLibraryBuilder<T extends TypeBuilder, R>
38 extends LibraryBuilder<T, R> { 38 extends LibraryBuilder<T, R> {
39 final SourceLoader loader; 39 final SourceLoader loader;
40 40
41 final DeclarationBuilder<T> libraryDeclaration = 41 final DeclarationBuilder<T> libraryDeclaration;
42 new DeclarationBuilder<T>(<String, Builder>{}, null);
43 42
44 final List<ConstructorReferenceBuilder> constructorReferences = 43 final List<ConstructorReferenceBuilder> constructorReferences =
45 <ConstructorReferenceBuilder>[]; 44 <ConstructorReferenceBuilder>[];
46 45
47 final List<SourceLibraryBuilder<T, R>> parts = <SourceLibraryBuilder<T, R>>[]; 46 final List<SourceLibraryBuilder<T, R>> parts = <SourceLibraryBuilder<T, R>>[];
48 47
49 final List<Import> imports = <Import>[]; 48 final List<Import> imports = <Import>[];
50 49
51 final Map<String, Builder> exports = <String, Builder>{}; 50 final Scope importScope;
52
53 final Scope scope = new Scope.top();
54 51
55 final Uri fileUri; 52 final Uri fileUri;
56 53
57 final List<List> implementationBuilders = <List<List>>[]; 54 final List<List> implementationBuilders = <List<List>>[];
58 55
59 String name; 56 String name;
60 57
61 String partOfName; 58 String partOfName;
62 59
63 Uri partOfUri; 60 Uri partOfUri;
64 61
65 List<MetadataBuilder> metadata; 62 List<MetadataBuilder> metadata;
66 63
67 /// The current declaration that is being built. When we start parsing a 64 /// The current declaration that is being built. When we start parsing a
68 /// declaration (class, method, and so on), we don't have enough information 65 /// declaration (class, method, and so on), we don't have enough information
69 /// to create a builder and this object records its members and types until, 66 /// to create a builder and this object records its members and types until,
70 /// for example, [addClass] is called. 67 /// for example, [addClass] is called.
71 DeclarationBuilder<T> currentDeclaration; 68 DeclarationBuilder<T> currentDeclaration;
72 69
73 bool canAddImplementationBuilders = false; 70 bool canAddImplementationBuilders = false;
74 71
75 SourceLibraryBuilder(this.loader, Uri fileUri) 72 SourceLibraryBuilder(SourceLoader loader, Uri fileUri)
76 : fileUri = fileUri, 73 : this.fromScopes(loader, fileUri, new DeclarationBuilder<T>.library(),
77 super(fileUri) { 74 new Scope.top());
78 currentDeclaration = libraryDeclaration; 75
79 } 76 SourceLibraryBuilder.fromScopes(
77 this.loader, this.fileUri, this.libraryDeclaration, this.importScope)
78 : currentDeclaration = libraryDeclaration,
79 super(
80 fileUri, libraryDeclaration.toScope(importScope), new Scope.top());
80 81
81 Uri get uri; 82 Uri get uri;
82 83
83 bool get isPart => partOfName != null || partOfUri != null; 84 bool get isPart => partOfName != null || partOfUri != null;
84 85
85 Map<String, Builder> get members => libraryDeclaration.members;
86
87 List<T> get types => libraryDeclaration.types; 86 List<T> get types => libraryDeclaration.types;
88 87
89 T addNamedType(String name, List<T> arguments, int charOffset); 88 T addNamedType(String name, List<T> arguments, int charOffset);
90 89
91 T addMixinApplication(T supertype, List<T> mixins, int charOffset); 90 T addMixinApplication(T supertype, List<T> mixins, int charOffset);
92 91
93 T addType(T type) { 92 T addType(T type) {
94 currentDeclaration.addType(type); 93 currentDeclaration.addType(type);
95 return type; 94 return type;
96 } 95 }
97 96
98 T addVoidType(int charOffset); 97 T addVoidType(int charOffset);
99 98
100 ConstructorReferenceBuilder addConstructorReference( 99 ConstructorReferenceBuilder addConstructorReference(
101 String name, List<T> typeArguments, String suffix, int charOffset) { 100 String name, List<T> typeArguments, String suffix, int charOffset) {
102 ConstructorReferenceBuilder ref = new ConstructorReferenceBuilder( 101 ConstructorReferenceBuilder ref = new ConstructorReferenceBuilder(
103 name, typeArguments, suffix, this, charOffset); 102 name, typeArguments, suffix, this, charOffset);
104 constructorReferences.add(ref); 103 constructorReferences.add(ref);
105 return ref; 104 return ref;
106 } 105 }
107 106
108 void beginNestedDeclaration(String name, {bool hasMembers}) { 107 void beginNestedDeclaration(String name, {bool hasMembers: true}) {
109 currentDeclaration = new DeclarationBuilder( 108 currentDeclaration = currentDeclaration.createNested(name, hasMembers);
110 <String, MemberBuilder>{}, name, currentDeclaration);
111 } 109 }
112 110
113 DeclarationBuilder<T> endNestedDeclaration() { 111 DeclarationBuilder<T> endNestedDeclaration() {
114 DeclarationBuilder<T> previous = currentDeclaration; 112 DeclarationBuilder<T> previous = currentDeclaration;
115 currentDeclaration = currentDeclaration.parent; 113 currentDeclaration = currentDeclaration.parent;
116 return previous; 114 return previous;
117 } 115 }
118 116
119 Uri resolve(String path) => uri.resolve(path); 117 Uri resolve(String path) => uri.resolve(path);
120 118
(...skipping 106 matching lines...) Expand 10 before | Expand all | Expand 10 after
227 int charOpenParenOffset, 225 int charOpenParenOffset,
228 int charEndOffset, 226 int charEndOffset,
229 String nativeMethodName); 227 String nativeMethodName);
230 228
231 FormalParameterBuilder addFormalParameter(List<MetadataBuilder> metadata, 229 FormalParameterBuilder addFormalParameter(List<MetadataBuilder> metadata,
232 int modifiers, T type, String name, bool hasThis, int charOffset); 230 int modifiers, T type, String name, bool hasThis, int charOffset);
233 231
234 TypeVariableBuilder addTypeVariable(String name, T bound, int charOffset); 232 TypeVariableBuilder addTypeVariable(String name, T bound, int charOffset);
235 233
236 Builder addBuilder(String name, Builder builder, int charOffset) { 234 Builder addBuilder(String name, Builder builder, int charOffset) {
237 if (name.indexOf(".") != -1 && name.indexOf("&") == -1) {
238 addCompileTimeError(
239 charOffset,
240 "Only constructors and factories can have"
241 " names containing a period ('.'): $name");
242 }
243 // TODO(ahe): Set the parent correctly here. Could then change the 235 // TODO(ahe): Set the parent correctly here. Could then change the
244 // implementation of MemberBuilder.isTopLevel to test explicitly for a 236 // implementation of MemberBuilder.isTopLevel to test explicitly for a
245 // LibraryBuilder. 237 // LibraryBuilder.
246 if (currentDeclaration == libraryDeclaration) { 238 if (currentDeclaration == libraryDeclaration) {
247 if (builder is MemberBuilder) { 239 if (builder is MemberBuilder) {
248 builder.parent = this; 240 builder.parent = this;
249 } else if (builder is TypeDeclarationBuilder) { 241 } else if (builder is TypeDeclarationBuilder) {
250 builder.parent = this; 242 builder.parent = this;
251 } else if (builder is PrefixBuilder) { 243 } else if (builder is PrefixBuilder) {
252 assert(builder.parent == this); 244 assert(builder.parent == this);
253 } else { 245 } else {
254 return internalError("Unhandled: ${builder.runtimeType}"); 246 return internalError("Unhandled: ${builder.runtimeType}");
255 } 247 }
256 } else { 248 } else {
257 assert(currentDeclaration.parent == libraryDeclaration); 249 assert(currentDeclaration.parent == libraryDeclaration);
258 } 250 }
259 Map<String, Builder> members = currentDeclaration.members; 251 bool isConstructor = builder is ProcedureBuilder &&
252 (builder.isConstructor || builder.isFactory);
253 Map<String, Builder> members = isConstructor
254 ? currentDeclaration.constructors
255 : (builder.isSetter
256 ? currentDeclaration.setters
257 : currentDeclaration.members);
260 Builder existing = members[name]; 258 Builder existing = members[name];
261 builder.next = existing; 259 builder.next = existing;
262 if (builder is PrefixBuilder && existing is PrefixBuilder) { 260 if (builder is PrefixBuilder && existing is PrefixBuilder) {
263 assert(existing.next == null); 261 assert(existing.next == null);
264 builder.exports.forEach((String name, Builder builder) { 262 return existing
265 Builder other = existing.exports.putIfAbsent(name, () => builder); 263 ..exports.merge(builder.exports,
266 if (other != builder) { 264 (String name, Builder existing, Builder member) {
267 existing.exports[name] = 265 return buildAmbiguousBuilder(name, existing, member, charOffset);
268 buildAmbiguousBuilder(name, other, builder, charOffset); 266 });
269 }
270 });
271 return existing;
272 } else if (isDuplicatedDefinition(existing, builder)) { 267 } else if (isDuplicatedDefinition(existing, builder)) {
273 addCompileTimeError(charOffset, "Duplicated definition of '$name'."); 268 addCompileTimeError(charOffset, "Duplicated definition of '$name'.");
274 } 269 }
275 return members[name] = builder; 270 return members[name] = builder;
276 } 271 }
277 272
278 bool isDuplicatedDefinition(Builder existing, Builder other) { 273 bool isDuplicatedDefinition(Builder existing, Builder other) {
279 if (existing == null) return false; 274 if (existing == null) return false;
280 Builder next = existing.next; 275 Builder next = existing.next;
281 if (next == null) { 276 if (next == null) {
(...skipping 24 matching lines...) Expand all
306 } while (builder != null); 301 } while (builder != null);
307 }); 302 });
308 for (List list in implementationBuilders) { 303 for (List list in implementationBuilders) {
309 String name = list[0]; 304 String name = list[0];
310 Builder builder = list[1]; 305 Builder builder = list[1];
311 int charOffset = list[2]; 306 int charOffset = list[2];
312 addBuilder(name, builder, charOffset); 307 addBuilder(name, builder, charOffset);
313 buildBuilder(builder); 308 buildBuilder(builder);
314 } 309 }
315 canAddImplementationBuilders = false; 310 canAddImplementationBuilders = false;
311
312 scope.setters.forEach((String name, Builder setter) {
313 Builder member = scopeBuilder[name];
314 if (member == null || !member.isField || member.isFinal) return;
315 // TODO(ahe): charOffset is missing.
316 addCompileTimeError(
317 setter.charOffset, "Conflicts with member '${name}'.");
318 addCompileTimeError(
319 member.charOffset, "Conflicts with setter '${name}'.");
320 });
321
316 return null; 322 return null;
317 } 323 }
318 324
319 /// Used to add implementation builder during the call to [build] above. 325 /// Used to add implementation builder during the call to [build] above.
320 /// Currently, only anonymous mixins are using implementation builders (see 326 /// Currently, only anonymous mixins are using implementation builders (see
321 /// [KernelMixinApplicationBuilder] 327 /// [KernelMixinApplicationBuilder]
322 /// (../kernel/kernel_mixin_application_builder.dart)). 328 /// (../kernel/kernel_mixin_application_builder.dart)).
323 void addImplementationBuilder(String name, Builder builder, int charOffset) { 329 void addImplementationBuilder(String name, Builder builder, int charOffset) {
324 assert(canAddImplementationBuilders, "$uri"); 330 assert(canAddImplementationBuilders, "$uri");
325 implementationBuilders.add([name, builder, charOffset]); 331 implementationBuilders.add([name, builder, charOffset]);
(...skipping 48 matching lines...) Expand 10 before | Expand all | Expand 10 after
374 part.forEach((String name, Builder builder) { 380 part.forEach((String name, Builder builder) {
375 if (builder.next != null) { 381 if (builder.next != null) {
376 assert(builder.next.next == null); 382 assert(builder.next.next == null);
377 addBuilder(name, builder.next, builder.next.charOffset); 383 addBuilder(name, builder.next, builder.next.charOffset);
378 } 384 }
379 addBuilder(name, builder, builder.charOffset); 385 addBuilder(name, builder, builder.charOffset);
380 }); 386 });
381 types.addAll(part.types); 387 types.addAll(part.types);
382 constructorReferences.addAll(part.constructorReferences); 388 constructorReferences.addAll(part.constructorReferences);
383 part.partOfLibrary = this; 389 part.partOfLibrary = this;
390 part.scope.becomePartOf(scope);
384 // TODO(ahe): Include metadata from part? 391 // TODO(ahe): Include metadata from part?
385 } 392 }
386 393
387 void buildInitialScopes() { 394 void buildInitialScopes() {
388 forEach(addToExportScope); 395 forEach(addToExportScope);
389 forEach((String name, Builder member) {
390 addToScope(name, member, member.charOffset, false);
391 });
392 } 396 }
393 397
394 void addImportsToScope() { 398 void addImportsToScope() {
395 bool explicitCoreImport = this == loader.coreLibrary; 399 bool explicitCoreImport = this == loader.coreLibrary;
396 for (Import import in imports) { 400 for (Import import in imports) {
397 if (import.imported == loader.coreLibrary) { 401 if (import.imported == loader.coreLibrary) {
398 explicitCoreImport = true; 402 explicitCoreImport = true;
399 } 403 }
400 import.finalizeImports(this); 404 import.finalizeImports(this);
401 } 405 }
402 if (!explicitCoreImport) { 406 if (!explicitCoreImport) {
403 loader.coreLibrary.exports.forEach((String name, Builder member) { 407 loader.coreLibrary.exports.forEach((String name, Builder member) {
404 addToScope(name, member, -1, true); 408 addToScope(name, member, -1, true);
405 }); 409 });
406 } 410 }
407 } 411 }
408 412
409 @override 413 @override
410 void addToScope(String name, Builder member, int charOffset, bool isImport) { 414 void addToScope(String name, Builder member, int charOffset, bool isImport) {
411 Builder existing = scope.lookup(name, member.charOffset, fileUri); 415 Map<String, Builder> map =
416 member.isSetter ? importScope.setters : importScope.local;
417 Builder existing = map[name];
412 if (existing != null) { 418 if (existing != null) {
413 if (existing != member) { 419 if (existing != member) {
414 scope.local[name] = buildAmbiguousBuilder( 420 map[name] = buildAmbiguousBuilder(name, existing, member, charOffset,
415 name, existing, member, charOffset,
416 isImport: isImport); 421 isImport: isImport);
417 } 422 }
418 } else { 423 } else {
419 scope.local[name] = member; 424 map[name] = member;
420 } 425 }
421 } 426 }
422 427
423 /// Returns true if the export scope was modified. 428 /// Returns true if the export scope was modified.
424 bool addToExportScope(String name, Builder member) { 429 bool addToExportScope(String name, Builder member) {
425 if (name.startsWith("_")) return false; 430 if (name.startsWith("_")) return false;
426 if (member is PrefixBuilder) return false; 431 if (member is PrefixBuilder) return false;
427 Builder existing = exports[name]; 432 Map<String, Builder> map =
433 member.isSetter ? exports.setters : exports.local;
434 Builder existing = map[name];
428 if (existing == member) return false; 435 if (existing == member) return false;
429 if (existing != null) { 436 if (existing != null) {
430 Builder result = 437 Builder result =
431 buildAmbiguousBuilder(name, existing, member, -1, isExport: true); 438 buildAmbiguousBuilder(name, existing, member, -1, isExport: true);
432 exports[name] = result; 439 map[name] = result;
433 return result != existing; 440 return result != existing;
434 } else { 441 } else {
435 exports[name] = member; 442 map[name] = member;
436 } 443 }
437 return true; 444 return true;
438 } 445 }
439 446
440 int resolveTypes(_) { 447 int resolveTypes(_) {
441 int typeCount = types.length; 448 int typeCount = types.length;
442 for (T t in types) { 449 for (T t in types) {
443 t.resolveIn(scope); 450 t.resolveIn(scope);
444 } 451 }
445 forEach((String name, Builder member) { 452 forEach((String name, Builder member) {
(...skipping 18 matching lines...) Expand all
464 String get fullNameForErrors => name ?? "<library '$relativeFileUri'>"; 471 String get fullNameForErrors => name ?? "<library '$relativeFileUri'>";
465 } 472 }
466 473
467 /// Unlike [Scope], this scope is used during construction of builders to 474 /// Unlike [Scope], this scope is used during construction of builders to
468 /// ensure types and members are added to and resolved in the correct location. 475 /// ensure types and members are added to and resolved in the correct location.
469 class DeclarationBuilder<T extends TypeBuilder> { 476 class DeclarationBuilder<T extends TypeBuilder> {
470 final DeclarationBuilder<T> parent; 477 final DeclarationBuilder<T> parent;
471 478
472 final Map<String, Builder> members; 479 final Map<String, Builder> members;
473 480
481 final Map<String, Builder> constructors;
482
483 final Map<String, Builder> setters;
484
474 final List<T> types = <T>[]; 485 final List<T> types = <T>[];
475 486
476 final String name; 487 final String name;
477 488
478 final Map<ProcedureBuilder, DeclarationBuilder<T>> factoryDeclarations = 489 final Map<ProcedureBuilder, DeclarationBuilder<T>> factoryDeclarations;
479 <ProcedureBuilder, DeclarationBuilder<T>>{};
480 490
481 DeclarationBuilder(this.members, this.name, [this.parent]); 491 DeclarationBuilder(this.members, this.setters, this.constructors,
492 this.factoryDeclarations, this.name, this.parent);
482 493
483 void addMember(String name, MemberBuilder builder) { 494 DeclarationBuilder.library()
484 if (members == null) { 495 : this(<String, Builder>{}, <String, Builder>{}, null, null, null, null);
485 parent.addMember(name, builder);
486 } else {
487 members[name] = builder;
488 }
489 }
490 496
491 MemberBuilder lookupMember(String name) { 497 DeclarationBuilder createNested(String name, bool hasMembers) {
492 return members == null ? parent.lookupMember(name) : members[name]; 498 return new DeclarationBuilder<T>(
499 hasMembers ? <String, MemberBuilder>{} : null,
500 hasMembers ? <String, MemberBuilder>{} : null,
501 hasMembers ? <String, MemberBuilder>{} : null,
502 <ProcedureBuilder, DeclarationBuilder<T>>{},
503 name,
504 this);
493 } 505 }
494 506
495 void addType(T type) { 507 void addType(T type) {
496 types.add(type); 508 types.add(type);
497 } 509 }
498 510
499 /// Resolves type variables in [types] and propagate other types to [parent]. 511 /// Resolves type variables in [types] and propagate other types to [parent].
500 void resolveTypes( 512 void resolveTypes(
501 List<TypeVariableBuilder> typeVariables, SourceLibraryBuilder library) { 513 List<TypeVariableBuilder> typeVariables, SourceLibraryBuilder library) {
502 // TODO(ahe): The input to this method, [typeVariables], shouldn't be just 514 // TODO(ahe): The input to this method, [typeVariables], shouldn't be just
(...skipping 36 matching lines...) Expand 10 before | Expand all | Expand 10 after
539 types.clear(); 551 types.clear();
540 } 552 }
541 553
542 /// Called to register [procedure] as a factory whose types are collected in 554 /// Called to register [procedure] as a factory whose types are collected in
543 /// [factoryDeclaration]. Later, once the class has been built, we can 555 /// [factoryDeclaration]. Later, once the class has been built, we can
544 /// synthesize type variables on the factory matching the class'. 556 /// synthesize type variables on the factory matching the class'.
545 void addFactoryDeclaration( 557 void addFactoryDeclaration(
546 ProcedureBuilder procedure, DeclarationBuilder<T> factoryDeclaration) { 558 ProcedureBuilder procedure, DeclarationBuilder<T> factoryDeclaration) {
547 factoryDeclarations[procedure] = factoryDeclaration; 559 factoryDeclarations[procedure] = factoryDeclaration;
548 } 560 }
561
562 Scope toScope(Scope parent) {
563 return new Scope(members, setters, parent, isModifiable: false);
564 }
549 } 565 }
OLDNEW
« no previous file with comments | « pkg/front_end/lib/src/fasta/source/source_class_builder.dart ('k') | samples/samples.status » ('j') | no next file with comments »

Powered by Google App Engine
This is Rietveld 408576698