Chromium Code Reviews| OLD | NEW |
|---|---|
| 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; | 5 library engine.resolver; |
| 6 | 6 |
| 7 import 'dart:collection'; | 7 import 'dart:collection'; |
| 8 | 8 |
| 9 import 'ast.dart'; | 9 import 'ast.dart'; |
| 10 import 'constant.dart'; | 10 import 'constant.dart'; |
| (...skipping 55 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
| 66 */ | 66 */ |
| 67 final ErrorReporter _errorReporter; | 67 final ErrorReporter _errorReporter; |
| 68 | 68 |
| 69 /** | 69 /** |
| 70 * The type Future<Null>, which is needed for determining whether it is safe | 70 * The type Future<Null>, which is needed for determining whether it is safe |
| 71 * to have a bare "return;" in an async method. | 71 * to have a bare "return;" in an async method. |
| 72 */ | 72 */ |
| 73 final InterfaceType _futureNullType; | 73 final InterfaceType _futureNullType; |
| 74 | 74 |
| 75 /** | 75 /** |
| 76 * The type system primitives | |
| 77 */ | |
| 78 TypeSystem _typeSystem; | |
| 79 | |
| 80 /** | |
| 76 * Create a new instance of the [BestPracticesVerifier]. | 81 * Create a new instance of the [BestPracticesVerifier]. |
| 77 * | 82 * |
| 78 * @param errorReporter the error reporter | 83 * @param errorReporter the error reporter |
| 79 */ | 84 */ |
| 80 BestPracticesVerifier(this._errorReporter, TypeProvider typeProvider) | 85 BestPracticesVerifier( |
| 86 this._errorReporter, TypeProvider typeProvider, this._typeSystem) | |
| 81 : _futureNullType = typeProvider.futureNullType; | 87 : _futureNullType = typeProvider.futureNullType; |
| 82 | 88 |
| 83 @override | 89 @override |
| 84 Object visitArgumentList(ArgumentList node) { | 90 Object visitArgumentList(ArgumentList node) { |
| 85 _checkForArgumentTypesNotAssignableInList(node); | 91 _checkForArgumentTypesNotAssignableInList(node); |
| 86 return super.visitArgumentList(node); | 92 return super.visitArgumentList(node); |
| 87 } | 93 } |
| 88 | 94 |
| 89 @override | 95 @override |
| 90 Object visitAsExpression(AsExpression node) { | 96 Object visitAsExpression(AsExpression node) { |
| (...skipping 206 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
| 297 Expression expression, | 303 Expression expression, |
| 298 DartType expectedStaticType, | 304 DartType expectedStaticType, |
| 299 DartType actualStaticType, | 305 DartType actualStaticType, |
| 300 DartType expectedPropagatedType, | 306 DartType expectedPropagatedType, |
| 301 DartType actualPropagatedType, | 307 DartType actualPropagatedType, |
| 302 ErrorCode hintCode) { | 308 ErrorCode hintCode) { |
| 303 // | 309 // |
| 304 // Warning case: test static type information | 310 // Warning case: test static type information |
| 305 // | 311 // |
| 306 if (actualStaticType != null && expectedStaticType != null) { | 312 if (actualStaticType != null && expectedStaticType != null) { |
| 307 if (!actualStaticType.isAssignableTo(expectedStaticType)) { | 313 if (!_typeSystem.isAssignableTo(actualStaticType, expectedStaticType)) { |
| 308 // A warning was created in the ErrorVerifier, return false, don't | 314 // A warning was created in the ErrorVerifier, return false, don't |
| 309 // create a hint when a warning has already been created. | 315 // create a hint when a warning has already been created. |
| 310 return false; | 316 return false; |
| 311 } | 317 } |
| 312 } | 318 } |
| 313 // | 319 // |
| 314 // Hint case: test propagated type information | 320 // Hint case: test propagated type information |
| 315 // | 321 // |
| 316 // Compute the best types to use. | 322 // Compute the best types to use. |
| 317 DartType expectedBestType = expectedPropagatedType != null | 323 DartType expectedBestType = expectedPropagatedType != null |
| 318 ? expectedPropagatedType | 324 ? expectedPropagatedType |
| 319 : expectedStaticType; | 325 : expectedStaticType; |
| 320 DartType actualBestType = | 326 DartType actualBestType = |
| 321 actualPropagatedType != null ? actualPropagatedType : actualStaticType; | 327 actualPropagatedType != null ? actualPropagatedType : actualStaticType; |
| 322 if (actualBestType != null && expectedBestType != null) { | 328 if (actualBestType != null && expectedBestType != null) { |
| 323 if (!actualBestType.isAssignableTo(expectedBestType)) { | 329 if (!_typeSystem.isAssignableTo(actualBestType, expectedBestType)) { |
| 324 _errorReporter.reportTypeErrorForNode( | 330 _errorReporter.reportTypeErrorForNode( |
| 325 hintCode, expression, [actualBestType, expectedBestType]); | 331 hintCode, expression, [actualBestType, expectedBestType]); |
| 326 return true; | 332 return true; |
| 327 } | 333 } |
| 328 } | 334 } |
| 329 return false; | 335 return false; |
| 330 } | 336 } |
| 331 | 337 |
| 332 /** | 338 /** |
| 333 * This verifies that the passed argument can be assigned to its corresponding parameter. | 339 * This verifies that the passed argument can be assigned to its corresponding parameter. |
| (...skipping 178 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
| 512 */ | 518 */ |
| 513 bool _checkForInvalidAssignment(Expression lhs, Expression rhs) { | 519 bool _checkForInvalidAssignment(Expression lhs, Expression rhs) { |
| 514 if (lhs == null || rhs == null) { | 520 if (lhs == null || rhs == null) { |
| 515 return false; | 521 return false; |
| 516 } | 522 } |
| 517 VariableElement leftVariableElement = ErrorVerifier.getVariableElement(lhs); | 523 VariableElement leftVariableElement = ErrorVerifier.getVariableElement(lhs); |
| 518 DartType leftType = (leftVariableElement == null) | 524 DartType leftType = (leftVariableElement == null) |
| 519 ? ErrorVerifier.getStaticType(lhs) | 525 ? ErrorVerifier.getStaticType(lhs) |
| 520 : leftVariableElement.type; | 526 : leftVariableElement.type; |
| 521 DartType staticRightType = ErrorVerifier.getStaticType(rhs); | 527 DartType staticRightType = ErrorVerifier.getStaticType(rhs); |
| 522 if (!staticRightType.isAssignableTo(leftType)) { | 528 if (!_typeSystem.isAssignableTo(staticRightType, leftType)) { |
| 523 // The warning was generated on this rhs | 529 // The warning was generated on this rhs |
| 524 return false; | 530 return false; |
| 525 } | 531 } |
| 526 // Test for, and then generate the hint | 532 // Test for, and then generate the hint |
| 527 DartType bestRightType = rhs.bestType; | 533 DartType bestRightType = rhs.bestType; |
| 528 if (leftType != null && bestRightType != null) { | 534 if (leftType != null && bestRightType != null) { |
| 529 if (!bestRightType.isAssignableTo(leftType)) { | 535 if (!_typeSystem.isAssignableTo(bestRightType, leftType)) { |
| 530 _errorReporter.reportTypeErrorForNode( | 536 _errorReporter.reportTypeErrorForNode( |
| 531 HintCode.INVALID_ASSIGNMENT, rhs, [bestRightType, leftType]); | 537 HintCode.INVALID_ASSIGNMENT, rhs, [bestRightType, leftType]); |
| 532 return true; | 538 return true; |
| 533 } | 539 } |
| 534 } | 540 } |
| 535 return false; | 541 return false; |
| 536 } | 542 } |
| 537 | 543 |
| 538 /** | 544 /** |
| 539 * Check that the imported library does not define a loadLibrary function. The import has already | 545 * Check that the imported library does not define a loadLibrary function. The import has already |
| (...skipping 46 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
| 586 if (body.isGenerator) { | 592 if (body.isGenerator) { |
| 587 return false; | 593 return false; |
| 588 } | 594 } |
| 589 // Check that the type is resolvable, and is not "void" | 595 // Check that the type is resolvable, and is not "void" |
| 590 DartType returnTypeType = returnType.type; | 596 DartType returnTypeType = returnType.type; |
| 591 if (returnTypeType == null || returnTypeType.isVoid) { | 597 if (returnTypeType == null || returnTypeType.isVoid) { |
| 592 return false; | 598 return false; |
| 593 } | 599 } |
| 594 // For async, give no hint if Future<Null> is assignable to the return | 600 // For async, give no hint if Future<Null> is assignable to the return |
| 595 // type. | 601 // type. |
| 596 if (body.isAsynchronous && _futureNullType.isAssignableTo(returnTypeType)) { | 602 if (body.isAsynchronous && |
| 603 _typeSystem.isAssignableTo(_futureNullType, returnTypeType)) { | |
| 597 return false; | 604 return false; |
| 598 } | 605 } |
| 599 // Check the block for a return statement, if not, create the hint | 606 // Check the block for a return statement, if not, create the hint |
| 600 BlockFunctionBody blockFunctionBody = body as BlockFunctionBody; | 607 BlockFunctionBody blockFunctionBody = body as BlockFunctionBody; |
| 601 if (!ExitDetector.exits(blockFunctionBody)) { | 608 if (!ExitDetector.exits(blockFunctionBody)) { |
| 602 _errorReporter.reportErrorForNode( | 609 _errorReporter.reportErrorForNode( |
| 603 HintCode.MISSING_RETURN, returnType, [returnTypeType.displayName]); | 610 HintCode.MISSING_RETURN, returnType, [returnTypeType.displayName]); |
| 604 return true; | 611 return true; |
| 605 } | 612 } |
| 606 return false; | 613 return false; |
| (...skipping 225 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
| 832 * The error reporter by which errors will be reported. | 839 * The error reporter by which errors will be reported. |
| 833 */ | 840 */ |
| 834 final ErrorReporter _errorReporter; | 841 final ErrorReporter _errorReporter; |
| 835 | 842 |
| 836 /** | 843 /** |
| 837 * The type provider used to access the known types. | 844 * The type provider used to access the known types. |
| 838 */ | 845 */ |
| 839 final TypeProvider _typeProvider; | 846 final TypeProvider _typeProvider; |
| 840 | 847 |
| 841 /** | 848 /** |
| 849 * The type system in use. | |
| 850 */ | |
| 851 final TypeSystem _typeSystem; | |
| 852 | |
| 853 /** | |
| 842 * The set of variables declared using '-D' on the command line. | 854 * The set of variables declared using '-D' on the command line. |
| 843 */ | 855 */ |
| 844 final DeclaredVariables declaredVariables; | 856 final DeclaredVariables declaredVariables; |
| 845 | 857 |
| 846 /** | 858 /** |
| 847 * The type representing the type 'bool'. | 859 * The type representing the type 'bool'. |
| 848 */ | 860 */ |
| 849 InterfaceType _boolType; | 861 InterfaceType _boolType; |
| 850 | 862 |
| 851 /** | 863 /** |
| (...skipping 15 matching lines...) Expand all Loading... | |
| 867 * The current library that is being analyzed. | 879 * The current library that is being analyzed. |
| 868 */ | 880 */ |
| 869 final LibraryElement _currentLibrary; | 881 final LibraryElement _currentLibrary; |
| 870 | 882 |
| 871 /** | 883 /** |
| 872 * Initialize a newly created constant verifier. | 884 * Initialize a newly created constant verifier. |
| 873 * | 885 * |
| 874 * @param errorReporter the error reporter by which errors will be reported | 886 * @param errorReporter the error reporter by which errors will be reported |
| 875 */ | 887 */ |
| 876 ConstantVerifier(this._errorReporter, this._currentLibrary, | 888 ConstantVerifier(this._errorReporter, this._currentLibrary, |
| 877 this._typeProvider, this.declaredVariables) { | 889 this._typeProvider, this._typeSystem, this.declaredVariables) { |
| 878 this._boolType = _typeProvider.boolType; | 890 this._boolType = _typeProvider.boolType; |
| 879 this._intType = _typeProvider.intType; | 891 this._intType = _typeProvider.intType; |
| 880 this._numType = _typeProvider.numType; | 892 this._numType = _typeProvider.numType; |
| 881 this._stringType = _typeProvider.stringType; | 893 this._stringType = _typeProvider.stringType; |
| 882 } | 894 } |
| 883 | 895 |
| 884 @override | 896 @override |
| 885 Object visitAnnotation(Annotation node) { | 897 Object visitAnnotation(Annotation node) { |
| 886 super.visitAnnotation(node); | 898 super.visitAnnotation(node); |
| 887 // check annotation creation | 899 // check annotation creation |
| (...skipping 37 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
| 925 } | 937 } |
| 926 | 938 |
| 927 @override | 939 @override |
| 928 Object visitInstanceCreationExpression(InstanceCreationExpression node) { | 940 Object visitInstanceCreationExpression(InstanceCreationExpression node) { |
| 929 if (node.isConst) { | 941 if (node.isConst) { |
| 930 // We need to evaluate the constant to see if any errors occur during its | 942 // We need to evaluate the constant to see if any errors occur during its |
| 931 // evaluation. | 943 // evaluation. |
| 932 ConstructorElement constructor = node.staticElement; | 944 ConstructorElement constructor = node.staticElement; |
| 933 if (constructor != null) { | 945 if (constructor != null) { |
| 934 ConstantEvaluationEngine evaluationEngine = | 946 ConstantEvaluationEngine evaluationEngine = |
| 935 new ConstantEvaluationEngine(_typeProvider, declaredVariables); | 947 new ConstantEvaluationEngine( |
| 948 _typeProvider, _typeSystem, declaredVariables); | |
| 936 ConstantVisitor constantVisitor = | 949 ConstantVisitor constantVisitor = |
| 937 new ConstantVisitor(evaluationEngine, _errorReporter); | 950 new ConstantVisitor(evaluationEngine, _errorReporter); |
| 938 evaluationEngine.evaluateConstructorCall( | 951 evaluationEngine.evaluateConstructorCall( |
| 939 node, | 952 node, |
| 940 node.argumentList.arguments, | 953 node.argumentList.arguments, |
| 941 constructor, | 954 constructor, |
| 942 constantVisitor, | 955 constantVisitor, |
| 943 _errorReporter); | 956 _errorReporter); |
| 944 } | 957 } |
| 945 } | 958 } |
| (...skipping 53 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
| 999 [type.displayName]); | 1012 [type.displayName]); |
| 1000 } | 1013 } |
| 1001 } | 1014 } |
| 1002 } else { | 1015 } else { |
| 1003 // Note: we throw the errors away because this isn't actually a const. | 1016 // Note: we throw the errors away because this isn't actually a const. |
| 1004 AnalysisErrorListener errorListener = | 1017 AnalysisErrorListener errorListener = |
| 1005 AnalysisErrorListener.NULL_LISTENER; | 1018 AnalysisErrorListener.NULL_LISTENER; |
| 1006 ErrorReporter subErrorReporter = | 1019 ErrorReporter subErrorReporter = |
| 1007 new ErrorReporter(errorListener, _errorReporter.source); | 1020 new ErrorReporter(errorListener, _errorReporter.source); |
| 1008 DartObjectImpl result = key.accept(new ConstantVisitor( | 1021 DartObjectImpl result = key.accept(new ConstantVisitor( |
| 1009 new ConstantEvaluationEngine(_typeProvider, declaredVariables), | 1022 new ConstantEvaluationEngine( |
| 1023 _typeProvider, _typeSystem, declaredVariables), | |
| 1010 subErrorReporter)); | 1024 subErrorReporter)); |
| 1011 if (result != null) { | 1025 if (result != null) { |
| 1012 if (keys.contains(result)) { | 1026 if (keys.contains(result)) { |
| 1013 invalidKeys.add(key); | 1027 invalidKeys.add(key); |
| 1014 } else { | 1028 } else { |
| 1015 keys.add(result); | 1029 keys.add(result); |
| 1016 } | 1030 } |
| 1017 } else { | 1031 } else { |
| 1018 reportEqualKeys = false; | 1032 reportEqualKeys = false; |
| 1019 } | 1033 } |
| (...skipping 185 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
| 1205 * | 1219 * |
| 1206 * @param expression the expression to be validated | 1220 * @param expression the expression to be validated |
| 1207 * @param errorCode the error code to be used if the expression is not a compi le time constant | 1221 * @param errorCode the error code to be used if the expression is not a compi le time constant |
| 1208 * @return the value of the compile time constant | 1222 * @return the value of the compile time constant |
| 1209 */ | 1223 */ |
| 1210 DartObjectImpl _validate(Expression expression, ErrorCode errorCode) { | 1224 DartObjectImpl _validate(Expression expression, ErrorCode errorCode) { |
| 1211 RecordingErrorListener errorListener = new RecordingErrorListener(); | 1225 RecordingErrorListener errorListener = new RecordingErrorListener(); |
| 1212 ErrorReporter subErrorReporter = | 1226 ErrorReporter subErrorReporter = |
| 1213 new ErrorReporter(errorListener, _errorReporter.source); | 1227 new ErrorReporter(errorListener, _errorReporter.source); |
| 1214 DartObjectImpl result = expression.accept(new ConstantVisitor( | 1228 DartObjectImpl result = expression.accept(new ConstantVisitor( |
| 1215 new ConstantEvaluationEngine(_typeProvider, declaredVariables), | 1229 new ConstantEvaluationEngine( |
| 1230 _typeProvider, _typeSystem, declaredVariables), | |
| 1216 subErrorReporter)); | 1231 subErrorReporter)); |
| 1217 _reportErrors(errorListener.errors, errorCode); | 1232 _reportErrors(errorListener.errors, errorCode); |
| 1218 return result; | 1233 return result; |
| 1219 } | 1234 } |
| 1220 | 1235 |
| 1221 /** | 1236 /** |
| 1222 * Validate that if the passed arguments are constant expressions. | 1237 * Validate that if the passed arguments are constant expressions. |
| 1223 * | 1238 * |
| 1224 * @param argumentList the argument list to evaluate | 1239 * @param argumentList the argument list to evaluate |
| 1225 */ | 1240 */ |
| (...skipping 88 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
| 1314 Expression initializer = variableDeclaration.initializer; | 1329 Expression initializer = variableDeclaration.initializer; |
| 1315 if (initializer != null) { | 1330 if (initializer != null) { |
| 1316 // Ignore any errors produced during validation--if the constant | 1331 // Ignore any errors produced during validation--if the constant |
| 1317 // can't be eavluated we'll just report a single error. | 1332 // can't be eavluated we'll just report a single error. |
| 1318 AnalysisErrorListener errorListener = | 1333 AnalysisErrorListener errorListener = |
| 1319 AnalysisErrorListener.NULL_LISTENER; | 1334 AnalysisErrorListener.NULL_LISTENER; |
| 1320 ErrorReporter subErrorReporter = | 1335 ErrorReporter subErrorReporter = |
| 1321 new ErrorReporter(errorListener, _errorReporter.source); | 1336 new ErrorReporter(errorListener, _errorReporter.source); |
| 1322 DartObjectImpl result = initializer.accept(new ConstantVisitor( | 1337 DartObjectImpl result = initializer.accept(new ConstantVisitor( |
| 1323 new ConstantEvaluationEngine( | 1338 new ConstantEvaluationEngine( |
| 1324 _typeProvider, declaredVariables), | 1339 _typeProvider, _typeSystem, declaredVariables), |
| 1325 subErrorReporter)); | 1340 subErrorReporter)); |
| 1326 if (result == null) { | 1341 if (result == null) { |
| 1327 _errorReporter.reportErrorForNode( | 1342 _errorReporter.reportErrorForNode( |
| 1328 CompileTimeErrorCode.CONST_CONSTRUCTOR_WITH_FIELD_INITIALIZE D_BY_NON_CONST, | 1343 CompileTimeErrorCode.CONST_CONSTRUCTOR_WITH_FIELD_INITIALIZE D_BY_NON_CONST, |
| 1329 errorSite, | 1344 errorSite, |
| 1330 [variableDeclaration.name.name]); | 1345 [variableDeclaration.name.name]); |
| 1331 } | 1346 } |
| 1332 } | 1347 } |
| 1333 } | 1348 } |
| 1334 } | 1349 } |
| 1335 } | 1350 } |
| 1336 } | 1351 } |
| 1337 } | 1352 } |
| 1338 | 1353 |
| 1339 /** | 1354 /** |
| 1340 * Validates that the given expression is a compile time constant. | 1355 * Validates that the given expression is a compile time constant. |
| 1341 * | 1356 * |
| 1342 * @param parameterElements the elements of parameters of constant constructor , they are | 1357 * @param parameterElements the elements of parameters of constant constructor , they are |
| 1343 * considered as a valid potentially constant expressions | 1358 * considered as a valid potentially constant expressions |
| 1344 * @param expression the expression to validate | 1359 * @param expression the expression to validate |
| 1345 */ | 1360 */ |
| 1346 void _validateInitializerExpression( | 1361 void _validateInitializerExpression( |
| 1347 List<ParameterElement> parameterElements, Expression expression) { | 1362 List<ParameterElement> parameterElements, Expression expression) { |
| 1348 RecordingErrorListener errorListener = new RecordingErrorListener(); | 1363 RecordingErrorListener errorListener = new RecordingErrorListener(); |
| 1349 ErrorReporter subErrorReporter = | 1364 ErrorReporter subErrorReporter = |
| 1350 new ErrorReporter(errorListener, _errorReporter.source); | 1365 new ErrorReporter(errorListener, _errorReporter.source); |
| 1351 DartObjectImpl result = expression.accept( | 1366 DartObjectImpl result = expression.accept( |
| 1352 new _ConstantVerifier_validateInitializerExpression(_typeProvider, | 1367 new _ConstantVerifier_validateInitializerExpression( |
| 1353 subErrorReporter, this, parameterElements, declaredVariables)); | 1368 _typeProvider, |
| 1369 _typeSystem, | |
| 1370 subErrorReporter, | |
| 1371 this, | |
| 1372 parameterElements, | |
| 1373 declaredVariables)); | |
| 1354 _reportErrors(errorListener.errors, | 1374 _reportErrors(errorListener.errors, |
| 1355 CompileTimeErrorCode.NON_CONSTANT_VALUE_IN_INITIALIZER); | 1375 CompileTimeErrorCode.NON_CONSTANT_VALUE_IN_INITIALIZER); |
| 1356 if (result != null) { | 1376 if (result != null) { |
| 1357 _reportErrorIfFromDeferredLibrary(expression, | 1377 _reportErrorIfFromDeferredLibrary(expression, |
| 1358 CompileTimeErrorCode.NON_CONSTANT_VALUE_IN_INITIALIZER_FROM_DEFERRED_L IBRARY); | 1378 CompileTimeErrorCode.NON_CONSTANT_VALUE_IN_INITIALIZER_FROM_DEFERRED_L IBRARY); |
| 1359 } | 1379 } |
| 1360 } | 1380 } |
| 1361 | 1381 |
| 1362 /** | 1382 /** |
| 1363 * Validates that all of the arguments of a constructor initializer are compil e time constants. | 1383 * Validates that all of the arguments of a constructor initializer are compil e time constants. |
| (...skipping 104 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
| 1468 * Instances of the class `DeadCodeVerifier` traverse an AST structure looking f or cases of | 1488 * Instances of the class `DeadCodeVerifier` traverse an AST structure looking f or cases of |
| 1469 * [HintCode.DEAD_CODE]. | 1489 * [HintCode.DEAD_CODE]. |
| 1470 */ | 1490 */ |
| 1471 class DeadCodeVerifier extends RecursiveAstVisitor<Object> { | 1491 class DeadCodeVerifier extends RecursiveAstVisitor<Object> { |
| 1472 /** | 1492 /** |
| 1473 * The error reporter by which errors will be reported. | 1493 * The error reporter by which errors will be reported. |
| 1474 */ | 1494 */ |
| 1475 final ErrorReporter _errorReporter; | 1495 final ErrorReporter _errorReporter; |
| 1476 | 1496 |
| 1477 /** | 1497 /** |
| 1498 * The type system for this visitor | |
| 1499 */ | |
| 1500 final TypeSystem _typeSystem; | |
| 1501 | |
| 1502 /** | |
| 1478 * Create a new instance of the [DeadCodeVerifier]. | 1503 * Create a new instance of the [DeadCodeVerifier]. |
| 1479 * | 1504 * |
| 1480 * @param errorReporter the error reporter | 1505 * @param errorReporter the error reporter |
| 1481 */ | 1506 */ |
| 1482 DeadCodeVerifier(this._errorReporter); | 1507 DeadCodeVerifier(this._errorReporter, this._typeSystem); |
| 1483 | 1508 |
| 1484 @override | 1509 @override |
| 1485 Object visitBinaryExpression(BinaryExpression node) { | 1510 Object visitBinaryExpression(BinaryExpression node) { |
| 1486 sc.Token operator = node.operator; | 1511 sc.Token operator = node.operator; |
| 1487 bool isAmpAmp = operator.type == sc.TokenType.AMPERSAND_AMPERSAND; | 1512 bool isAmpAmp = operator.type == sc.TokenType.AMPERSAND_AMPERSAND; |
| 1488 bool isBarBar = operator.type == sc.TokenType.BAR_BAR; | 1513 bool isBarBar = operator.type == sc.TokenType.BAR_BAR; |
| 1489 if (isAmpAmp || isBarBar) { | 1514 if (isAmpAmp || isBarBar) { |
| 1490 Expression lhsCondition = node.leftOperand; | 1515 Expression lhsCondition = node.leftOperand; |
| 1491 if (!_isDebugConstant(lhsCondition)) { | 1516 if (!_isDebugConstant(lhsCondition)) { |
| 1492 EvaluationResultImpl lhsResult = _getConstantBooleanValue(lhsCondition); | 1517 EvaluationResultImpl lhsResult = _getConstantBooleanValue(lhsCondition); |
| (...skipping 144 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
| 1637 CatchClause nextCatchClause = catchClauses[i + 1]; | 1662 CatchClause nextCatchClause = catchClauses[i + 1]; |
| 1638 CatchClause lastCatchClause = catchClauses[numOfCatchClauses - 1]; | 1663 CatchClause lastCatchClause = catchClauses[numOfCatchClauses - 1]; |
| 1639 int offset = nextCatchClause.offset; | 1664 int offset = nextCatchClause.offset; |
| 1640 int length = lastCatchClause.end - offset; | 1665 int length = lastCatchClause.end - offset; |
| 1641 _errorReporter.reportErrorForOffset( | 1666 _errorReporter.reportErrorForOffset( |
| 1642 HintCode.DEAD_CODE_CATCH_FOLLOWING_CATCH, offset, length); | 1667 HintCode.DEAD_CODE_CATCH_FOLLOWING_CATCH, offset, length); |
| 1643 return null; | 1668 return null; |
| 1644 } | 1669 } |
| 1645 } | 1670 } |
| 1646 for (DartType type in visitedTypes) { | 1671 for (DartType type in visitedTypes) { |
| 1647 if (currentType.isSubtypeOf(type)) { | 1672 if (_typeSystem.isSubtypeOf(currentType, type)) { |
| 1648 CatchClause lastCatchClause = catchClauses[numOfCatchClauses - 1]; | 1673 CatchClause lastCatchClause = catchClauses[numOfCatchClauses - 1]; |
| 1649 int offset = catchClause.offset; | 1674 int offset = catchClause.offset; |
| 1650 int length = lastCatchClause.end - offset; | 1675 int length = lastCatchClause.end - offset; |
| 1651 _errorReporter.reportErrorForOffset( | 1676 _errorReporter.reportErrorForOffset( |
| 1652 HintCode.DEAD_CODE_ON_CATCH_SUBTYPE, | 1677 HintCode.DEAD_CODE_ON_CATCH_SUBTYPE, |
| 1653 offset, | 1678 offset, |
| 1654 length, | 1679 length, |
| 1655 [currentType.displayName, type.displayName]); | 1680 [currentType.displayName, type.displayName]); |
| 1656 return null; | 1681 return null; |
| 1657 } | 1682 } |
| (...skipping 3134 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
| 4792 } | 4817 } |
| 4793 _library.accept(new UnusedLocalElementsVerifier( | 4818 _library.accept(new UnusedLocalElementsVerifier( |
| 4794 _errorListener, _usedLocalElementsVisitor.usedElements)); | 4819 _errorListener, _usedLocalElementsVisitor.usedElements)); |
| 4795 }); | 4820 }); |
| 4796 } | 4821 } |
| 4797 | 4822 |
| 4798 void _generateForCompilationUnit(CompilationUnit unit, Source source) { | 4823 void _generateForCompilationUnit(CompilationUnit unit, Source source) { |
| 4799 ErrorReporter errorReporter = new ErrorReporter(_errorListener, source); | 4824 ErrorReporter errorReporter = new ErrorReporter(_errorListener, source); |
| 4800 unit.accept(_usedImportedElementsVisitor); | 4825 unit.accept(_usedImportedElementsVisitor); |
| 4801 // dead code analysis | 4826 // dead code analysis |
| 4802 unit.accept(new DeadCodeVerifier(errorReporter)); | 4827 unit.accept(new DeadCodeVerifier(errorReporter, _context.typeSystem)); |
| 4803 unit.accept(_usedLocalElementsVisitor); | 4828 unit.accept(_usedLocalElementsVisitor); |
| 4804 // dart2js analysis | 4829 // dart2js analysis |
| 4805 if (_enableDart2JSHints) { | 4830 if (_enableDart2JSHints) { |
| 4806 unit.accept(new Dart2JSVerifier(errorReporter)); | 4831 unit.accept(new Dart2JSVerifier(errorReporter)); |
| 4807 } | 4832 } |
| 4808 // Dart best practices | 4833 // Dart best practices |
| 4809 unit.accept( | 4834 unit.accept(new BestPracticesVerifier( |
| 4810 new BestPracticesVerifier(errorReporter, _context.typeProvider)); | 4835 errorReporter, _context.typeProvider, _context.typeSystem)); |
| 4811 unit.accept(new OverrideVerifier(errorReporter, _manager)); | 4836 unit.accept(new OverrideVerifier(errorReporter, _manager)); |
| 4812 // Find to-do comments | 4837 // Find to-do comments |
| 4813 new ToDoFinder(errorReporter).findIn(unit); | 4838 new ToDoFinder(errorReporter).findIn(unit); |
| 4814 // pub analysis | 4839 // pub analysis |
| 4815 // TODO(danrubel/jwren) Commented out until bugs in the pub verifier are | 4840 // TODO(danrubel/jwren) Commented out until bugs in the pub verifier are |
| 4816 // fixed | 4841 // fixed |
| 4817 // unit.accept(new PubVerifier(context, errorReporter)); | 4842 // unit.accept(new PubVerifier(context, errorReporter)); |
| 4818 } | 4843 } |
| 4819 } | 4844 } |
| 4820 | 4845 |
| (...skipping 1440 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
| 6261 for (int i = 0; i < numOfEltsWithMatchingNames; i++) { | 6286 for (int i = 0; i < numOfEltsWithMatchingNames; i++) { |
| 6262 executableElementTypes[i] = elements[i].type; | 6287 executableElementTypes[i] = elements[i].type; |
| 6263 } | 6288 } |
| 6264 List<int> subtypesOfAllOtherTypesIndexes = new List<int>(); | 6289 List<int> subtypesOfAllOtherTypesIndexes = new List<int>(); |
| 6265 for (int i = 0; i < numOfEltsWithMatchingNames; i++) { | 6290 for (int i = 0; i < numOfEltsWithMatchingNames; i++) { |
| 6266 FunctionType subtype = executableElementTypes[i]; | 6291 FunctionType subtype = executableElementTypes[i]; |
| 6267 if (subtype == null) { | 6292 if (subtype == null) { |
| 6268 continue; | 6293 continue; |
| 6269 } | 6294 } |
| 6270 bool subtypeOfAllTypes = true; | 6295 bool subtypeOfAllTypes = true; |
| 6296 TypeSystem typeSystem = _library.context.typeSystem; | |
| 6271 for (int j = 0; | 6297 for (int j = 0; |
| 6272 j < numOfEltsWithMatchingNames && subtypeOfAllTypes; | 6298 j < numOfEltsWithMatchingNames && subtypeOfAllTypes; |
| 6273 j++) { | 6299 j++) { |
| 6274 if (i != j) { | 6300 if (i != j) { |
| 6275 if (!subtype.isSubtypeOf(executableElementTypes[j])) { | 6301 if (!typeSystem.isSubtypeOf( |
| 6302 subtype, executableElementTypes[j])) { | |
| 6276 subtypeOfAllTypes = false; | 6303 subtypeOfAllTypes = false; |
| 6277 break; | 6304 break; |
| 6278 } | 6305 } |
| 6279 } | 6306 } |
| 6280 } | 6307 } |
| 6281 if (subtypeOfAllTypes) { | 6308 if (subtypeOfAllTypes) { |
| 6282 subtypesOfAllOtherTypesIndexes.add(i); | 6309 subtypesOfAllOtherTypesIndexes.add(i); |
| 6283 } | 6310 } |
| 6284 } | 6311 } |
| 6285 // | 6312 // |
| (...skipping 1277 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
| 7563 * The object representing the async library. | 7590 * The object representing the async library. |
| 7564 */ | 7591 */ |
| 7565 Library _asyncLibrary; | 7592 Library _asyncLibrary; |
| 7566 | 7593 |
| 7567 /** | 7594 /** |
| 7568 * The object used to access the types from the core library. | 7595 * The object used to access the types from the core library. |
| 7569 */ | 7596 */ |
| 7570 TypeProvider _typeProvider; | 7597 TypeProvider _typeProvider; |
| 7571 | 7598 |
| 7572 /** | 7599 /** |
| 7600 * The type system in use for the library | |
| 7601 */ | |
| 7602 TypeSystem _typeSystem; | |
| 7603 | |
| 7604 /** | |
| 7573 * A table mapping library sources to the information being maintained for tho se libraries. | 7605 * A table mapping library sources to the information being maintained for tho se libraries. |
| 7574 */ | 7606 */ |
| 7575 HashMap<Source, Library> _libraryMap = new HashMap<Source, Library>(); | 7607 HashMap<Source, Library> _libraryMap = new HashMap<Source, Library>(); |
| 7576 | 7608 |
| 7577 /** | 7609 /** |
| 7578 * A collection containing the libraries that are being resolved together. | 7610 * A collection containing the libraries that are being resolved together. |
| 7579 */ | 7611 */ |
| 7580 Set<Library> _librariesInCycles; | 7612 Set<Library> _librariesInCycles; |
| 7581 | 7613 |
| 7582 /** | 7614 /** |
| (...skipping 22 matching lines...) Expand all Loading... | |
| 7605 * @return an array containing the libraries that were resolved | 7637 * @return an array containing the libraries that were resolved |
| 7606 */ | 7638 */ |
| 7607 Set<Library> get resolvedLibraries => _librariesInCycles; | 7639 Set<Library> get resolvedLibraries => _librariesInCycles; |
| 7608 | 7640 |
| 7609 /** | 7641 /** |
| 7610 * The object used to access the types from the core library. | 7642 * The object used to access the types from the core library. |
| 7611 */ | 7643 */ |
| 7612 TypeProvider get typeProvider => _typeProvider; | 7644 TypeProvider get typeProvider => _typeProvider; |
| 7613 | 7645 |
| 7614 /** | 7646 /** |
| 7647 * The type system in use. | |
| 7648 */ | |
| 7649 TypeSystem get typeSystem => _typeSystem; | |
| 7650 | |
| 7651 /** | |
| 7615 * Create an object to represent the information about the library defined by the compilation unit | 7652 * Create an object to represent the information about the library defined by the compilation unit |
| 7616 * with the given source. | 7653 * with the given source. |
| 7617 * | 7654 * |
| 7618 * @param librarySource the source of the library's defining compilation unit | 7655 * @param librarySource the source of the library's defining compilation unit |
| 7619 * @return the library object that was created | 7656 * @return the library object that was created |
| 7620 * @throws AnalysisException if the library source is not valid | 7657 * @throws AnalysisException if the library source is not valid |
| 7621 */ | 7658 */ |
| 7622 Library createLibrary(Source librarySource) { | 7659 Library createLibrary(Source librarySource) { |
| 7623 Library library = | 7660 Library library = |
| 7624 new Library(analysisContext, _errorListener, librarySource); | 7661 new Library(analysisContext, _errorListener, librarySource); |
| (...skipping 64 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
| 7689 LibraryElement coreElement = _coreLibrary.libraryElement; | 7726 LibraryElement coreElement = _coreLibrary.libraryElement; |
| 7690 if (coreElement == null) { | 7727 if (coreElement == null) { |
| 7691 throw new AnalysisException("Could not resolve dart:core"); | 7728 throw new AnalysisException("Could not resolve dart:core"); |
| 7692 } | 7729 } |
| 7693 LibraryElement asyncElement = _asyncLibrary.libraryElement; | 7730 LibraryElement asyncElement = _asyncLibrary.libraryElement; |
| 7694 if (asyncElement == null) { | 7731 if (asyncElement == null) { |
| 7695 throw new AnalysisException("Could not resolve dart:async"); | 7732 throw new AnalysisException("Could not resolve dart:async"); |
| 7696 } | 7733 } |
| 7697 _buildDirectiveModels(); | 7734 _buildDirectiveModels(); |
| 7698 _typeProvider = new TypeProviderImpl(coreElement, asyncElement); | 7735 _typeProvider = new TypeProviderImpl(coreElement, asyncElement); |
| 7736 _typeSystem = TypeSystem.create(analysisContext); | |
| 7699 _buildTypeHierarchies(); | 7737 _buildTypeHierarchies(); |
| 7700 // | 7738 // |
| 7701 // Perform resolution and type analysis. | 7739 // Perform resolution and type analysis. |
| 7702 // | 7740 // |
| 7703 // TODO(brianwilkerson) Decide whether we want to resolve all of the | 7741 // TODO(brianwilkerson) Decide whether we want to resolve all of the |
| 7704 // libraries or whether we want to only resolve the target library. | 7742 // libraries or whether we want to only resolve the target library. |
| 7705 // The advantage to resolving everything is that we have already done part | 7743 // The advantage to resolving everything is that we have already done part |
| 7706 // of the work so we'll avoid duplicated effort. The disadvantage of | 7744 // of the work so we'll avoid duplicated effort. The disadvantage of |
| 7707 // resolving everything is that we might do extra work that we don't | 7745 // resolving everything is that we might do extra work that we don't |
| 7708 // really care about. Another possibility is to add a parameter to this | 7746 // really care about. Another possibility is to add a parameter to this |
| (...skipping 58 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
| 7767 LibraryElement coreElement = _coreLibrary.libraryElement; | 7805 LibraryElement coreElement = _coreLibrary.libraryElement; |
| 7768 if (coreElement == null) { | 7806 if (coreElement == null) { |
| 7769 throw new AnalysisException("Could not resolve dart:core"); | 7807 throw new AnalysisException("Could not resolve dart:core"); |
| 7770 } | 7808 } |
| 7771 LibraryElement asyncElement = _asyncLibrary.libraryElement; | 7809 LibraryElement asyncElement = _asyncLibrary.libraryElement; |
| 7772 if (asyncElement == null) { | 7810 if (asyncElement == null) { |
| 7773 throw new AnalysisException("Could not resolve dart:async"); | 7811 throw new AnalysisException("Could not resolve dart:async"); |
| 7774 } | 7812 } |
| 7775 _buildDirectiveModels(); | 7813 _buildDirectiveModels(); |
| 7776 _typeProvider = new TypeProviderImpl(coreElement, asyncElement); | 7814 _typeProvider = new TypeProviderImpl(coreElement, asyncElement); |
| 7815 _typeSystem = TypeSystem.create(analysisContext); | |
| 7777 _buildEnumMembers(); | 7816 _buildEnumMembers(); |
| 7778 _buildTypeHierarchies(); | 7817 _buildTypeHierarchies(); |
| 7779 // | 7818 // |
| 7780 // Perform resolution and type analysis. | 7819 // Perform resolution and type analysis. |
| 7781 // | 7820 // |
| 7782 // TODO(brianwilkerson) Decide whether we want to resolve all of the | 7821 // TODO(brianwilkerson) Decide whether we want to resolve all of the |
| 7783 // libraries or whether we want to only resolve the target library. The | 7822 // libraries or whether we want to only resolve the target library. The |
| 7784 // advantage to resolving everything is that we have already done part of | 7823 // advantage to resolving everything is that we have already done part of |
| 7785 // the work so we'll avoid duplicated effort. The disadvantage of | 7824 // the work so we'll avoid duplicated effort. The disadvantage of |
| 7786 // resolving everything is that we might do extra work that we don't | 7825 // resolving everything is that we might do extra work that we don't |
| (...skipping 492 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
| 8279 } | 8318 } |
| 8280 return identifiers; | 8319 return identifiers; |
| 8281 } | 8320 } |
| 8282 | 8321 |
| 8283 /** | 8322 /** |
| 8284 * Compute a value for all of the constants in the libraries being analyzed. | 8323 * Compute a value for all of the constants in the libraries being analyzed. |
| 8285 */ | 8324 */ |
| 8286 void _performConstantEvaluation() { | 8325 void _performConstantEvaluation() { |
| 8287 PerformanceStatistics.resolve.makeCurrentWhile(() { | 8326 PerformanceStatistics.resolve.makeCurrentWhile(() { |
| 8288 ConstantValueComputer computer = new ConstantValueComputer( | 8327 ConstantValueComputer computer = new ConstantValueComputer( |
| 8289 analysisContext, _typeProvider, analysisContext.declaredVariables); | 8328 analysisContext, |
| 8329 _typeProvider, | |
| 8330 _typeSystem, | |
| 8331 analysisContext.declaredVariables); | |
| 8290 for (Library library in _librariesInCycles) { | 8332 for (Library library in _librariesInCycles) { |
| 8291 for (Source source in library.compilationUnitSources) { | 8333 for (Source source in library.compilationUnitSources) { |
| 8292 try { | 8334 try { |
| 8293 CompilationUnit unit = library.getAST(source); | 8335 CompilationUnit unit = library.getAST(source); |
| 8294 if (unit != null) { | 8336 if (unit != null) { |
| 8295 computer.add(unit, source, library.librarySource); | 8337 computer.add(unit, source, library.librarySource); |
| 8296 } | 8338 } |
| 8297 } on AnalysisException catch (exception, stackTrace) { | 8339 } on AnalysisException catch (exception, stackTrace) { |
| 8298 AnalysisEngine.instance.logger.logError( | 8340 AnalysisEngine.instance.logger.logError( |
| 8299 "Internal Error: Could not access AST for ${source.fullName} dur ing constant evaluation", | 8341 "Internal Error: Could not access AST for ${source.fullName} dur ing constant evaluation", |
| 8300 new CaughtException(exception, stackTrace)); | 8342 new CaughtException(exception, stackTrace)); |
| 8301 } | 8343 } |
| 8302 } | 8344 } |
| 8303 } | 8345 } |
| 8304 computer.computeValues(); | 8346 computer.computeValues(); |
| 8305 // As a temporary workaround for issue 21572, run ConstantVerifier now. | 8347 // As a temporary workaround for issue 21572, run ConstantVerifier now. |
| 8306 // TODO(paulberry): remove this workaround once issue 21572 is fixed. | 8348 // TODO(paulberry): remove this workaround once issue 21572 is fixed. |
| 8307 for (Library library in _librariesInCycles) { | 8349 for (Library library in _librariesInCycles) { |
| 8308 for (Source source in library.compilationUnitSources) { | 8350 for (Source source in library.compilationUnitSources) { |
| 8309 try { | 8351 try { |
| 8310 CompilationUnit unit = library.getAST(source); | 8352 CompilationUnit unit = library.getAST(source); |
| 8311 ErrorReporter errorReporter = | 8353 ErrorReporter errorReporter = |
| 8312 new ErrorReporter(_errorListener, source); | 8354 new ErrorReporter(_errorListener, source); |
| 8313 ConstantVerifier constantVerifier = new ConstantVerifier( | 8355 ConstantVerifier constantVerifier = new ConstantVerifier( |
| 8314 errorReporter, | 8356 errorReporter, |
| 8315 library.libraryElement, | 8357 library.libraryElement, |
| 8316 _typeProvider, | 8358 _typeProvider, |
| 8359 _typeSystem, | |
| 8317 analysisContext.declaredVariables); | 8360 analysisContext.declaredVariables); |
| 8318 unit.accept(constantVerifier); | 8361 unit.accept(constantVerifier); |
| 8319 } on AnalysisException catch (exception, stackTrace) { | 8362 } on AnalysisException catch (exception, stackTrace) { |
| 8320 AnalysisEngine.instance.logger.logError( | 8363 AnalysisEngine.instance.logger.logError( |
| 8321 "Internal Error: Could not access AST for ${source.fullName} " | 8364 "Internal Error: Could not access AST for ${source.fullName} " |
| 8322 "during constant verification", | 8365 "during constant verification", |
| 8323 new CaughtException(exception, stackTrace)); | 8366 new CaughtException(exception, stackTrace)); |
| 8324 } | 8367 } |
| 8325 } | 8368 } |
| 8326 } | 8369 } |
| (...skipping 12 matching lines...) Expand all Loading... | |
| 8339 for (Source source in library.compilationUnitSources) { | 8382 for (Source source in library.compilationUnitSources) { |
| 8340 CompilationUnit ast = library.getAST(source); | 8383 CompilationUnit ast = library.getAST(source); |
| 8341 ast.accept(new VariableResolverVisitor(library.libraryElement, source, | 8384 ast.accept(new VariableResolverVisitor(library.libraryElement, source, |
| 8342 _typeProvider, library.errorListener, | 8385 _typeProvider, library.errorListener, |
| 8343 nameScope: library.libraryScope)); | 8386 nameScope: library.libraryScope)); |
| 8344 ResolverVisitorFactory visitorFactory = | 8387 ResolverVisitorFactory visitorFactory = |
| 8345 analysisContext.resolverVisitorFactory; | 8388 analysisContext.resolverVisitorFactory; |
| 8346 ResolverVisitor visitor = visitorFactory != null | 8389 ResolverVisitor visitor = visitorFactory != null |
| 8347 ? visitorFactory(library, source, _typeProvider) | 8390 ? visitorFactory(library, source, _typeProvider) |
| 8348 : new ResolverVisitor(library.libraryElement, source, _typeProvider, | 8391 : new ResolverVisitor(library.libraryElement, source, _typeProvider, |
| 8349 library.errorListener, | 8392 _typeSystem, library.errorListener, |
| 8350 nameScope: library.libraryScope, | 8393 nameScope: library.libraryScope, |
| 8351 inheritanceManager: library.inheritanceManager); | 8394 inheritanceManager: library.inheritanceManager); |
| 8352 ast.accept(visitor); | 8395 ast.accept(visitor); |
| 8353 } | 8396 } |
| 8354 }); | 8397 }); |
| 8355 } | 8398 } |
| 8356 | 8399 |
| 8357 /** | 8400 /** |
| 8358 * Return the result of resolving the URI of the given URI-based directive aga inst the URI of the | 8401 * Return the result of resolving the URI of the given URI-based directive aga inst the URI of the |
| 8359 * given library, or `null` if the URI is not valid. | 8402 * given library, or `null` if the URI is not valid. |
| (...skipping 52 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
| 8412 * The object representing the async library. | 8455 * The object representing the async library. |
| 8413 */ | 8456 */ |
| 8414 ResolvableLibrary _asyncLibrary; | 8457 ResolvableLibrary _asyncLibrary; |
| 8415 | 8458 |
| 8416 /** | 8459 /** |
| 8417 * The object used to access the types from the core library. | 8460 * The object used to access the types from the core library. |
| 8418 */ | 8461 */ |
| 8419 TypeProvider _typeProvider; | 8462 TypeProvider _typeProvider; |
| 8420 | 8463 |
| 8421 /** | 8464 /** |
| 8465 * The type system in use for the library | |
| 8466 */ | |
| 8467 TypeSystem _typeSystem; | |
| 8468 | |
| 8469 /** | |
| 8422 * A table mapping library sources to the information being maintained for tho se libraries. | 8470 * A table mapping library sources to the information being maintained for tho se libraries. |
| 8423 */ | 8471 */ |
| 8424 HashMap<Source, ResolvableLibrary> _libraryMap = | 8472 HashMap<Source, ResolvableLibrary> _libraryMap = |
| 8425 new HashMap<Source, ResolvableLibrary>(); | 8473 new HashMap<Source, ResolvableLibrary>(); |
| 8426 | 8474 |
| 8427 /** | 8475 /** |
| 8428 * A collection containing the libraries that are being resolved together. | 8476 * A collection containing the libraries that are being resolved together. |
| 8429 */ | 8477 */ |
| 8430 List<ResolvableLibrary> _librariesInCycle; | 8478 List<ResolvableLibrary> _librariesInCycle; |
| 8431 | 8479 |
| (...skipping 69 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
| 8501 LibraryElement coreElement = _coreLibrary.libraryElement; | 8549 LibraryElement coreElement = _coreLibrary.libraryElement; |
| 8502 if (coreElement == null) { | 8550 if (coreElement == null) { |
| 8503 missingCoreLibrary(analysisContext, _coreLibrarySource); | 8551 missingCoreLibrary(analysisContext, _coreLibrarySource); |
| 8504 } | 8552 } |
| 8505 LibraryElement asyncElement = _asyncLibrary.libraryElement; | 8553 LibraryElement asyncElement = _asyncLibrary.libraryElement; |
| 8506 if (asyncElement == null) { | 8554 if (asyncElement == null) { |
| 8507 missingAsyncLibrary(analysisContext, _asyncLibrarySource); | 8555 missingAsyncLibrary(analysisContext, _asyncLibrarySource); |
| 8508 } | 8556 } |
| 8509 _buildDirectiveModels(); | 8557 _buildDirectiveModels(); |
| 8510 _typeProvider = new TypeProviderImpl(coreElement, asyncElement); | 8558 _typeProvider = new TypeProviderImpl(coreElement, asyncElement); |
| 8559 _typeSystem = TypeSystem.create(analysisContext); | |
| 8511 _buildEnumMembers(); | 8560 _buildEnumMembers(); |
| 8512 _buildTypeHierarchies(); | 8561 _buildTypeHierarchies(); |
| 8513 // | 8562 // |
| 8514 // Perform resolution and type analysis. | 8563 // Perform resolution and type analysis. |
| 8515 // | 8564 // |
| 8516 // TODO(brianwilkerson) Decide whether we want to resolve all of the | 8565 // TODO(brianwilkerson) Decide whether we want to resolve all of the |
| 8517 // libraries or whether we want to only resolve the target library. The | 8566 // libraries or whether we want to only resolve the target library. The |
| 8518 // advantage to resolving everything is that we have already done part of | 8567 // advantage to resolving everything is that we have already done part of |
| 8519 // the work so we'll avoid duplicated effort. The disadvantage of | 8568 // the work so we'll avoid duplicated effort. The disadvantage of |
| 8520 // resolving everything is that we might do extra work that we don't | 8569 // resolving everything is that we might do extra work that we don't |
| (...skipping 253 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
| 8774 } | 8823 } |
| 8775 return identifiers; | 8824 return identifiers; |
| 8776 } | 8825 } |
| 8777 | 8826 |
| 8778 /** | 8827 /** |
| 8779 * Compute a value for all of the constants in the libraries being analyzed. | 8828 * Compute a value for all of the constants in the libraries being analyzed. |
| 8780 */ | 8829 */ |
| 8781 void _performConstantEvaluation() { | 8830 void _performConstantEvaluation() { |
| 8782 PerformanceStatistics.resolve.makeCurrentWhile(() { | 8831 PerformanceStatistics.resolve.makeCurrentWhile(() { |
| 8783 ConstantValueComputer computer = new ConstantValueComputer( | 8832 ConstantValueComputer computer = new ConstantValueComputer( |
| 8784 analysisContext, _typeProvider, analysisContext.declaredVariables); | 8833 analysisContext, |
| 8834 _typeProvider, | |
| 8835 _typeSystem, | |
| 8836 analysisContext.declaredVariables); | |
| 8785 for (ResolvableLibrary library in _librariesInCycle) { | 8837 for (ResolvableLibrary library in _librariesInCycle) { |
| 8786 for (ResolvableCompilationUnit unit | 8838 for (ResolvableCompilationUnit unit |
| 8787 in library.resolvableCompilationUnits) { | 8839 in library.resolvableCompilationUnits) { |
| 8788 CompilationUnit ast = unit.compilationUnit; | 8840 CompilationUnit ast = unit.compilationUnit; |
| 8789 if (ast != null) { | 8841 if (ast != null) { |
| 8790 computer.add(ast, unit.source, library.librarySource); | 8842 computer.add(ast, unit.source, library.librarySource); |
| 8791 } | 8843 } |
| 8792 } | 8844 } |
| 8793 } | 8845 } |
| 8794 computer.computeValues(); | 8846 computer.computeValues(); |
| 8795 // As a temporary workaround for issue 21572, run ConstantVerifier now. | 8847 // As a temporary workaround for issue 21572, run ConstantVerifier now. |
| 8796 // TODO(paulberry): remove this workaround once issue 21572 is fixed. | 8848 // TODO(paulberry): remove this workaround once issue 21572 is fixed. |
| 8797 for (ResolvableLibrary library in _librariesInCycle) { | 8849 for (ResolvableLibrary library in _librariesInCycle) { |
| 8798 for (ResolvableCompilationUnit unit | 8850 for (ResolvableCompilationUnit unit |
| 8799 in library.resolvableCompilationUnits) { | 8851 in library.resolvableCompilationUnits) { |
| 8800 CompilationUnit ast = unit.compilationUnit; | 8852 CompilationUnit ast = unit.compilationUnit; |
| 8801 ErrorReporter errorReporter = | 8853 ErrorReporter errorReporter = |
| 8802 new ErrorReporter(_errorListener, unit.source); | 8854 new ErrorReporter(_errorListener, unit.source); |
| 8803 ConstantVerifier constantVerifier = new ConstantVerifier( | 8855 ConstantVerifier constantVerifier = new ConstantVerifier( |
| 8804 errorReporter, | 8856 errorReporter, |
| 8805 library.libraryElement, | 8857 library.libraryElement, |
| 8806 _typeProvider, | 8858 _typeProvider, |
| 8859 _typeSystem, | |
| 8807 analysisContext.declaredVariables); | 8860 analysisContext.declaredVariables); |
| 8808 ast.accept(constantVerifier); | 8861 ast.accept(constantVerifier); |
| 8809 } | 8862 } |
| 8810 } | 8863 } |
| 8811 }); | 8864 }); |
| 8812 } | 8865 } |
| 8813 | 8866 |
| 8814 /** | 8867 /** |
| 8815 * Resolve the identifiers and perform type analysis in the libraries in the c urrent cycle. | 8868 * Resolve the identifiers and perform type analysis in the libraries in the c urrent cycle. |
| 8816 * | 8869 * |
| (...skipping 15 matching lines...) Expand all Loading... | |
| 8832 */ | 8885 */ |
| 8833 void _resolveReferencesAndTypesInLibrary(ResolvableLibrary library) { | 8886 void _resolveReferencesAndTypesInLibrary(ResolvableLibrary library) { |
| 8834 PerformanceStatistics.resolve.makeCurrentWhile(() { | 8887 PerformanceStatistics.resolve.makeCurrentWhile(() { |
| 8835 for (ResolvableCompilationUnit unit | 8888 for (ResolvableCompilationUnit unit |
| 8836 in library.resolvableCompilationUnits) { | 8889 in library.resolvableCompilationUnits) { |
| 8837 Source source = unit.source; | 8890 Source source = unit.source; |
| 8838 CompilationUnit ast = unit.compilationUnit; | 8891 CompilationUnit ast = unit.compilationUnit; |
| 8839 ast.accept(new VariableResolverVisitor(library.libraryElement, source, | 8892 ast.accept(new VariableResolverVisitor(library.libraryElement, source, |
| 8840 _typeProvider, library.libraryScope.errorListener, | 8893 _typeProvider, library.libraryScope.errorListener, |
| 8841 nameScope: library.libraryScope)); | 8894 nameScope: library.libraryScope)); |
| 8842 ResolverVisitor visitor = new ResolverVisitor(library.libraryElement, | 8895 ResolverVisitor visitor = new ResolverVisitor( |
| 8843 source, _typeProvider, library._libraryScope.errorListener, | 8896 library.libraryElement, |
| 8897 source, | |
| 8898 _typeProvider, | |
| 8899 _typeSystem, | |
| 8900 library._libraryScope.errorListener, | |
| 8844 nameScope: library._libraryScope, | 8901 nameScope: library._libraryScope, |
| 8845 inheritanceManager: library.inheritanceManager); | 8902 inheritanceManager: library.inheritanceManager); |
| 8846 ast.accept(visitor); | 8903 ast.accept(visitor); |
| 8847 } | 8904 } |
| 8848 }); | 8905 }); |
| 8849 } | 8906 } |
| 8850 | 8907 |
| 8851 /** | 8908 /** |
| 8852 * Report that the async library could not be resolved in the given | 8909 * Report that the async library could not be resolved in the given |
| 8853 * [analysisContext] and throw an exception. [asyncLibrarySource] is the sour ce | 8910 * [analysisContext] and throw an exception. [asyncLibrarySource] is the sour ce |
| (...skipping 728 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
| 9582 * listener that will be informed of any errors that are found during | 9639 * listener that will be informed of any errors that are found during |
| 9583 * resolution. The [nameScope] is the scope used to resolve identifiers in the | 9640 * resolution. The [nameScope] is the scope used to resolve identifiers in the |
| 9584 * node that will first be visited. If `null` or unspecified, a new | 9641 * node that will first be visited. If `null` or unspecified, a new |
| 9585 * [LibraryScope] will be created based on [definingLibrary] and | 9642 * [LibraryScope] will be created based on [definingLibrary] and |
| 9586 * [typeProvider]. The [inheritanceManager] is used to perform inheritance | 9643 * [typeProvider]. The [inheritanceManager] is used to perform inheritance |
| 9587 * lookups. If `null` or unspecified, a new [InheritanceManager] will be | 9644 * lookups. If `null` or unspecified, a new [InheritanceManager] will be |
| 9588 * created based on [definingLibrary]. The [typeAnalyzerFactory] is used to | 9645 * created based on [definingLibrary]. The [typeAnalyzerFactory] is used to |
| 9589 * create the type analyzer. If `null` or unspecified, a type analyzer of | 9646 * create the type analyzer. If `null` or unspecified, a type analyzer of |
| 9590 * type [StaticTypeAnalyzer] will be created. | 9647 * type [StaticTypeAnalyzer] will be created. |
| 9591 */ | 9648 */ |
| 9592 PartialResolverVisitor(LibraryElement definingLibrary, Source source, | 9649 PartialResolverVisitor( |
| 9593 TypeProvider typeProvider, AnalysisErrorListener errorListener, | 9650 LibraryElement definingLibrary, |
| 9651 Source source, | |
| 9652 TypeProvider typeProvider, | |
| 9653 TypeSystem typeSystem, | |
| 9654 AnalysisErrorListener errorListener, | |
| 9594 {Scope nameScope, | 9655 {Scope nameScope, |
| 9595 InheritanceManager inheritanceManager, | 9656 InheritanceManager inheritanceManager, |
| 9596 StaticTypeAnalyzerFactory typeAnalyzerFactory}) | 9657 StaticTypeAnalyzerFactory typeAnalyzerFactory}) |
| 9597 : strongMode = definingLibrary.context.analysisOptions.strongMode, | 9658 : strongMode = definingLibrary.context.analysisOptions.strongMode, |
| 9598 super(definingLibrary, source, typeProvider, | 9659 super(definingLibrary, source, typeProvider, typeSystem, |
| 9599 new DisablableErrorListener(errorListener)); | 9660 new DisablableErrorListener(errorListener)); |
| 9600 | 9661 |
| 9601 @override | 9662 @override |
| 9602 Object visitBlockFunctionBody(BlockFunctionBody node) { | 9663 Object visitBlockFunctionBody(BlockFunctionBody node) { |
| 9603 if (_shouldBeSkipped(node)) { | 9664 if (_shouldBeSkipped(node)) { |
| 9604 return null; | 9665 return null; |
| 9605 } | 9666 } |
| 9606 return super.visitBlockFunctionBody(node); | 9667 return super.visitBlockFunctionBody(node); |
| 9607 } | 9668 } |
| 9608 | 9669 |
| (...skipping 678 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
| 10287 * listener that will be informed of any errors that are found during | 10348 * listener that will be informed of any errors that are found during |
| 10288 * resolution. The [nameScope] is the scope used to resolve identifiers in the | 10349 * resolution. The [nameScope] is the scope used to resolve identifiers in the |
| 10289 * node that will first be visited. If `null` or unspecified, a new | 10350 * node that will first be visited. If `null` or unspecified, a new |
| 10290 * [LibraryScope] will be created based on [definingLibrary] and | 10351 * [LibraryScope] will be created based on [definingLibrary] and |
| 10291 * [typeProvider]. The [inheritanceManager] is used to perform inheritance | 10352 * [typeProvider]. The [inheritanceManager] is used to perform inheritance |
| 10292 * lookups. If `null` or unspecified, a new [InheritanceManager] will be | 10353 * lookups. If `null` or unspecified, a new [InheritanceManager] will be |
| 10293 * created based on [definingLibrary]. The [typeAnalyzerFactory] is used to | 10354 * created based on [definingLibrary]. The [typeAnalyzerFactory] is used to |
| 10294 * create the type analyzer. If `null` or unspecified, a type analyzer of | 10355 * create the type analyzer. If `null` or unspecified, a type analyzer of |
| 10295 * type [StaticTypeAnalyzer] will be created. | 10356 * type [StaticTypeAnalyzer] will be created. |
| 10296 */ | 10357 */ |
| 10297 ResolverVisitor(LibraryElement definingLibrary, Source source, | 10358 ResolverVisitor( |
| 10298 TypeProvider typeProvider, AnalysisErrorListener errorListener, | 10359 LibraryElement definingLibrary, |
| 10360 Source source, | |
| 10361 TypeProvider typeProvider, | |
| 10362 TypeSystem typeSystem, | |
| 10363 AnalysisErrorListener errorListener, | |
| 10299 {Scope nameScope, | 10364 {Scope nameScope, |
| 10300 InheritanceManager inheritanceManager, | 10365 InheritanceManager inheritanceManager, |
| 10301 StaticTypeAnalyzerFactory typeAnalyzerFactory}) | 10366 StaticTypeAnalyzerFactory typeAnalyzerFactory}) |
| 10302 : super(definingLibrary, source, typeProvider, errorListener, | 10367 : super(definingLibrary, source, typeProvider, errorListener, |
| 10303 nameScope: nameScope) { | 10368 nameScope: nameScope) { |
| 10304 if (inheritanceManager == null) { | 10369 if (inheritanceManager == null) { |
| 10305 this._inheritanceManager = new InheritanceManager(definingLibrary); | 10370 this._inheritanceManager = new InheritanceManager(definingLibrary); |
| 10306 } else { | 10371 } else { |
| 10307 this._inheritanceManager = inheritanceManager; | 10372 this._inheritanceManager = inheritanceManager; |
| 10308 } | 10373 } |
| 10309 this.elementResolver = new ElementResolver(this); | 10374 this.elementResolver = new ElementResolver(this); |
| 10310 if (typeAnalyzerFactory == null) { | 10375 if (typeAnalyzerFactory == null) { |
| 10311 this.typeAnalyzer = new StaticTypeAnalyzer(this); | 10376 this.typeAnalyzer = new StaticTypeAnalyzer(this, typeSystem); |
| 10312 } else { | 10377 } else { |
| 10313 this.typeAnalyzer = typeAnalyzerFactory(this); | 10378 this.typeAnalyzer = typeAnalyzerFactory(this); |
| 10314 } | 10379 } |
| 10315 } | 10380 } |
| 10316 | 10381 |
| 10317 /** | 10382 /** |
| 10318 * Initialize a newly created visitor to resolve the nodes in a compilation un it. | 10383 * Initialize a newly created visitor to resolve the nodes in a compilation un it. |
| 10319 * | 10384 * |
| 10320 * @param library the library containing the compilation unit being resolved | 10385 * @param library the library containing the compilation unit being resolved |
| 10321 * @param source the source representing the compilation unit being visited | 10386 * @param source the source representing the compilation unit being visited |
| 10322 * @param typeProvider the object used to access the types from the core libra ry | 10387 * @param typeProvider the object used to access the types from the core libra ry |
| 10323 * | 10388 * |
| 10324 * Deprecated. Please use unnamed constructor instead. | 10389 * Deprecated. Please use unnamed constructor instead. |
| 10325 */ | 10390 */ |
| 10326 @deprecated | 10391 @deprecated |
| 10327 ResolverVisitor.con1( | 10392 ResolverVisitor.con1(Library library, Source source, |
| 10328 Library library, Source source, TypeProvider typeProvider, | 10393 TypeProvider typeProvider, TypeSystem typeSystem, |
| 10329 {StaticTypeAnalyzerFactory typeAnalyzerFactory}) | 10394 {StaticTypeAnalyzerFactory typeAnalyzerFactory}) |
| 10330 : this( | 10395 : this(library.libraryElement, source, typeProvider, typeSystem, |
| 10331 library.libraryElement, source, typeProvider, library.errorListener, | 10396 library.errorListener, |
| 10332 nameScope: library.libraryScope, | 10397 nameScope: library.libraryScope, |
| 10333 inheritanceManager: library.inheritanceManager, | 10398 inheritanceManager: library.inheritanceManager, |
| 10334 typeAnalyzerFactory: typeAnalyzerFactory); | 10399 typeAnalyzerFactory: typeAnalyzerFactory); |
| 10335 | 10400 |
| 10336 /** | 10401 /** |
| 10337 * Return the element representing the function containing the current node, o r `null` if | 10402 * Return the element representing the function containing the current node, o r `null` if |
| 10338 * the current node is not contained in a function. | 10403 * the current node is not contained in a function. |
| 10339 * | 10404 * |
| 10340 * @return the element representing the function containing the current node | 10405 * @return the element representing the function containing the current node |
| 10341 */ | 10406 */ |
| (...skipping 4547 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
| 14889 } | 14954 } |
| 14890 | 14955 |
| 14891 /** | 14956 /** |
| 14892 * The interface `TypeSystem` defines the behavior of an object representing | 14957 * The interface `TypeSystem` defines the behavior of an object representing |
| 14893 * the type system. This provides a common location to put methods that act on | 14958 * the type system. This provides a common location to put methods that act on |
| 14894 * types but may need access to more global data structures, and it paves the | 14959 * types but may need access to more global data structures, and it paves the |
| 14895 * way for a possible future where we may wish to make the type system | 14960 * way for a possible future where we may wish to make the type system |
| 14896 * pluggable. | 14961 * pluggable. |
| 14897 */ | 14962 */ |
| 14898 abstract class TypeSystem { | 14963 abstract class TypeSystem { |
| 14899 /** | 14964 /* Create either a strong mode or regular type system based on context. |
|
Brian Wilkerson
2015/09/16 14:00:45
nit: Why is this (and several other places) just a
Leaf
2015/09/16 21:07:55
Because I'm not very used to using doc comment con
| |
| 14900 * Return the [TypeProvider] associated with this [TypeSystem]. | |
| 14901 */ | 14965 */ |
| 14902 TypeProvider get typeProvider; | 14966 static TypeSystem create(AnalysisContext context) { |
| 14967 return (context.analysisOptions.strongMode) | |
| 14968 ? new StrongTypeSystemImpl() | |
| 14969 : new TypeSystemImpl(); | |
| 14970 } | |
| 14903 | 14971 |
| 14904 /** | 14972 /** |
| 14905 * Compute the least upper bound of two types. | 14973 * Compute the least upper bound of two types. |
| 14906 */ | 14974 */ |
| 14907 DartType getLeastUpperBound(DartType type1, DartType type2); | 14975 DartType getLeastUpperBound( |
| 14976 TypeProvider typeProvider, DartType type1, DartType type2); | |
| 14977 | |
| 14978 /** | |
| 14979 * Return `true` if the [leftType] is assignable to the [rightType] (that is, | |
| 14980 * if leftType <==> rightType). | |
| 14981 */ | |
| 14982 bool isAssignableTo(DartType leftType, DartType rightType); | |
| 14908 | 14983 |
| 14909 /** | 14984 /** |
| 14910 * Return `true` if the [leftType] is a subtype of the [rightType] (that is, | 14985 * Return `true` if the [leftType] is a subtype of the [rightType] (that is, |
| 14911 * if leftType <: rightType). | 14986 * if leftType <: rightType). |
| 14912 */ | 14987 */ |
| 14913 bool isSubtypeOf(DartType leftType, DartType rightType); | 14988 bool isSubtypeOf(DartType leftType, DartType rightType); |
| 14914 } | 14989 } |
| 14915 | 14990 |
| 14916 /** | 14991 /** |
| 14917 * Implementation of [TypeSystem] using the rules in the Dart specification. | 14992 * Implementation of [TypeSystem] using the rules in the Dart specification. |
| 14918 */ | 14993 */ |
| 14919 class TypeSystemImpl implements TypeSystem { | 14994 class TypeSystemImpl implements TypeSystem { |
| 14920 @override | 14995 TypeSystemImpl(); |
| 14921 final TypeProvider typeProvider; | |
| 14922 | |
| 14923 TypeSystemImpl(this.typeProvider); | |
| 14924 | 14996 |
| 14925 @override | 14997 @override |
| 14926 DartType getLeastUpperBound(DartType type1, DartType type2) { | 14998 DartType getLeastUpperBound( |
| 14999 TypeProvider typeProvider, DartType type1, DartType type2) { | |
| 14927 // The least upper bound relation is reflexive. | 15000 // The least upper bound relation is reflexive. |
| 14928 if (identical(type1, type2)) { | 15001 if (identical(type1, type2)) { |
| 14929 return type1; | 15002 return type1; |
| 14930 } | 15003 } |
| 14931 // The least upper bound of dynamic and any type T is dynamic. | 15004 // The least upper bound of dynamic and any type T is dynamic. |
| 14932 if (type1.isDynamic) { | 15005 if (type1.isDynamic) { |
| 14933 return type1; | 15006 return type1; |
| 14934 } | 15007 } |
| 14935 if (type2.isDynamic) { | 15008 if (type2.isDynamic) { |
| 14936 return type2; | 15009 return type2; |
| (...skipping 58 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
| 14995 } | 15068 } |
| 14996 return result; | 15069 return result; |
| 14997 } else { | 15070 } else { |
| 14998 // Should never happen. As a defensive measure, return the dynamic type. | 15071 // Should never happen. As a defensive measure, return the dynamic type. |
| 14999 assert(false); | 15072 assert(false); |
| 15000 return typeProvider.dynamicType; | 15073 return typeProvider.dynamicType; |
| 15001 } | 15074 } |
| 15002 } | 15075 } |
| 15003 | 15076 |
| 15004 @override | 15077 @override |
| 15078 bool isAssignableTo(DartType leftType, DartType rightType) { | |
| 15079 return leftType.isAssignableTo(rightType); | |
| 15080 } | |
| 15081 | |
| 15082 @override | |
| 15005 bool isSubtypeOf(DartType leftType, DartType rightType) { | 15083 bool isSubtypeOf(DartType leftType, DartType rightType) { |
| 15006 return leftType.isSubtypeOf(rightType); | 15084 return leftType.isSubtypeOf(rightType); |
| 15007 } | 15085 } |
| 15008 } | 15086 } |
| 15009 | 15087 |
| 15088 typedef bool _GuardedSubtypeChecker<T>(T t1, T t2, Set<Element> visited); | |
| 15089 typedef bool _SubtypeChecker<T>(T t1, T t2); | |
| 15090 | |
| 15091 /** | |
| 15092 * Implementation of [TypeSystem] using the strong mode rules. | |
|
Brian Wilkerson
2015/09/16 14:00:45
We should either document the strong mode semantic
Leaf
2015/09/16 21:07:55
Done.
| |
| 15093 */ | |
| 15094 class StrongTypeSystemImpl implements TypeSystem { | |
| 15095 StrongTypeSystemImpl(); | |
| 15096 | |
| 15097 final _specTypeSystem = new TypeSystemImpl(); | |
| 15098 | |
| 15099 @override | |
| 15100 DartType getLeastUpperBound( | |
| 15101 TypeProvider typeProvider, DartType type1, DartType type2) { | |
| 15102 // TODO(leafp): Implement a strong mode version of this. | |
| 15103 return _specTypeSystem.getLeastUpperBound(typeProvider, type1, type2); | |
| 15104 } | |
| 15105 | |
| 15106 @override | |
| 15107 bool isAssignableTo(DartType toType, DartType fromType) { | |
| 15108 // An actual subtype | |
| 15109 if (isSubtypeOf(fromType, toType)) { | |
| 15110 return true; | |
| 15111 } | |
| 15112 | |
| 15113 // Don't allow implicit downcasts between function types | |
| 15114 // and call method objects, as these will almost always fail. | |
| 15115 if ((fromType is FunctionType && _getCallMethodType(toType) != null) || | |
| 15116 (toType is FunctionType && _getCallMethodType(fromType) != null)) { | |
| 15117 return false; | |
| 15118 } | |
| 15119 | |
| 15120 // If the subtype relation goes the other way, allow the implicit downcast. | |
| 15121 // TODO(leafp): Emit warnings and hints for these in some way. | |
| 15122 // TODO(leafp): Consider adding a flag to disable these? Or just rely on | |
| 15123 // --warnings-as-errors? | |
| 15124 if (isSubtypeOf(toType, fromType) || | |
| 15125 _specTypeSystem.isAssignableTo(toType, fromType)) { | |
| 15126 // TODO(leafp): error if type is known to be exact (literal, | |
| 15127 // instance creation). | |
| 15128 // TODO(leafp): Warn on composite downcast. | |
| 15129 // TODO(leafp): hint on object/dynamic downcast. | |
| 15130 // TODO(leafp): Consider allowing assignment casts. | |
| 15131 return true; | |
| 15132 } | |
| 15133 | |
| 15134 return false; | |
| 15135 } | |
| 15136 | |
| 15137 bool _isBottom(DartType t, {bool dynamicIsBottom: false}) { | |
| 15138 if (t.isDynamic && dynamicIsBottom) return true; | |
| 15139 if (t.isBottom) return true; | |
|
Brian Wilkerson
2015/09/16 14:00:45
nit: Why not just "return t.isBottom;"?
Leaf
2015/09/16 21:07:55
Done.
| |
| 15140 return false; | |
| 15141 } | |
| 15142 | |
| 15143 bool _isTop(DartType t, {bool dynamicIsBottom: false}) { | |
| 15144 if (t.isDynamic && !dynamicIsBottom) return true; | |
| 15145 if (t.isObject) return true; | |
|
Brian Wilkerson
2015/09/16 14:00:45
nit: Similarly, why not just "return t.isObject;"?
Leaf
2015/09/16 21:07:55
Done.
| |
| 15146 return false; | |
| 15147 } | |
| 15148 | |
| 15149 /// Given a type t, if t is an interface type with a call method | |
| 15150 /// defined, return the function type for the call method, otherwise | |
| 15151 /// return null. | |
| 15152 FunctionType _getCallMethodType(DartType t) { | |
| 15153 if (t is InterfaceType) { | |
| 15154 ClassElement element = t.element; | |
| 15155 InheritanceManager manager = new InheritanceManager(element.library); | |
| 15156 FunctionType callType = manager.lookupMemberType(t, "call"); | |
| 15157 return callType; | |
| 15158 } | |
| 15159 return null; | |
| 15160 } | |
| 15161 | |
| 15162 /* Check that f1 is a subtype of f2. | |
|
Brian Wilkerson
2015/09/16 14:00:45
nit: This should be a doc comment and 'f1' and 'f2
Leaf
2015/09/16 21:07:55
Done.
| |
| 15163 * [fuzzyArrows] indicates whether or not the f1 and f2 should be | |
| 15164 * treated as fuzzy arrow types (and hence dynamic parameters to f2 treated as | |
| 15165 * bottom). | |
| 15166 */ | |
| 15167 bool _isFunctionSubtypeOf(FunctionType f1, FunctionType f2, | |
| 15168 {bool fuzzyArrows: true}) { | |
| 15169 final r1s = f1.normalParameterTypes; | |
| 15170 final o1s = f1.optionalParameterTypes; | |
| 15171 final n1s = f1.namedParameterTypes; | |
| 15172 final r2s = f2.normalParameterTypes; | |
| 15173 final o2s = f2.optionalParameterTypes; | |
| 15174 final n2s = f2.namedParameterTypes; | |
| 15175 final ret1 = f1.returnType; | |
| 15176 final ret2 = f2.returnType; | |
| 15177 | |
| 15178 // A -> B <: C -> D if C <: A and | |
| 15179 // either D is void or B <: D | |
| 15180 if (!ret2.isVoid && !isSubtypeOf(ret1, ret2)) { | |
| 15181 return false; | |
| 15182 } | |
| 15183 | |
| 15184 // Reject if one has named and the other has optional | |
| 15185 if (n1s.length > 0 && o2s.length > 0) { | |
| 15186 return false; | |
| 15187 } | |
| 15188 if (n2s.length > 0 && o1s.length > 0) { | |
| 15189 return false; | |
| 15190 } | |
| 15191 | |
| 15192 // Rebind _isSubtypeOf for convenience | |
| 15193 _SubtypeChecker<DartType> parameterSubtype = (DartType t1, DartType t2) => | |
| 15194 _isSubtypeOf(t1, t2, null, dynamicIsBottom: fuzzyArrows); | |
| 15195 | |
| 15196 // f2 has named parameters | |
| 15197 if (n2s.length > 0) { | |
| 15198 // Check that every named parameter in f2 has a match in f1 | |
| 15199 for (String k2 in n2s.keys) { | |
| 15200 if (!n1s.containsKey(k2)) { | |
| 15201 return false; | |
| 15202 } | |
| 15203 if (!parameterSubtype(n2s[k2], n1s[k2])) { | |
| 15204 return false; | |
| 15205 } | |
| 15206 } | |
| 15207 } | |
| 15208 // If we get here, we either have no named parameters, | |
| 15209 // or else the named parameters match and we have no optional | |
| 15210 // parameters | |
| 15211 | |
| 15212 // If f1 has more required parameters, reject | |
| 15213 if (r1s.length > r2s.length) { | |
| 15214 return false; | |
| 15215 } | |
| 15216 | |
| 15217 // If f2 has more required + optional parameters, reject | |
| 15218 if (r2s.length + o2s.length > r1s.length + o1s.length) { | |
| 15219 return false; | |
| 15220 } | |
| 15221 | |
| 15222 // The parameter lists must look like the following at this point | |
| 15223 // where rrr is a region of required, and ooo is a region of optionals. | |
| 15224 // f1: rrr ooo ooo ooo | |
| 15225 // f2: rrr rrr ooo | |
| 15226 int rr = r1s.length; // required in both | |
| 15227 int or = r2s.length - r1s.length; // optional in f1, required in f2 | |
| 15228 int oo = o2s.length; // optional in both | |
| 15229 | |
| 15230 for (int i = 0; i < rr; ++i) { | |
| 15231 if (!parameterSubtype(r2s[i], r1s[i])) { | |
| 15232 return false; | |
| 15233 } | |
| 15234 } | |
| 15235 for (int i = 0, j = rr; i < or; ++i, ++j) { | |
| 15236 if (!parameterSubtype(r2s[j], o1s[i])) { | |
| 15237 return false; | |
| 15238 } | |
| 15239 } | |
| 15240 for (int i = or, j = 0; i < oo; ++i, ++j) { | |
| 15241 if (!parameterSubtype(o2s[j], o1s[i])) { | |
| 15242 return false; | |
| 15243 } | |
| 15244 } | |
| 15245 return true; | |
| 15246 } | |
| 15247 | |
| 15248 // Guard against loops in the class hierarchy | |
| 15249 _GuardedSubtypeChecker<DartType> _guard( | |
| 15250 _GuardedSubtypeChecker<DartType> check) { | |
| 15251 return (DartType t1, DartType t2, Set<Element> visited) { | |
| 15252 Element element = t1.element; | |
| 15253 if (visited == null) { | |
| 15254 visited = new HashSet<Element>(); | |
| 15255 } | |
| 15256 if (element == null || !visited.add(element)) { | |
| 15257 return false; | |
| 15258 } | |
| 15259 try { | |
| 15260 return check(t1, t2, visited); | |
| 15261 } finally { | |
| 15262 visited.remove(element); | |
| 15263 } | |
| 15264 }; | |
| 15265 } | |
| 15266 | |
| 15267 bool _isInterfaceSubtypeOf( | |
|
Brian Wilkerson
2015/09/16 14:00:45
nit: Add doc comment?
Leaf
2015/09/16 21:07:55
Is the recommendation to use doc comments for ever
Brian Wilkerson
2015/09/16 22:54:51
My personal recommendation :-) is to use doc comme
| |
| 15268 InterfaceType i1, InterfaceType i2, Set<Element> visited) { | |
| 15269 // Guard recursive calls | |
| 15270 _GuardedSubtypeChecker<InterfaceType> guardedInterfaceSubtype = | |
| 15271 _guard(_isInterfaceSubtypeOf); | |
| 15272 | |
| 15273 if (i1 == i2) { | |
| 15274 return true; | |
| 15275 } | |
| 15276 | |
| 15277 if (i1.element == i2.element) { | |
| 15278 List<DartType> tArgs1 = i1.typeArguments; | |
| 15279 List<DartType> tArgs2 = i2.typeArguments; | |
| 15280 | |
| 15281 assert(tArgs1.length == tArgs2.length); | |
| 15282 | |
| 15283 for (int i = 0; i < tArgs1.length; i++) { | |
| 15284 DartType t1 = tArgs1[i]; | |
| 15285 DartType t2 = tArgs2[i]; | |
| 15286 if (!isSubtypeOf(t1, t2)) { | |
| 15287 return false; | |
| 15288 } | |
| 15289 } | |
| 15290 return true; | |
| 15291 } | |
| 15292 | |
| 15293 if (i2.isDartCoreFunction && i1.element.getMethod("call") != null) { | |
| 15294 return true; | |
| 15295 } | |
| 15296 | |
| 15297 if (i1.isObject) { | |
| 15298 return false; | |
| 15299 } | |
| 15300 | |
| 15301 if (guardedInterfaceSubtype(i1.superclass, i2, visited)) { | |
| 15302 return true; | |
| 15303 } | |
| 15304 | |
| 15305 for (final parent in i1.interfaces) { | |
| 15306 if (guardedInterfaceSubtype(parent, i2, visited)) { | |
| 15307 return true; | |
| 15308 } | |
| 15309 } | |
| 15310 | |
| 15311 for (final parent in i1.mixins) { | |
| 15312 if (guardedInterfaceSubtype(parent, i2, visited)) { | |
| 15313 return true; | |
| 15314 } | |
| 15315 } | |
| 15316 | |
| 15317 return false; | |
| 15318 } | |
| 15319 | |
| 15320 bool _isSubtypeOf(DartType t1, DartType t2, Set<Element> visited, | |
| 15321 {bool dynamicIsBottom: false}) { | |
| 15322 // Guard recursive calls | |
| 15323 _GuardedSubtypeChecker<DartType> guardedSubtype = _guard(_isSubtypeOf); | |
| 15324 | |
| 15325 if (t1 == t2) { | |
| 15326 return true; | |
| 15327 } | |
| 15328 | |
| 15329 // The types are void, dynamic, bottom, interface types, function types | |
| 15330 // and type parameters. We proceed by eliminating these different classes | |
| 15331 // from consideration. | |
| 15332 | |
| 15333 // Trivially true. | |
| 15334 if (_isTop(t2, dynamicIsBottom: dynamicIsBottom) || | |
| 15335 _isBottom(t1, dynamicIsBottom: dynamicIsBottom)) { | |
| 15336 return true; | |
| 15337 } | |
| 15338 | |
| 15339 // Trivially false. | |
| 15340 if (_isTop(t1, dynamicIsBottom: dynamicIsBottom) || | |
| 15341 _isBottom(t2, dynamicIsBottom: dynamicIsBottom)) { | |
| 15342 return false; | |
| 15343 } | |
| 15344 | |
| 15345 // S <: T where S is a type variable | |
| 15346 // T is not dynamic or object (handled above) | |
| 15347 // S != T (handled above) | |
| 15348 // So only true if bound of S is S' and | |
| 15349 // S' <: T | |
| 15350 if (t1 is TypeParameterType) { | |
| 15351 DartType bound = t1.element.bound; | |
| 15352 if (bound == null) return false; | |
| 15353 return guardedSubtype(bound, t2, visited); | |
| 15354 } | |
| 15355 | |
| 15356 if (t2 is TypeParameterType) { | |
| 15357 return false; | |
| 15358 } | |
| 15359 | |
| 15360 if (t1.isVoid || t2.isVoid) { | |
| 15361 return false; | |
| 15362 } | |
| 15363 | |
| 15364 // We've eliminated void, dynamic, bottom, and type parameters. The only | |
| 15365 // cases are the combinations of interface type and function type. | |
| 15366 | |
| 15367 // A function type can only subtype an interface type if | |
| 15368 // the interface type is Function | |
| 15369 if (t1 is FunctionType && t2 is InterfaceType) { | |
| 15370 return t2.isDartCoreFunction; | |
| 15371 } | |
| 15372 | |
| 15373 // An interface type can only subtype a function type if | |
| 15374 // the interface type declares a call method with a type | |
| 15375 // which is a super type of the function type. | |
| 15376 if (t1 is InterfaceType && t2 is FunctionType) { | |
| 15377 var callType = _getCallMethodType(t1); | |
| 15378 return (callType != null) && _isFunctionSubtypeOf(callType, t2); | |
| 15379 } | |
| 15380 | |
| 15381 // Two interface types | |
| 15382 if (t1 is InterfaceType && t2 is InterfaceType) { | |
| 15383 return _isInterfaceSubtypeOf(t1, t2, visited); | |
| 15384 } | |
| 15385 | |
| 15386 return _isFunctionSubtypeOf(t1 as FunctionType, t2 as FunctionType); | |
| 15387 } | |
| 15388 | |
| 15389 @override | |
| 15390 bool isSubtypeOf(DartType leftType, DartType rightType) { | |
| 15391 return _isSubtypeOf(leftType, rightType, null); | |
| 15392 } | |
| 15393 } | |
| 15394 | |
| 15010 /** | 15395 /** |
| 15011 * Instances of the class [UnusedLocalElementsVerifier] traverse an element | 15396 * Instances of the class [UnusedLocalElementsVerifier] traverse an element |
| 15012 * structure looking for cases of [HintCode.UNUSED_ELEMENT], | 15397 * structure looking for cases of [HintCode.UNUSED_ELEMENT], |
| 15013 * [HintCode.UNUSED_FIELD], [HintCode.UNUSED_LOCAL_VARIABLE], etc. | 15398 * [HintCode.UNUSED_FIELD], [HintCode.UNUSED_LOCAL_VARIABLE], etc. |
| 15014 */ | 15399 */ |
| 15015 class UnusedLocalElementsVerifier extends RecursiveElementVisitor { | 15400 class UnusedLocalElementsVerifier extends RecursiveElementVisitor { |
| 15016 /** | 15401 /** |
| 15017 * The error listener to which errors will be reported. | 15402 * The error listener to which errors will be reported. |
| 15018 */ | 15403 */ |
| 15019 final AnalysisErrorListener _errorListener; | 15404 final AnalysisErrorListener _errorListener; |
| (...skipping 382 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
| 15402 } | 15787 } |
| 15403 return null; | 15788 return null; |
| 15404 } | 15789 } |
| 15405 } | 15790 } |
| 15406 | 15791 |
| 15407 class _ConstantVerifier_validateInitializerExpression extends ConstantVisitor { | 15792 class _ConstantVerifier_validateInitializerExpression extends ConstantVisitor { |
| 15408 final ConstantVerifier verifier; | 15793 final ConstantVerifier verifier; |
| 15409 | 15794 |
| 15410 List<ParameterElement> parameterElements; | 15795 List<ParameterElement> parameterElements; |
| 15411 | 15796 |
| 15797 TypeSystem _typeSystem; | |
| 15798 | |
| 15412 _ConstantVerifier_validateInitializerExpression( | 15799 _ConstantVerifier_validateInitializerExpression( |
| 15413 TypeProvider typeProvider, | 15800 TypeProvider typeProvider, |
| 15801 TypeSystem typeSystem, | |
| 15414 ErrorReporter errorReporter, | 15802 ErrorReporter errorReporter, |
| 15415 this.verifier, | 15803 this.verifier, |
| 15416 this.parameterElements, | 15804 this.parameterElements, |
| 15417 DeclaredVariables declaredVariables) | 15805 DeclaredVariables declaredVariables) |
| 15418 : super(new ConstantEvaluationEngine(typeProvider, declaredVariables), | 15806 : _typeSystem = typeSystem, |
| 15807 super( | |
| 15808 new ConstantEvaluationEngine( | |
| 15809 typeProvider, typeSystem, declaredVariables), | |
| 15419 errorReporter); | 15810 errorReporter); |
| 15420 | 15811 |
| 15421 @override | 15812 @override |
| 15422 DartObjectImpl visitSimpleIdentifier(SimpleIdentifier node) { | 15813 DartObjectImpl visitSimpleIdentifier(SimpleIdentifier node) { |
| 15423 Element element = node.staticElement; | 15814 Element element = node.staticElement; |
| 15424 for (ParameterElement parameterElement in parameterElements) { | 15815 for (ParameterElement parameterElement in parameterElements) { |
| 15425 if (identical(parameterElement, element) && parameterElement != null) { | 15816 if (identical(parameterElement, element) && parameterElement != null) { |
| 15426 DartType type = parameterElement.type; | 15817 DartType type = parameterElement.type; |
| 15427 if (type != null) { | 15818 if (type != null) { |
| 15428 if (type.isDynamic) { | 15819 if (type.isDynamic) { |
| 15429 return new DartObjectImpl( | 15820 return new DartObjectImpl( |
| 15430 verifier._typeProvider.objectType, DynamicState.DYNAMIC_STATE); | 15821 verifier._typeProvider.objectType, DynamicState.DYNAMIC_STATE); |
| 15431 } else if (type.isSubtypeOf(verifier._boolType)) { | 15822 } else if (_typeSystem.isSubtypeOf(type, verifier._boolType)) { |
| 15432 return new DartObjectImpl( | 15823 return new DartObjectImpl( |
| 15433 verifier._typeProvider.boolType, BoolState.UNKNOWN_VALUE); | 15824 verifier._typeProvider.boolType, BoolState.UNKNOWN_VALUE); |
| 15434 } else if (type.isSubtypeOf(verifier._typeProvider.doubleType)) { | 15825 } else if (_typeSystem.isSubtypeOf( |
| 15826 type, verifier._typeProvider.doubleType)) { | |
| 15435 return new DartObjectImpl( | 15827 return new DartObjectImpl( |
| 15436 verifier._typeProvider.doubleType, DoubleState.UNKNOWN_VALUE); | 15828 verifier._typeProvider.doubleType, DoubleState.UNKNOWN_VALUE); |
| 15437 } else if (type.isSubtypeOf(verifier._intType)) { | 15829 } else if (_typeSystem.isSubtypeOf(type, verifier._intType)) { |
| 15438 return new DartObjectImpl( | 15830 return new DartObjectImpl( |
| 15439 verifier._typeProvider.intType, IntState.UNKNOWN_VALUE); | 15831 verifier._typeProvider.intType, IntState.UNKNOWN_VALUE); |
| 15440 } else if (type.isSubtypeOf(verifier._numType)) { | 15832 } else if (_typeSystem.isSubtypeOf(type, verifier._numType)) { |
| 15441 return new DartObjectImpl( | 15833 return new DartObjectImpl( |
| 15442 verifier._typeProvider.numType, NumState.UNKNOWN_VALUE); | 15834 verifier._typeProvider.numType, NumState.UNKNOWN_VALUE); |
| 15443 } else if (type.isSubtypeOf(verifier._stringType)) { | 15835 } else if (_typeSystem.isSubtypeOf(type, verifier._stringType)) { |
| 15444 return new DartObjectImpl( | 15836 return new DartObjectImpl( |
| 15445 verifier._typeProvider.stringType, StringState.UNKNOWN_VALUE); | 15837 verifier._typeProvider.stringType, StringState.UNKNOWN_VALUE); |
| 15446 } | 15838 } |
| 15447 // | 15839 // |
| 15448 // We don't test for other types of objects (such as List, Map, | 15840 // We don't test for other types of objects (such as List, Map, |
| 15449 // Function or Type) because there are no operations allowed on such | 15841 // Function or Type) because there are no operations allowed on such |
| 15450 // types other than '==' and '!=', which means that we don't need to | 15842 // types other than '==' and '!=', which means that we don't need to |
| 15451 // know the type when there is no specific data about the state of | 15843 // know the type when there is no specific data about the state of |
| 15452 // such objects. | 15844 // such objects. |
| 15453 // | 15845 // |
| (...skipping 112 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
| 15566 nonFields.add(node); | 15958 nonFields.add(node); |
| 15567 return null; | 15959 return null; |
| 15568 } | 15960 } |
| 15569 | 15961 |
| 15570 @override | 15962 @override |
| 15571 Object visitNode(AstNode node) => node.accept(TypeResolverVisitor_this); | 15963 Object visitNode(AstNode node) => node.accept(TypeResolverVisitor_this); |
| 15572 | 15964 |
| 15573 @override | 15965 @override |
| 15574 Object visitWithClause(WithClause node) => null; | 15966 Object visitWithClause(WithClause node) => null; |
| 15575 } | 15967 } |
| OLD | NEW |