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

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

Issue 1916223004: Stop concatenating prefixes and identifiers when performing lookup (issue 26069) (Closed) Base URL: https://github.com/dart-lang/sdk.git@master
Patch Set: Clean up Created 4 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
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 getSource(identifier), 121 getSource(identifier),
122 identifier.offset, 122 identifier.offset,
123 identifier.length, 123 identifier.length,
124 CompileTimeErrorCode.REFERENCED_BEFORE_DECLARATION, [])); 124 CompileTimeErrorCode.REFERENCED_BEFORE_DECLARATION, []));
125 return hiddenElement; 125 return hiddenElement;
126 } 126 }
127 } 127 }
128 // Check enclosing scope. 128 // Check enclosing scope.
129 return enclosingScope.internalLookup(identifier, name, referencingLibrary); 129 return enclosingScope.internalLookup(identifier, name, referencingLibrary);
130 } 130 }
131
132 @override
133 Element _internalLookupPrefixed(Identifier identifier, String prefix,
134 String name, LibraryElement referencingLibrary) {
135 return enclosingScope._internalLookupPrefixed(
136 identifier, prefix, name, referencingLibrary);
137 }
131 } 138 }
132 139
133 /** 140 /**
134 * The scope defined by a function. 141 * The scope defined by a function.
135 */ 142 */
136 class FunctionScope extends EnclosedScope { 143 class FunctionScope extends EnclosedScope {
137 /** 144 /**
138 * The element representing the function that defines this scope. 145 * The element representing the function that defines this scope.
139 */ 146 */
140 final ExecutableElement _functionElement; 147 final ExecutableElement _functionElement;
(...skipping 199 matching lines...) Expand 10 before | Expand all | Expand 10 after
340 @override 347 @override
341 final AnalysisErrorListener errorListener; 348 final AnalysisErrorListener errorListener;
342 349
343 /** 350 /**
344 * A list of the namespaces representing the names that are available in this scope from imported 351 * A list of the namespaces representing the names that are available in this scope from imported
345 * libraries. 352 * libraries.
346 */ 353 */
347 List<Namespace> _importedNamespaces; 354 List<Namespace> _importedNamespaces;
348 355
349 /** 356 /**
357 * A table mapping prefixes that have been referenced to a map from the names
358 * that have been referenced to the element associated with the prefixed name.
359 */
360 Map<String, Map<String, Element>> _definedPrefixedNames;
361
362 /**
350 * Initialize a newly created scope representing the names imported into the 363 * Initialize a newly created scope representing the names imported into the
351 * [_definingLibrary]. The [errorListener] is the listener that is to be 364 * [_definingLibrary]. The [errorListener] is the listener that is to be
352 * informed when an error is encountered. 365 * informed when an error is encountered.
353 */ 366 */
354 LibraryImportScope(this._definingLibrary, this.errorListener) { 367 LibraryImportScope(this._definingLibrary, this.errorListener) {
355 _createImportedNamespaces(); 368 _createImportedNamespaces();
356 } 369 }
357 370
358 @override 371 @override
359 void define(Element element) { 372 void define(Element element) {
(...skipping 69 matching lines...) Expand 10 before | Expand all | Expand 10 after
429 List<ImportElement> imports = _definingLibrary.imports; 442 List<ImportElement> imports = _definingLibrary.imports;
430 int count = imports.length; 443 int count = imports.length;
431 _importedNamespaces = new List<Namespace>(count); 444 _importedNamespaces = new List<Namespace>(count);
432 for (int i = 0; i < count; i++) { 445 for (int i = 0; i < count; i++) {
433 _importedNamespaces[i] = 446 _importedNamespaces[i] =
434 builder.createImportNamespaceForDirective(imports[i]); 447 builder.createImportNamespaceForDirective(imports[i]);
435 } 448 }
436 } 449 }
437 450
438 /** 451 /**
452 * Add the given [element] to this scope without checking for duplication or
453 * hiding.
454 */
455 void _definePrefixedNameWithoutChecking(
456 String prefix, String name, Element element) {
457 _definedPrefixedNames ??= new HashMap<String, Map<String, Element>>();
458 Map<String, Element> unprefixedNames = _definedPrefixedNames.putIfAbsent(
459 prefix, () => new HashMap<String, Element>());
460 unprefixedNames[name] = element;
461 }
462
463 /**
439 * Return the name of the library that defines given [element]. 464 * Return the name of the library that defines given [element].
440 */ 465 */
441 String _getLibraryName(Element element) { 466 String _getLibraryName(Element element) {
442 if (element == null) { 467 if (element == null) {
443 return StringUtilities.EMPTY; 468 return StringUtilities.EMPTY;
444 } 469 }
445 LibraryElement library = element.library; 470 LibraryElement library = element.library;
446 if (library == null) { 471 if (library == null) {
447 return StringUtilities.EMPTY; 472 return StringUtilities.EMPTY;
448 } 473 }
(...skipping 26 matching lines...) Expand all
475 indirectSources.sort(); 500 indirectSources.sort();
476 buffer.write(StringUtilities.printListOfQuotedNames(indirectSources)); 501 buffer.write(StringUtilities.printListOfQuotedNames(indirectSources));
477 } else { 502 } else {
478 buffer.write(indirectSources[0]); 503 buffer.write(indirectSources[0]);
479 } 504 }
480 buffer.write(")"); 505 buffer.write(")");
481 } 506 }
482 return buffer.toString(); 507 return buffer.toString();
483 } 508 }
484 509
510 @override
511 Element _internalLookupPrefixed(Identifier identifier, String prefix,
512 String name, LibraryElement referencingLibrary) {
513 Element foundElement = _localPrefixedLookup(prefix, name);
514 if (foundElement != null) {
515 return foundElement;
516 }
517 for (int i = 0; i < _importedNamespaces.length; i++) {
518 Namespace nameSpace = _importedNamespaces[i];
519 Element element = nameSpace.getPrefixed(prefix, name);
520 if (element != null) {
521 if (foundElement == null) {
522 foundElement = element;
523 } else if (!identical(foundElement, element)) {
524 foundElement = MultiplyDefinedElementImpl.fromElements(
525 _definingLibrary.context, foundElement, element);
526 }
527 }
528 }
529 Element element = foundElement;
530 if (element is MultiplyDefinedElementImpl) {
531 foundElement = _removeSdkElements(identifier, name, element);
532 }
533 if (foundElement is MultiplyDefinedElementImpl) {
534 String foundEltName = foundElement.displayName;
535 List<Element> conflictingMembers = foundElement.conflictingElements;
536 int count = conflictingMembers.length;
537 List<String> libraryNames = new List<String>(count);
538 for (int i = 0; i < count; i++) {
539 libraryNames[i] = _getLibraryName(conflictingMembers[i]);
540 }
541 libraryNames.sort();
542 errorListener.onError(new AnalysisError(
543 getSource(identifier),
544 identifier.offset,
545 identifier.length,
546 StaticWarningCode.AMBIGUOUS_IMPORT, [
547 foundEltName,
548 StringUtilities.printListOfQuotedNames(libraryNames)
549 ]));
550 return foundElement;
551 }
552 if (foundElement != null) {
553 _definePrefixedNameWithoutChecking(prefix, name, foundElement);
554 }
555 return foundElement;
556 }
557
558 /**
559 * Return the element with which the given [prefix] and [name] are associated,
560 * or `null` if the name is not defined within this scope.
561 */
562 Element _localPrefixedLookup(String prefix, String name) {
563 if (_definedPrefixedNames != null) {
564 Map<String, Element> unprefixedNames = _definedPrefixedNames[prefix];
565 if (unprefixedNames != null) {
566 return unprefixedNames[name];
567 }
568 }
569 return null;
570 }
571
485 /** 572 /**
486 * Given a collection of elements (captured by the [foundElement]) that the 573 * Given a collection of elements (captured by the [foundElement]) that the
487 * [identifier] (with the given [name]) resolved to, remove from the list all 574 * [identifier] (with the given [name]) resolved to, remove from the list all
488 * of the names defined in the SDK and return the element(s) that remain. 575 * of the names defined in the SDK and return the element(s) that remain.
489 */ 576 */
490 Element _removeSdkElements(Identifier identifier, String name, 577 Element _removeSdkElements(Identifier identifier, String name,
491 MultiplyDefinedElementImpl foundElement) { 578 MultiplyDefinedElementImpl foundElement) {
492 List<Element> conflictingElements = foundElement.conflictingElements; 579 List<Element> conflictingElements = foundElement.conflictingElements;
493 List<Element> nonSdkElements = new List<Element>(); 580 List<Element> nonSdkElements = new List<Element>();
494 Element sdkElement = null; 581 Element sdkElement = null;
(...skipping 128 matching lines...) Expand 10 before | Expand all | Expand 10 after
623 Namespace(this._definedNames); 710 Namespace(this._definedNames);
624 711
625 /** 712 /**
626 * Return a table containing the same mappings as those defined by this 713 * Return a table containing the same mappings as those defined by this
627 * namespace. 714 * namespace.
628 */ 715 */
629 Map<String, Element> get definedNames => _definedNames; 716 Map<String, Element> get definedNames => _definedNames;
630 717
631 /** 718 /**
632 * Return the element in this namespace that is available to the containing 719 * Return the element in this namespace that is available to the containing
633 * scope using the given name. 720 * scope using the given name, or `null` if there is no such element.
634 */ 721 */
635 Element get(String name) => _definedNames[name]; 722 Element get(String name) => _definedNames[name];
723
724 /**
725 * Return the element in this namespace whose name is the result of combining
726 * the [prefix] and the [name], separated by a period, or `null` if there is
727 * no such element.
728 */
729 Element getPrefixed(String prefix, String name) => null;
636 } 730 }
637 731
638 /** 732 /**
639 * The builder used to build a namespace. Namespace builders are thread-safe and 733 * The builder used to build a namespace. Namespace builders are thread-safe and
640 * re-usable. 734 * re-usable.
641 */ 735 */
642 class NamespaceBuilder { 736 class NamespaceBuilder {
643 /** 737 /**
644 * Create a namespace representing the export namespace of the given [element] . 738 * Create a namespace representing the export namespace of the given [element] .
645 */ 739 */
(...skipping 26 matching lines...) Expand all
672 LibraryElement importedLibrary = element.importedLibrary; 766 LibraryElement importedLibrary = element.importedLibrary;
673 if (importedLibrary == null) { 767 if (importedLibrary == null) {
674 // 768 //
675 // The imported library will be null if the URI does not reference a valid 769 // The imported library will be null if the URI does not reference a valid
676 // library. 770 // library.
677 // 771 //
678 return Namespace.EMPTY; 772 return Namespace.EMPTY;
679 } 773 }
680 HashMap<String, Element> exportedNames = _getExportMapping(importedLibrary); 774 HashMap<String, Element> exportedNames = _getExportMapping(importedLibrary);
681 exportedNames = _applyCombinators(exportedNames, element.combinators); 775 exportedNames = _applyCombinators(exportedNames, element.combinators);
682 exportedNames = _applyPrefix(exportedNames, element.prefix); 776 PrefixElement prefix = element.prefix;
777 if (prefix != null) {
778 return new PrefixedNamespace(prefix.name, exportedNames);
779 }
683 return new Namespace(exportedNames); 780 return new Namespace(exportedNames);
684 } 781 }
685 782
686 /** 783 /**
687 * Create a namespace representing the public namespace of the given 784 * Create a namespace representing the public namespace of the given
688 * [library]. 785 * [library].
689 */ 786 */
690 Namespace createPublicNamespaceForLibrary(LibraryElement library) { 787 Namespace createPublicNamespaceForLibrary(LibraryElement library) {
691 HashMap<String, Element> definedNames = new HashMap<String, Element>(); 788 HashMap<String, Element> definedNames = new HashMap<String, Element>();
692 _addPublicNames(definedNames, library.definingCompilationUnit); 789 _addPublicNames(definedNames, library.definingCompilationUnit);
(...skipping 65 matching lines...) Expand 10 before | Expand all | Expand 10 after
758 } else { 855 } else {
759 // Internal error. 856 // Internal error.
760 AnalysisEngine.instance.logger 857 AnalysisEngine.instance.logger
761 .logError("Unknown type of combinator: ${combinator.runtimeType}"); 858 .logError("Unknown type of combinator: ${combinator.runtimeType}");
762 } 859 }
763 } 860 }
764 return definedNames; 861 return definedNames;
765 } 862 }
766 863
767 /** 864 /**
768 * Apply the prefix defined by the [prefixElement] to all of the names in the
769 * table of [definedNames].
770 */
771 HashMap<String, Element> _applyPrefix(
772 HashMap<String, Element> definedNames, PrefixElement prefixElement) {
773 if (prefixElement != null) {
774 String prefix = prefixElement.name;
775 HashMap<String, Element> newNames = new HashMap<String, Element>();
776 definedNames.forEach((String name, Element element) {
777 newNames["$prefix.$name"] = element;
778 });
779 return newNames;
780 } else {
781 return definedNames;
782 }
783 }
784
785 /**
786 * Create a mapping table representing the export namespace of the given 865 * Create a mapping table representing the export namespace of the given
787 * [library]. The set of [visitedElements] contains the libraries that do not 866 * [library]. The set of [visitedElements] contains the libraries that do not
788 * need to be visited when processing the export directives of the given 867 * need to be visited when processing the export directives of the given
789 * library because all of the names defined by them will be added by another 868 * library because all of the names defined by them will be added by another
790 * library. 869 * library.
791 */ 870 */
792 HashMap<String, Element> _computeExportMapping( 871 HashMap<String, Element> _computeExportMapping(
793 LibraryElement library, HashSet<LibraryElement> visitedElements) { 872 LibraryElement library, HashSet<LibraryElement> visitedElements) {
794 visitedElements.add(library); 873 visitedElements.add(library);
795 try { 874 try {
(...skipping 66 matching lines...) Expand 10 before | Expand all | Expand 10 after
862 element = definedNames[setterName]; 941 element = definedNames[setterName];
863 if (element != null) { 942 if (element != null) {
864 newNames[setterName] = element; 943 newNames[setterName] = element;
865 } 944 }
866 } 945 }
867 return newNames; 946 return newNames;
868 } 947 }
869 } 948 }
870 949
871 /** 950 /**
951 * A mapping of identifiers to the elements represented by those identifiers.
952 * Namespaces are the building blocks for scopes.
953 */
954 class PrefixedNamespace implements Namespace {
955 /**
956 * The prefix that is prepended to each of the defined names.
957 */
958 final String _prefix;
959
960 /**
961 * The length of the prefix.
962 */
963 final int _length;
964
965 /**
966 * A table mapping names that are defined in this namespace to the element
967 * representing the thing declared with that name.
968 */
969 final HashMap<String, Element> _definedNames;
970
971 /**
972 * Initialize a newly created namespace to have the names resulting from
973 * prefixing each of the [_definedNames] with the given [_prefix] (and a
974 * period).
975 */
976 PrefixedNamespace(String prefix, this._definedNames)
977 : _prefix = prefix,
978 _length = prefix.length;
979
980 @override
981 Map<String, Element> get definedNames {
982 Map<String, Element> definedNames = <String, Element>{};
983 _definedNames.forEach((String name, Element element) {
984 definedNames["$_prefix.$name"] = element;
985 });
986 return definedNames;
987 }
988
989 @override
990 Element get(String name) {
991 if (name.startsWith(_prefix)) {
992 if (name.codeUnitAt(_length) == '.'.codeUnitAt(0)) {
993 return _definedNames[name.substring(_length + 1)];
994 }
995 }
996 return null;
997 }
998
999 @override
1000 Element getPrefixed(String prefix, String name) {
1001 if (prefix == _prefix) {
1002 return _definedNames[name];
1003 }
1004 return null;
1005 }
1006 }
1007
1008 /**
872 * A name scope used by the resolver to determine which names are visible at any 1009 * A name scope used by the resolver to determine which names are visible at any
873 * given point in the code. 1010 * given point in the code.
874 */ 1011 */
875 abstract class Scope { 1012 abstract class Scope {
876 /** 1013 /**
877 * The prefix used to mark an identifier as being private to its library. 1014 * The prefix used to mark an identifier as being private to its library.
878 */ 1015 */
879 static int PRIVATE_NAME_PREFIX = 0x5F; 1016 static int PRIVATE_NAME_PREFIX = 0x5F;
880 1017
881 /** 1018 /**
(...skipping 120 matching lines...) Expand 10 before | Expand all | Expand 10 after
1002 } 1139 }
1003 return null; 1140 return null;
1004 } 1141 }
1005 1142
1006 /** 1143 /**
1007 * Return the element with which the given [identifier] is associated, or 1144 * Return the element with which the given [identifier] is associated, or
1008 * `null` if the name is not defined within this scope. The 1145 * `null` if the name is not defined within this scope. The
1009 * [referencingLibrary] is the library that contains the reference to the 1146 * [referencingLibrary] is the library that contains the reference to the
1010 * name, used to implement library-level privacy. 1147 * name, used to implement library-level privacy.
1011 */ 1148 */
1012 Element lookup(Identifier identifier, LibraryElement referencingLibrary) => 1149 Element lookup(Identifier identifier, LibraryElement referencingLibrary) {
1013 internalLookup(identifier, identifier.name, referencingLibrary); 1150 if (identifier is PrefixedIdentifier) {
1151 return _internalLookupPrefixed(identifier, identifier.prefix.name,
1152 identifier.identifier.name, referencingLibrary);
1153 }
1154 return internalLookup(identifier, identifier.name, referencingLibrary);
1155 }
1014 1156
1015 /** 1157 /**
1016 * Return the name that will be used to look up the given [element]. 1158 * Return the name that will be used to look up the given [element].
1017 */ 1159 */
1018 String _getName(Element element) { 1160 String _getName(Element element) {
1019 if (element is MethodElement) { 1161 if (element is MethodElement) {
1020 MethodElement method = element; 1162 MethodElement method = element;
1021 if (method.name == "-" && method.parameters.length == 0) { 1163 if (method.name == "-" && method.parameters.length == 0) {
1022 return UNARY_MINUS; 1164 return UNARY_MINUS;
1023 } 1165 }
1024 } 1166 }
1025 return element.name; 1167 return element.name;
1026 } 1168 }
1027 1169
1028 /** 1170 /**
1171 * Return the element with which the given [prefix] and [name] are associated,
1172 * or `null` if the name is not defined within this scope. The [identifier] is
1173 * the identifier node to lookup element for, used to report correct kind of a
1174 * problem and associate problem with. The [referencingLibrary] is the library
1175 * that contains the reference to the name, used to implement library-level
1176 * privacy.
1177 */
1178 Element _internalLookupPrefixed(Identifier identifier, String prefix,
1179 String name, LibraryElement referencingLibrary);
1180
1181 /**
1029 * Return `true` if the given [name] is a library-private name. 1182 * Return `true` if the given [name] is a library-private name.
1030 */ 1183 */
1031 static bool isPrivateName(String name) => 1184 static bool isPrivateName(String name) =>
1032 name != null && StringUtilities.startsWithChar(name, PRIVATE_NAME_PREFIX); 1185 name != null && StringUtilities.startsWithChar(name, PRIVATE_NAME_PREFIX);
1033 } 1186 }
1034 1187
1035 /** 1188 /**
1036 * The scope defined by the type parameters in a class. 1189 * The scope defined by the type parameters in a class.
1037 */ 1190 */
1038 class TypeParameterScope extends EnclosedScope { 1191 class TypeParameterScope extends EnclosedScope {
(...skipping 11 matching lines...) Expand all
1050 1203
1051 /** 1204 /**
1052 * Define the type parameters declared by the [classElement]. 1205 * Define the type parameters declared by the [classElement].
1053 */ 1206 */
1054 void _defineTypeParameters(ClassElement classElement) { 1207 void _defineTypeParameters(ClassElement classElement) {
1055 for (TypeParameterElement typeParameter in classElement.typeParameters) { 1208 for (TypeParameterElement typeParameter in classElement.typeParameters) {
1056 define(typeParameter); 1209 define(typeParameter);
1057 } 1210 }
1058 } 1211 }
1059 } 1212 }
OLDNEW
« no previous file with comments | « pkg/analyzer/lib/src/dart/ast/ast.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