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

Side by Side Diff: pkg/analyzer/lib/src/dart/resolver/scope.dart

Issue 2314963002: Remove the final error being generated in a scope (Closed)
Patch Set: Created 4 years, 3 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
OLDNEW
1 // Copyright (c) 2014, the Dart project authors. Please see the AUTHORS file 1 // Copyright (c) 2014, 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 analyzer.src.dart.resolver.scope; 5 library analyzer.src.dart.resolver.scope;
6 6
7 import 'dart:collection'; 7 import 'dart:collection';
8 8
9 import 'package:analyzer/dart/ast/ast.dart'; 9 import 'package:analyzer/dart/ast/ast.dart';
10 import 'package:analyzer/dart/element/element.dart'; 10 import 'package:analyzer/dart/element/element.dart';
(...skipping 110 matching lines...) Expand 10 before | Expand all | Expand 10 after
121 * The scope in which this scope is lexically enclosed. 121 * The scope in which this scope is lexically enclosed.
122 */ 122 */
123 @override 123 @override
124 final Scope enclosingScope; 124 final Scope enclosingScope;
125 125
126 /** 126 /**
127 * Initialize a newly created scope, enclosed within the [enclosingScope]. 127 * Initialize a newly created scope, enclosed within the [enclosingScope].
128 */ 128 */
129 EnclosedScope(this.enclosingScope); 129 EnclosedScope(this.enclosingScope);
130 130
131 @deprecated
131 @override 132 @override
132 AnalysisErrorListener get errorListener => enclosingScope.errorListener; 133 AnalysisErrorListener get errorListener => enclosingScope.errorListener;
133 134
134 @override 135 @override
135 Element internalLookup( 136 Element internalLookup(
136 Identifier identifier, String name, LibraryElement referencingLibrary) { 137 Identifier identifier, String name, LibraryElement referencingLibrary) {
137 Element element = localLookup(name, referencingLibrary); 138 Element element = localLookup(name, referencingLibrary);
138 if (element != null) { 139 if (element != null) {
139 return element; 140 return element;
140 } 141 }
141 // Check enclosing scope. 142 // Check enclosing scope.
142 return enclosingScope.internalLookup(identifier, name, referencingLibrary); 143 return enclosingScope.internalLookup(identifier, name, referencingLibrary);
143 } 144 }
144 145
145 @override 146 @override
146 Element _internalLookupPrefixed(Identifier identifier, String prefix, 147 Element _internalLookupPrefixed(PrefixedIdentifier identifier, String prefix,
147 String name, LibraryElement referencingLibrary) { 148 String name, LibraryElement referencingLibrary) {
148 return enclosingScope._internalLookupPrefixed( 149 return enclosingScope._internalLookupPrefixed(
149 identifier, prefix, name, referencingLibrary); 150 identifier, prefix, name, referencingLibrary);
150 } 151 }
151 } 152 }
152 153
153 /** 154 /**
154 * The scope defined by a function. 155 * The scope defined by a function.
155 */ 156 */
156 class FunctionScope extends EnclosedScope { 157 class FunctionScope extends EnclosedScope {
(...skipping 188 matching lines...) Expand 10 before | Expand all | Expand 10 after
345 } 346 }
346 return _outerScope?.lookup(targetLabel); 347 return _outerScope?.lookup(targetLabel);
347 } 348 }
348 } 349 }
349 350
350 /** 351 /**
351 * The scope containing all of the names available from imported libraries. 352 * The scope containing all of the names available from imported libraries.
352 */ 353 */
353 class LibraryImportScope extends Scope { 354 class LibraryImportScope extends Scope {
354 /** 355 /**
356 * The name of the property containing a list of the elements from the SDK
357 * that conflict with the single name imported from non-SDK libraries. The
358 * value of the property is always of type `List<Element>`.
359 */
360 static const String conflictingSdkElements = 'conflictingSdkElements';
361
362 /**
355 * The element representing the library in which this scope is enclosed. 363 * The element representing the library in which this scope is enclosed.
356 */ 364 */
357 final LibraryElement _definingLibrary; 365 final LibraryElement _definingLibrary;
358 366
359 /** 367 @deprecated
360 * The listener that is to be informed when an error is encountered.
361 */
362 @override 368 @override
363 final AnalysisErrorListener errorListener; 369 final AnalysisErrorListener errorListener;
364 370
365 /** 371 /**
366 * A list of the namespaces representing the names that are available in this scope from imported 372 * A list of the namespaces representing the names that are available in this scope from imported
367 * libraries. 373 * libraries.
368 */ 374 */
369 List<Namespace> _importedNamespaces; 375 List<Namespace> _importedNamespaces;
370 376
371 /** 377 /**
372 * A table mapping prefixes that have been referenced to a map from the names 378 * A table mapping prefixes that have been referenced to a map from the names
373 * that have been referenced to the element associated with the prefixed name. 379 * that have been referenced to the element associated with the prefixed name.
374 */ 380 */
375 Map<String, Map<String, Element>> _definedPrefixedNames; 381 Map<String, Map<String, Element>> _definedPrefixedNames;
376 382
377 /** 383 /**
378 * Initialize a newly created scope representing the names imported into the 384 * Initialize a newly created scope representing the names imported into the
379 * [_definingLibrary]. The [errorListener] is the listener that is to be 385 * [_definingLibrary]. The [errorListener] is no longer used and should be
380 * informed when an error is encountered. 386 * omitted.
381 */ 387 */
382 LibraryImportScope(this._definingLibrary, this.errorListener) { 388 LibraryImportScope(this._definingLibrary, [this.errorListener]) {
383 _createImportedNamespaces(); 389 _createImportedNamespaces();
384 } 390 }
385 391
386 @override 392 @override
387 void define(Element element) { 393 void define(Element element) {
388 if (!Scope.isPrivateName(element.displayName)) { 394 if (!Scope.isPrivateName(element.displayName)) {
389 super.define(element); 395 super.define(element);
390 } 396 }
391 } 397 }
392 398
393 @override 399 @override
394 Source getSource(AstNode node) { 400 Source getSource(AstNode node) {
395 Source source = super.getSource(node); 401 Source source = super.getSource(node);
396 if (source == null) { 402 if (source == null) {
397 source = _definingLibrary.definingCompilationUnit.source; 403 source = _definingLibrary.definingCompilationUnit.source;
398 } 404 }
399 return source; 405 return source;
400 } 406 }
401 407
402 @override 408 @override
403 Element internalLookup( 409 Element internalLookup(
404 Identifier identifier, String name, LibraryElement referencingLibrary) { 410 Identifier identifier, String name, LibraryElement referencingLibrary) {
405 Element foundElement = localLookup(name, referencingLibrary); 411 Element element = localLookup(name, referencingLibrary);
406 if (foundElement != null) { 412 if (element != null) {
407 return foundElement; 413 return element;
408 } 414 }
409 for (int i = 0; i < _importedNamespaces.length; i++) { 415 element = _lookupInImportedNamespaces(
410 Namespace nameSpace = _importedNamespaces[i]; 416 identifier, (Namespace namespace) => namespace.get(name));
411 Element element = nameSpace.get(name); 417 if (element != null) {
412 if (element != null) { 418 defineNameWithoutChecking(name, element);
413 if (foundElement == null) {
414 foundElement = element;
415 } else if (!identical(foundElement, element)) {
416 foundElement = MultiplyDefinedElementImpl.fromElements(
417 _definingLibrary.context, foundElement, element);
418 }
419 }
420 } 419 }
421 Element element = foundElement; 420 return element;
422 if (element is MultiplyDefinedElementImpl) {
423 foundElement = _removeSdkElements(identifier, name, element);
424 }
425 if (foundElement is MultiplyDefinedElementImpl) {
426 String foundEltName = foundElement.displayName;
427 List<Element> conflictingMembers = foundElement.conflictingElements;
428 int count = conflictingMembers.length;
429 List<String> libraryNames = new List<String>(count);
430 for (int i = 0; i < count; i++) {
431 libraryNames[i] = _getLibraryName(conflictingMembers[i]);
432 }
433 libraryNames.sort();
434 errorListener.onError(new AnalysisError(
435 getSource(identifier),
436 identifier.offset,
437 identifier.length,
438 StaticWarningCode.AMBIGUOUS_IMPORT, [
439 foundEltName,
440 StringUtilities.printListOfQuotedNames(libraryNames)
441 ]));
442 return foundElement;
443 }
444 if (foundElement != null) {
445 defineNameWithoutChecking(name, foundElement);
446 }
447 return foundElement;
448 } 421 }
449 422
450 @override 423 @override
451 bool shouldIgnoreUndefined(Identifier node) { 424 bool shouldIgnoreUndefined(Identifier node) {
452 Iterable<NamespaceCombinator> getShowCombinators( 425 Iterable<NamespaceCombinator> getShowCombinators(
453 ImportElement importElement) => 426 ImportElement importElement) =>
454 importElement.combinators.where((NamespaceCombinator combinator) => 427 importElement.combinators.where((NamespaceCombinator combinator) =>
455 combinator is ShowElementCombinator); 428 combinator is ShowElementCombinator);
456 if (node is PrefixedIdentifier) { 429 if (node is PrefixedIdentifier) {
457 String prefix = node.prefix.name; 430 String prefix = node.prefix.name;
(...skipping 57 matching lines...) Expand 10 before | Expand all | Expand 10 after
515 * hiding. 488 * hiding.
516 */ 489 */
517 void _definePrefixedNameWithoutChecking( 490 void _definePrefixedNameWithoutChecking(
518 String prefix, String name, Element element) { 491 String prefix, String name, Element element) {
519 _definedPrefixedNames ??= new HashMap<String, Map<String, Element>>(); 492 _definedPrefixedNames ??= new HashMap<String, Map<String, Element>>();
520 Map<String, Element> unprefixedNames = _definedPrefixedNames.putIfAbsent( 493 Map<String, Element> unprefixedNames = _definedPrefixedNames.putIfAbsent(
521 prefix, () => new HashMap<String, Element>()); 494 prefix, () => new HashMap<String, Element>());
522 unprefixedNames[name] = element; 495 unprefixedNames[name] = element;
523 } 496 }
524 497
525 /** 498 @override
526 * Return the name of the library that defines given [element]. 499 Element _internalLookupPrefixed(PrefixedIdentifier identifier, String prefix,
527 */ 500 String name, LibraryElement referencingLibrary) {
528 String _getLibraryName(Element element) { 501 Element element = _localPrefixedLookup(prefix, name);
529 if (element == null) { 502 if (element != null) {
530 return StringUtilities.EMPTY; 503 return element;
531 } 504 }
532 LibraryElement library = element.library; 505 element = _lookupInImportedNamespaces(identifier.identifier,
533 if (library == null) { 506 (Namespace namespace) => namespace.getPrefixed(prefix, name));
534 return StringUtilities.EMPTY; 507 if (element != null) {
508 _definePrefixedNameWithoutChecking(prefix, name, element);
535 } 509 }
536 List<ImportElement> imports = _definingLibrary.imports; 510 return element;
537 int count = imports.length;
538 for (int i = 0; i < count; i++) {
539 if (identical(imports[i].importedLibrary, library)) {
540 return library.definingCompilationUnit.displayName;
541 }
542 }
543 List<String> indirectSources = new List<String>();
544 for (int i = 0; i < count; i++) {
545 LibraryElement importedLibrary = imports[i].importedLibrary;
546 if (importedLibrary != null) {
547 for (LibraryElement exportedLibrary
548 in importedLibrary.exportedLibraries) {
549 if (identical(exportedLibrary, library)) {
550 indirectSources
551 .add(importedLibrary.definingCompilationUnit.displayName);
552 }
553 }
554 }
555 }
556 int indirectCount = indirectSources.length;
557 StringBuffer buffer = new StringBuffer();
558 buffer.write(library.definingCompilationUnit.displayName);
559 if (indirectCount > 0) {
560 buffer.write(" (via ");
561 if (indirectCount > 1) {
562 indirectSources.sort();
563 buffer.write(StringUtilities.printListOfQuotedNames(indirectSources));
564 } else {
565 buffer.write(indirectSources[0]);
566 }
567 buffer.write(")");
568 }
569 return buffer.toString();
570 }
571
572 @override
573 Element _internalLookupPrefixed(Identifier identifier, String prefix,
574 String name, LibraryElement referencingLibrary) {
575 Element foundElement = _localPrefixedLookup(prefix, name);
576 if (foundElement != null) {
577 return foundElement;
578 }
579 for (int i = 0; i < _importedNamespaces.length; i++) {
580 Element element = _importedNamespaces[i].getPrefixed(prefix, name);
581 if (element != null) {
582 if (foundElement == null) {
583 foundElement = element;
584 } else if (!identical(foundElement, element)) {
585 foundElement = MultiplyDefinedElementImpl.fromElements(
586 _definingLibrary.context, foundElement, element);
587 }
588 }
589 }
590 Element element = foundElement;
591 if (element is MultiplyDefinedElementImpl) {
592 foundElement = _removeSdkElements(identifier, name, element);
593 }
594 if (foundElement is MultiplyDefinedElementImpl) {
595 String foundEltName = foundElement.displayName;
596 List<Element> conflictingMembers = foundElement.conflictingElements;
597 int count = conflictingMembers.length;
598 List<String> libraryNames = new List<String>(count);
599 for (int i = 0; i < count; i++) {
600 libraryNames[i] = _getLibraryName(conflictingMembers[i]);
601 }
602 libraryNames.sort();
603 errorListener.onError(new AnalysisError(
604 getSource(identifier),
605 identifier.offset,
606 identifier.length,
607 StaticWarningCode.AMBIGUOUS_IMPORT, [
608 foundEltName,
609 StringUtilities.printListOfQuotedNames(libraryNames)
610 ]));
611 return foundElement;
612 }
613 if (foundElement != null) {
614 _definePrefixedNameWithoutChecking(prefix, name, foundElement);
615 }
616 return foundElement;
617 } 511 }
618 512
619 /** 513 /**
620 * Return the element with which the given [prefix] and [name] are associated, 514 * Return the element with which the given [prefix] and [name] are associated,
621 * or `null` if the name is not defined within this scope. 515 * or `null` if the name is not defined within this scope.
622 */ 516 */
623 Element _localPrefixedLookup(String prefix, String name) { 517 Element _localPrefixedLookup(String prefix, String name) {
624 if (_definedPrefixedNames != null) { 518 if (_definedPrefixedNames != null) {
625 Map<String, Element> unprefixedNames = _definedPrefixedNames[prefix]; 519 Map<String, Element> unprefixedNames = _definedPrefixedNames[prefix];
626 if (unprefixedNames != null) { 520 if (unprefixedNames != null) {
627 return unprefixedNames[name]; 521 return unprefixedNames[name];
628 } 522 }
629 } 523 }
630 return null; 524 return null;
631 } 525 }
632 526
633 /** 527 Element _lookupInImportedNamespaces(
634 * Given a collection of elements (captured by the [foundElement]) that the 528 Identifier identifier, Element lookup(Namespace namespace)) {
635 * [identifier] (with the given [name]) resolved to, remove from the list all 529 Set<Element> sdkElements = new HashSet<Element>.identity();
636 * of the names defined in the SDK and return the element(s) that remain. 530 Set<Element> nonSdkElements = new HashSet<Element>.identity();
637 */ 531 for (int i = 0; i < _importedNamespaces.length; i++) {
638 Element _removeSdkElements(Identifier identifier, String name, 532 Element element = lookup(_importedNamespaces[i]);
639 MultiplyDefinedElementImpl foundElement) { 533 if (element != null) {
640 List<Element> conflictingElements = foundElement.conflictingElements; 534 if (element.library.isInSdk) {
641 List<Element> nonSdkElements = new List<Element>(); 535 sdkElements.add(element);
642 Element sdkElement = null; 536 } else {
643 for (Element member in conflictingElements) { 537 nonSdkElements.add(element);
644 if (member.library.isInSdk) { 538 }
645 sdkElement = member;
646 } else {
647 nonSdkElements.add(member);
648 } 539 }
649 } 540 }
650 if (sdkElement != null && nonSdkElements.length > 0) { 541 int nonSdkCount = nonSdkElements.length;
651 String sdkLibName = _getLibraryName(sdkElement); 542 int sdkCount = sdkElements.length;
652 String otherLibName = _getLibraryName(nonSdkElements[0]); 543 if (nonSdkCount == 0) {
653 errorListener.onError(new AnalysisError( 544 if (sdkCount == 0) {
654 getSource(identifier), 545 return null;
655 identifier.offset, 546 } else if (sdkCount == 1) {
656 identifier.length, 547 return sdkElements.first;
657 StaticWarningCode.CONFLICTING_DART_IMPORT, 548 }
658 [name, sdkLibName, otherLibName]));
659 } 549 }
660 if (nonSdkElements.length == conflictingElements.length) { 550 if (nonSdkCount == 1) {
661 // None of the members were removed 551 if (sdkCount > 0) {
662 return foundElement; 552 identifier.setProperty(
663 } else if (nonSdkElements.length == 1) { 553 conflictingSdkElements, sdkElements.toList(growable: false));
664 // All but one member was removed 554 }
665 return nonSdkElements[0]; 555 return nonSdkElements.first;
666 } else if (nonSdkElements.length == 0) {
667 // All members were removed
668 AnalysisEngine.instance.logger
669 .logInformation("Multiply defined SDK element: $foundElement");
670 return foundElement;
671 } 556 }
672 return new MultiplyDefinedElementImpl( 557 return new MultiplyDefinedElementImpl(
673 _definingLibrary.context, nonSdkElements); 558 _definingLibrary.context,
559 sdkElements.toList(growable: false),
560 nonSdkElements.toList(growable: false));
674 } 561 }
675 } 562 }
676 563
677 /** 564 /**
678 * A scope containing all of the names defined in a given library. 565 * A scope containing all of the names defined in a given library.
679 */ 566 */
680 class LibraryScope extends EnclosedScope { 567 class LibraryScope extends EnclosedScope {
681 /** 568 /**
682 * Initialize a newly created scope representing the names defined in the 569 * Initialize a newly created scope representing the names defined in the
683 * [definingLibrary]. The [errorListener] is the listener that is to be 570 * [definingLibrary]. The [errorListener] is no longer used and should be
684 * informed when an error is encountered 571 * omitted.
685 */ 572 */
686 LibraryScope( 573 LibraryScope(LibraryElement definingLibrary,
687 LibraryElement definingLibrary, AnalysisErrorListener errorListener) 574 [@deprecated AnalysisErrorListener errorListener])
688 : super(new LibraryImportScope(definingLibrary, errorListener)) { 575 : super(new LibraryImportScope(definingLibrary, errorListener)) {
689 _defineTopLevelNames(definingLibrary); 576 _defineTopLevelNames(definingLibrary);
690 } 577 }
691 578
692 @override 579 @override
693 AnalysisError getErrorForDuplicate(Element existing, Element duplicate) { 580 AnalysisError getErrorForDuplicate(Element existing, Element duplicate) {
694 if (existing is PrefixElement) { 581 if (existing is PrefixElement) {
695 // TODO(scheglov) consider providing actual 'nameOffset' from the 582 // TODO(scheglov) consider providing actual 'nameOffset' from the
696 // synthetic accessor 583 // synthetic accessor
697 int offset = duplicate.nameOffset; 584 int offset = duplicate.nameOffset;
(...skipping 398 matching lines...) Expand 10 before | Expand all | Expand 10 after
1096 HashMap<String, Element> _definedNames = null; 983 HashMap<String, Element> _definedNames = null;
1097 984
1098 /** 985 /**
1099 * Return the scope in which this scope is lexically enclosed. 986 * Return the scope in which this scope is lexically enclosed.
1100 */ 987 */
1101 Scope get enclosingScope => null; 988 Scope get enclosingScope => null;
1102 989
1103 /** 990 /**
1104 * Return the listener that is to be informed when an error is encountered. 991 * Return the listener that is to be informed when an error is encountered.
1105 */ 992 */
993 @deprecated
1106 AnalysisErrorListener get errorListener; 994 AnalysisErrorListener get errorListener;
1107 995
1108 /** 996 /**
1109 * Add the given [element] to this scope. If there is already an element with 997 * Add the given [element] to this scope. If there is already an element with
1110 * the given name defined in this scope, then an error will be generated and 998 * the given name defined in this scope, then an error will be generated and
1111 * the original element will continue to be mapped to the name. If there is an 999 * the original element will continue to be mapped to the name. If there is an
1112 * element with the given name in an enclosing scope, then a warning will be 1000 * element with the given name in an enclosing scope, then a warning will be
1113 * generated but the given element will hide the inherited element. 1001 * generated but the given element will hide the inherited element.
1114 */ 1002 */
1115 void define(Element element) { 1003 void define(Element element) {
(...skipping 122 matching lines...) Expand 10 before | Expand all | Expand 10 after
1238 } 1126 }
1239 1127
1240 /** 1128 /**
1241 * Return the element with which the given [prefix] and [name] are associated, 1129 * Return the element with which the given [prefix] and [name] are associated,
1242 * or `null` if the name is not defined within this scope. The [identifier] is 1130 * or `null` if the name is not defined within this scope. The [identifier] is
1243 * the identifier node to lookup element for, used to report correct kind of a 1131 * the identifier node to lookup element for, used to report correct kind of a
1244 * problem and associate problem with. The [referencingLibrary] is the library 1132 * problem and associate problem with. The [referencingLibrary] is the library
1245 * that contains the reference to the name, used to implement library-level 1133 * that contains the reference to the name, used to implement library-level
1246 * privacy. 1134 * privacy.
1247 */ 1135 */
1248 Element _internalLookupPrefixed(Identifier identifier, String prefix, 1136 Element _internalLookupPrefixed(PrefixedIdentifier identifier, String prefix,
1249 String name, LibraryElement referencingLibrary); 1137 String name, LibraryElement referencingLibrary);
1250 1138
1251 /** 1139 /**
1252 * Return `true` if the given [name] is a library-private name. 1140 * Return `true` if the given [name] is a library-private name.
1253 */ 1141 */
1254 static bool isPrivateName(String name) => 1142 static bool isPrivateName(String name) =>
1255 name != null && StringUtilities.startsWithChar(name, PRIVATE_NAME_PREFIX); 1143 name != null && StringUtilities.startsWithChar(name, PRIVATE_NAME_PREFIX);
1256 } 1144 }
1257 1145
1258 /** 1146 /**
(...skipping 14 matching lines...) Expand all
1273 1161
1274 /** 1162 /**
1275 * Define the type parameters declared by the [classElement]. 1163 * Define the type parameters declared by the [classElement].
1276 */ 1164 */
1277 void _defineTypeParameters(ClassElement classElement) { 1165 void _defineTypeParameters(ClassElement classElement) {
1278 for (TypeParameterElement typeParameter in classElement.typeParameters) { 1166 for (TypeParameterElement typeParameter in classElement.typeParameters) {
1279 define(typeParameter); 1167 define(typeParameter);
1280 } 1168 }
1281 } 1169 }
1282 } 1170 }
OLDNEW
« no previous file with comments | « pkg/analyzer/lib/src/dart/element/element.dart ('k') | pkg/analyzer/lib/src/generated/element_resolver.dart » ('j') | no next file with comments »

Powered by Google App Engine
This is Rietveld 408576698