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

Side by Side Diff: pkg/analyzer/lib/src/generated/element_resolver.dart

Issue 1173523002: Fix analyzer's handling of import prefixes not followed by '.'. (Closed) Base URL: git@github.com:dart-lang/sdk.git@master
Patch Set: Created 5 years, 6 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 | « no previous file | pkg/analyzer/lib/src/generated/error.dart » ('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) 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 engine.resolver.element_resolver; 5 library engine.resolver.element_resolver;
6 6
7 import 'dart:collection'; 7 import 'dart:collection';
8 8
9 import 'ast.dart'; 9 import 'ast.dart';
10 import 'element.dart'; 10 import 'element.dart';
(...skipping 591 matching lines...) Expand 10 before | Expand all | Expand 10 after
602 // then we don't call resolveInvokedElement(...) which walks up the class 602 // then we don't call resolveInvokedElement(...) which walks up the class
603 // hierarchy, instead we just look for the member in the type only. This 603 // hierarchy, instead we just look for the member in the type only. This
604 // does not apply to conditional method invocation (i.e. 'C?.m(...)'). 604 // does not apply to conditional method invocation (i.e. 'C?.m(...)').
605 // 605 //
606 bool isConditional = node.operator.type == sc.TokenType.QUESTION_PERIOD; 606 bool isConditional = node.operator.type == sc.TokenType.QUESTION_PERIOD;
607 ClassElementImpl typeReference = getTypeReference(target, isConditional); 607 ClassElementImpl typeReference = getTypeReference(target, isConditional);
608 if (typeReference != null) { 608 if (typeReference != null) {
609 staticElement = 609 staticElement =
610 propagatedElement = _resolveElement(typeReference, methodName); 610 propagatedElement = _resolveElement(typeReference, methodName);
611 } else { 611 } else {
612 staticElement = 612 staticElement = _resolveInvokedElementWithTarget(
613 _resolveInvokedElementWithTarget(target, staticType, methodName); 613 target, staticType, methodName, isConditional);
614 propagatedElement = _resolveInvokedElementWithTarget( 614 propagatedElement = _resolveInvokedElementWithTarget(
615 target, propagatedType, methodName); 615 target, propagatedType, methodName, isConditional);
616 } 616 }
617 } 617 }
618 staticElement = _convertSetterToGetter(staticElement); 618 staticElement = _convertSetterToGetter(staticElement);
619 propagatedElement = _convertSetterToGetter(propagatedElement); 619 propagatedElement = _convertSetterToGetter(propagatedElement);
620 // 620 //
621 // Record the results. 621 // Record the results.
622 // 622 //
623 methodName.staticElement = staticElement; 623 methodName.staticElement = staticElement;
624 methodName.propagatedElement = propagatedElement; 624 methodName.propagatedElement = propagatedElement;
625 ArgumentList argumentList = node.argumentList; 625 ArgumentList argumentList = node.argumentList;
(...skipping 369 matching lines...) Expand 10 before | Expand all | Expand 10 after
995 } else if (element == null || 995 } else if (element == null ||
996 (element is PrefixElement && !_isValidAsPrefix(node))) { 996 (element is PrefixElement && !_isValidAsPrefix(node))) {
997 // TODO(brianwilkerson) Recover from this error. 997 // TODO(brianwilkerson) Recover from this error.
998 if (_isConstructorReturnType(node)) { 998 if (_isConstructorReturnType(node)) {
999 _resolver.reportErrorForNode( 999 _resolver.reportErrorForNode(
1000 CompileTimeErrorCode.INVALID_CONSTRUCTOR_NAME, node); 1000 CompileTimeErrorCode.INVALID_CONSTRUCTOR_NAME, node);
1001 } else if (node.parent is Annotation) { 1001 } else if (node.parent is Annotation) {
1002 Annotation annotation = node.parent as Annotation; 1002 Annotation annotation = node.parent as Annotation;
1003 _resolver.reportErrorForNode( 1003 _resolver.reportErrorForNode(
1004 CompileTimeErrorCode.INVALID_ANNOTATION, annotation); 1004 CompileTimeErrorCode.INVALID_ANNOTATION, annotation);
1005 } else if (element is PrefixElement) {
1006 _resolver.reportErrorForNode(
1007 CompileTimeErrorCode.PREFIX_IDENTIFIER_NOT_FOLLOWED_BY_DOT, node,
1008 [element.name]);
1005 } else { 1009 } else {
1006 _recordUndefinedNode(_resolver.enclosingClass, 1010 _recordUndefinedNode(_resolver.enclosingClass,
1007 StaticWarningCode.UNDEFINED_IDENTIFIER, node, [node.name]); 1011 StaticWarningCode.UNDEFINED_IDENTIFIER, node, [node.name]);
1008 } 1012 }
1009 } 1013 }
1010 node.staticElement = element; 1014 node.staticElement = element;
1011 if (node.inSetterContext() && 1015 if (node.inSetterContext() &&
1012 node.inGetterContext() && 1016 node.inGetterContext() &&
1013 enclosingClass != null) { 1017 enclosingClass != null) {
1014 InterfaceType enclosingType = enclosingClass.type; 1018 InterfaceType enclosingType = enclosingClass.type;
(...skipping 333 matching lines...) Expand 10 before | Expand all | Expand 10 after
1348 element = MultiplyDefinedElementImpl.fromElements( 1352 element = MultiplyDefinedElementImpl.fromElements(
1349 _definingLibrary.context, element, importedElement); 1353 _definingLibrary.context, element, importedElement);
1350 } 1354 }
1351 } 1355 }
1352 } 1356 }
1353 } 1357 }
1354 return element; 1358 return element;
1355 } 1359 }
1356 1360
1357 /** 1361 /**
1362 * Return the best type of the given [expression] that is to be used for
1363 * type analysis.
1364 */
1365 DartType _getBestType(Expression expression) {
1366 DartType bestType = _resolveTypeParameter(expression.bestType);
1367 if (bestType is FunctionType) {
1368 //
1369 // All function types are subtypes of 'Function', which is itself a
1370 // subclass of 'Object'.
1371 //
1372 bestType = _resolver.typeProvider.functionType;
1373 }
1374 return bestType;
1375 }
1376
1377 /**
1358 * Assuming that the given [expression] is a prefix for a deferred import, 1378 * Assuming that the given [expression] is a prefix for a deferred import,
1359 * return the library that is being imported. 1379 * return the library that is being imported.
1360 */ 1380 */
1361 LibraryElement _getImportedLibrary(Expression expression) { 1381 LibraryElement _getImportedLibrary(Expression expression) {
1362 PrefixElement prefixElement = 1382 PrefixElement prefixElement =
1363 (expression as SimpleIdentifier).staticElement as PrefixElement; 1383 (expression as SimpleIdentifier).staticElement as PrefixElement;
1364 List<ImportElement> imports = 1384 List<ImportElement> imports =
1365 prefixElement.enclosingElement.getImportsWithPrefix(prefixElement); 1385 prefixElement.enclosingElement.getImportsWithPrefix(prefixElement);
1366 return imports[0].importedLibrary; 1386 return imports[0].importedLibrary;
1367 } 1387 }
(...skipping 17 matching lines...) Expand all
1385 } else if (operatorType == sc.TokenType.MINUS_MINUS) { 1405 } else if (operatorType == sc.TokenType.MINUS_MINUS) {
1386 return sc.TokenType.MINUS.lexeme; 1406 return sc.TokenType.MINUS.lexeme;
1387 } else if (operatorType == sc.TokenType.MINUS) { 1407 } else if (operatorType == sc.TokenType.MINUS) {
1388 return "unary-"; 1408 return "unary-";
1389 } else { 1409 } else {
1390 return operator.lexeme; 1410 return operator.lexeme;
1391 } 1411 }
1392 } 1412 }
1393 1413
1394 /** 1414 /**
1395 * Return the best type of the given [expression] that is to be used for
1396 * type analysis.
1397 */
1398 DartType _getBestType(Expression expression) {
1399 DartType bestType = _resolveTypeParameter(expression.bestType);
1400 if (bestType is FunctionType) {
1401 //
1402 // All function types are subtypes of 'Function', which is itself a
1403 // subclass of 'Object'.
1404 //
1405 bestType = _resolver.typeProvider.functionType;
1406 }
1407 return bestType;
1408 }
1409
1410 /**
1411 * Return the propagated type of the given [expression] that is to be used for 1415 * Return the propagated type of the given [expression] that is to be used for
1412 * type analysis. 1416 * type analysis.
1413 */ 1417 */
1414 DartType _getPropagatedType(Expression expression) { 1418 DartType _getPropagatedType(Expression expression) {
1415 DartType propagatedType = _resolveTypeParameter(expression.propagatedType); 1419 DartType propagatedType = _resolveTypeParameter(expression.propagatedType);
1416 if (propagatedType is FunctionType) { 1420 if (propagatedType is FunctionType) {
1417 // 1421 //
1418 // All function types are subtypes of 'Function', which is itself a 1422 // All function types are subtypes of 'Function', which is itself a
1419 // subclass of 'Object'. 1423 // subclass of 'Object'.
1420 // 1424 //
(...skipping 905 matching lines...) Expand 10 before | Expand all | Expand 10 after
2326 * will be invoked. If the returned element is a getter, the getter will be 2330 * will be invoked. If the returned element is a getter, the getter will be
2327 * invoked without arguments and the result of that invocation will then be 2331 * invoked without arguments and the result of that invocation will then be
2328 * invoked with the arguments. The [methodName] is the name of the method 2332 * invoked with the arguments. The [methodName] is the name of the method
2329 * being invoked ('m'). 2333 * being invoked ('m').
2330 */ 2334 */
2331 Element _resolveInvokedElement(SimpleIdentifier methodName) { 2335 Element _resolveInvokedElement(SimpleIdentifier methodName) {
2332 // 2336 //
2333 // Look first in the lexical scope. 2337 // Look first in the lexical scope.
2334 // 2338 //
2335 Element element = _resolver.nameScope.lookup(methodName, _definingLibrary); 2339 Element element = _resolver.nameScope.lookup(methodName, _definingLibrary);
2336 if (element == null) { 2340 if (element == null || element is PrefixElement) {
2337 // 2341 //
2338 // If it isn't defined in the lexical scope, and the invocation is within 2342 // If it isn't defined in the lexical scope, and the invocation is within
2339 // a class, then look in the inheritance scope. 2343 // a class, then look in the inheritance scope.
2340 // 2344 //
2341 ClassElement enclosingClass = _resolver.enclosingClass; 2345 ClassElement enclosingClass = _resolver.enclosingClass;
2342 if (enclosingClass != null) { 2346 if (enclosingClass != null) {
2343 InterfaceType enclosingType = enclosingClass.type; 2347 InterfaceType enclosingType = enclosingClass.type;
2344 element = _lookUpMethod(null, enclosingType, methodName.name); 2348 element = _lookUpMethod(null, enclosingType, methodName.name);
2345 if (element == null) { 2349 if (element == null) {
2346 // 2350 //
2347 // If there's no method, then it's possible that 'm' is a getter that 2351 // If there's no method, then it's possible that 'm' is a getter that
2348 // returns a function. 2352 // returns a function.
2349 // 2353 //
2350 element = _lookUpGetter(null, enclosingType, methodName.name); 2354 element = _lookUpGetter(null, enclosingType, methodName.name);
2351 } 2355 }
2352 } 2356 }
2353 } 2357 }
2354 // TODO(brianwilkerson) Report this error. 2358 // TODO(brianwilkerson) Report this error.
2355 return element; 2359 return element;
2356 } 2360 }
2357 2361
2358 /** 2362 /**
2359 * Given an invocation of the form 'e.m(a1, ..., an)', resolve 'e.m' to the 2363 * Given an invocation of the form 'e.m(a1, ..., an)', resolve 'e.m' to the
2360 * element being invoked. If the returned element is a method, then the method 2364 * element being invoked. If the returned element is a method, then the method
2361 * will be invoked. If the returned element is a getter, the getter will be 2365 * will be invoked. If the returned element is a getter, the getter will be
2362 * invoked without arguments and the result of that invocation will then be 2366 * invoked without arguments and the result of that invocation will then be
2363 * invoked with the arguments. The [target] is the target of the invocation 2367 * invoked with the arguments. The [target] is the target of the invocation
2364 * ('e'). The [targetType] is the type of the target. The [methodName] is th 2368 * ('e'). The [targetType] is the type of the target. The [methodName] is th
2365 * name of the method being invoked ('m'). 2369 * name of the method being invoked ('m'). [isConditional] indicates
2370 * whether the invocatoin uses a '?.' operator.
2366 */ 2371 */
2367 Element _resolveInvokedElementWithTarget( 2372 Element _resolveInvokedElementWithTarget(Expression target,
2368 Expression target, DartType targetType, SimpleIdentifier methodName) { 2373 DartType targetType, SimpleIdentifier methodName, bool isConditional) {
2369 if (targetType is InterfaceType) { 2374 if (targetType is InterfaceType) {
2370 Element element = _lookUpMethod(target, targetType, methodName.name); 2375 Element element = _lookUpMethod(target, targetType, methodName.name);
2371 if (element == null) { 2376 if (element == null) {
2372 // 2377 //
2373 // If there's no method, then it's possible that 'm' is a getter that 2378 // If there's no method, then it's possible that 'm' is a getter that
2374 // returns a function. 2379 // returns a function.
2375 // 2380 //
2376 // TODO (collinsn): need to add union type support here too, in the 2381 // TODO (collinsn): need to add union type support here too, in the
2377 // style of [lookUpMethod]. 2382 // style of [lookUpMethod].
2378 element = _lookUpGetter(target, targetType, methodName.name); 2383 element = _lookUpGetter(target, targetType, methodName.name);
2379 } 2384 }
2380 return element; 2385 return element;
2381 } else if (target is SimpleIdentifier) { 2386 } else if (target is SimpleIdentifier) {
2382 Element targetElement = target.staticElement; 2387 Element targetElement = target.staticElement;
2383 if (targetElement is PrefixElement) { 2388 if (targetElement is PrefixElement) {
2389 if (isConditional) {
2390 _resolver.reportErrorForNode(
2391 CompileTimeErrorCode.PREFIX_IDENTIFIER_NOT_FOLLOWED_BY_DOT,
2392 target, [target.name]);
2393 }
2384 // 2394 //
2385 // Look to see whether the name of the method is really part of a 2395 // Look to see whether the name of the method is really part of a
2386 // prefixed identifier for an imported top-level function or top-level 2396 // prefixed identifier for an imported top-level function or top-level
2387 // getter that returns a function. 2397 // getter that returns a function.
2388 // 2398 //
2389 String name = "${target.name}.$methodName"; 2399 String name = "${target.name}.$methodName";
2390 Identifier functionName = new SyntheticIdentifier(name, methodName); 2400 Identifier functionName = new SyntheticIdentifier(name, methodName);
2391 Element element = 2401 Element element =
2392 _resolver.nameScope.lookup(functionName, _definingLibrary); 2402 _resolver.nameScope.lookup(functionName, _definingLibrary);
2393 if (element != null) { 2403 if (element != null) {
(...skipping 181 matching lines...) Expand 10 before | Expand all | Expand 10 after
2575 if (setter != null) { 2585 if (setter != null) {
2576 element = setter; 2586 element = setter;
2577 } 2587 }
2578 } 2588 }
2579 } else if (element == null && 2589 } else if (element == null &&
2580 (identifier.inSetterContext() || 2590 (identifier.inSetterContext() ||
2581 identifier.parent is CommentReference)) { 2591 identifier.parent is CommentReference)) {
2582 element = _resolver.nameScope.lookup( 2592 element = _resolver.nameScope.lookup(
2583 new SyntheticIdentifier("${identifier.name}=", identifier), 2593 new SyntheticIdentifier("${identifier.name}=", identifier),
2584 _definingLibrary); 2594 _definingLibrary);
2595 } else if (element is PrefixElement && !identifier.inGetterContext()) {
2596 element = _resolver.nameScope.lookup(
2597 new SyntheticIdentifier("${identifier.name}=", identifier),
2598 _definingLibrary);
2585 } 2599 }
2586 ClassElement enclosingClass = _resolver.enclosingClass; 2600 ClassElement enclosingClass = _resolver.enclosingClass;
2587 if (element == null && enclosingClass != null) { 2601 if (element == null && enclosingClass != null) {
2588 InterfaceType enclosingType = enclosingClass.type; 2602 InterfaceType enclosingType = enclosingClass.type;
2589 if (element == null && 2603 if (element == null &&
2590 (identifier.inSetterContext() || 2604 (identifier.inSetterContext() ||
2591 identifier.parent is CommentReference)) { 2605 identifier.parent is CommentReference)) {
2592 element = _lookUpSetter(null, enclosingType, identifier.name); 2606 element = _lookUpSetter(null, enclosingType, identifier.name);
2593 } 2607 }
2594 if (element == null && identifier.inGetterContext()) { 2608 if (element == null && identifier.inGetterContext()) {
(...skipping 197 matching lines...) Expand 10 before | Expand all | Expand 10 after
2792 2806
2793 @override 2807 @override
2794 Element get staticElement => null; 2808 Element get staticElement => null;
2795 2809
2796 @override 2810 @override
2797 accept(AstVisitor visitor) => null; 2811 accept(AstVisitor visitor) => null;
2798 2812
2799 @override 2813 @override
2800 void visitChildren(AstVisitor visitor) {} 2814 void visitChildren(AstVisitor visitor) {}
2801 } 2815 }
OLDNEW
« no previous file with comments | « no previous file | pkg/analyzer/lib/src/generated/error.dart » ('j') | no next file with comments »

Powered by Google App Engine
This is Rietveld 408576698