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 64 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
| 75 /** | 75 /** |
| 76 * The type system primitives | 76 * The type system primitives |
| 77 */ | 77 */ |
| 78 TypeSystem _typeSystem; | 78 TypeSystem _typeSystem; |
| 79 | 79 |
| 80 /** | 80 /** |
| 81 * Create a new instance of the [BestPracticesVerifier]. | 81 * Create a new instance of the [BestPracticesVerifier]. |
| 82 * | 82 * |
| 83 * @param errorReporter the error reporter | 83 * @param errorReporter the error reporter |
| 84 */ | 84 */ |
| 85 BestPracticesVerifier( | 85 BestPracticesVerifier(this._errorReporter, TypeProvider typeProvider, |
| 86 this._errorReporter, TypeProvider typeProvider, this._typeSystem) | 86 {TypeSystem typeSystem}) |
| 87 : _futureNullType = typeProvider.futureNullType; | 87 : _futureNullType = typeProvider.futureNullType, |
| 88 _typeSystem = (typeSystem != null) ? typeSystem : new TypeSystemImpl(); | |
| 88 | 89 |
| 89 @override | 90 @override |
| 90 Object visitArgumentList(ArgumentList node) { | 91 Object visitArgumentList(ArgumentList node) { |
| 91 _checkForArgumentTypesNotAssignableInList(node); | 92 _checkForArgumentTypesNotAssignableInList(node); |
| 92 return super.visitArgumentList(node); | 93 return super.visitArgumentList(node); |
| 93 } | 94 } |
| 94 | 95 |
| 95 @override | 96 @override |
| 96 Object visitAsExpression(AsExpression node) { | 97 Object visitAsExpression(AsExpression node) { |
| 97 _checkForUnnecessaryCast(node); | 98 _checkForUnnecessaryCast(node); |
| (...skipping 743 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
| 841 final ErrorReporter _errorReporter; | 842 final ErrorReporter _errorReporter; |
| 842 | 843 |
| 843 /** | 844 /** |
| 844 * The type provider used to access the known types. | 845 * The type provider used to access the known types. |
| 845 */ | 846 */ |
| 846 final TypeProvider _typeProvider; | 847 final TypeProvider _typeProvider; |
| 847 | 848 |
| 848 /** | 849 /** |
| 849 * The type system in use. | 850 * The type system in use. |
| 850 */ | 851 */ |
| 851 final TypeSystem _typeSystem; | 852 TypeSystem _typeSystem; |
| 852 | 853 |
| 853 /** | 854 /** |
| 854 * The set of variables declared using '-D' on the command line. | 855 * The set of variables declared using '-D' on the command line. |
| 855 */ | 856 */ |
| 856 final DeclaredVariables declaredVariables; | 857 final DeclaredVariables declaredVariables; |
| 857 | 858 |
| 858 /** | 859 /** |
| 859 * The type representing the type 'bool'. | 860 * The type representing the type 'bool'. |
| 860 */ | 861 */ |
| 861 InterfaceType _boolType; | 862 InterfaceType _boolType; |
| (...skipping 17 matching lines...) Expand all Loading... | |
| 879 * The current library that is being analyzed. | 880 * The current library that is being analyzed. |
| 880 */ | 881 */ |
| 881 final LibraryElement _currentLibrary; | 882 final LibraryElement _currentLibrary; |
| 882 | 883 |
| 883 /** | 884 /** |
| 884 * Initialize a newly created constant verifier. | 885 * Initialize a newly created constant verifier. |
| 885 * | 886 * |
| 886 * @param errorReporter the error reporter by which errors will be reported | 887 * @param errorReporter the error reporter by which errors will be reported |
| 887 */ | 888 */ |
| 888 ConstantVerifier(this._errorReporter, this._currentLibrary, | 889 ConstantVerifier(this._errorReporter, this._currentLibrary, |
| 889 this._typeProvider, this._typeSystem, this.declaredVariables) { | 890 this._typeProvider, this.declaredVariables) { |
|
Paul Berry
2015/09/18 05:19:25
Nit: how about this instead:
ConstantVerifier(thi
Leaf
2015/09/18 16:59:04
Done.
| |
| 890 this._boolType = _typeProvider.boolType; | 891 this._boolType = _typeProvider.boolType; |
| 891 this._intType = _typeProvider.intType; | 892 this._intType = _typeProvider.intType; |
| 892 this._numType = _typeProvider.numType; | 893 this._numType = _typeProvider.numType; |
| 893 this._stringType = _typeProvider.stringType; | 894 this._stringType = _typeProvider.stringType; |
| 895 this._typeSystem = _currentLibrary.context.typeSystem; | |
| 894 } | 896 } |
| 895 | 897 |
| 896 @override | 898 @override |
| 897 Object visitAnnotation(Annotation node) { | 899 Object visitAnnotation(Annotation node) { |
| 898 super.visitAnnotation(node); | 900 super.visitAnnotation(node); |
| 899 // check annotation creation | 901 // check annotation creation |
| 900 Element element = node.element; | 902 Element element = node.element; |
| 901 if (element is ConstructorElement) { | 903 if (element is ConstructorElement) { |
| 902 ConstructorElement constructorElement = element; | 904 ConstructorElement constructorElement = element; |
| 903 // should 'const' constructor | 905 // should 'const' constructor |
| (...skipping 33 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
| 937 } | 939 } |
| 938 | 940 |
| 939 @override | 941 @override |
| 940 Object visitInstanceCreationExpression(InstanceCreationExpression node) { | 942 Object visitInstanceCreationExpression(InstanceCreationExpression node) { |
| 941 if (node.isConst) { | 943 if (node.isConst) { |
| 942 // We need to evaluate the constant to see if any errors occur during its | 944 // We need to evaluate the constant to see if any errors occur during its |
| 943 // evaluation. | 945 // evaluation. |
| 944 ConstructorElement constructor = node.staticElement; | 946 ConstructorElement constructor = node.staticElement; |
| 945 if (constructor != null) { | 947 if (constructor != null) { |
| 946 ConstantEvaluationEngine evaluationEngine = | 948 ConstantEvaluationEngine evaluationEngine = |
| 947 new ConstantEvaluationEngine( | 949 new ConstantEvaluationEngine(_typeProvider, declaredVariables, |
| 948 _typeProvider, _typeSystem, declaredVariables); | 950 typeSystem: _typeSystem); |
| 949 ConstantVisitor constantVisitor = | 951 ConstantVisitor constantVisitor = |
| 950 new ConstantVisitor(evaluationEngine, _errorReporter); | 952 new ConstantVisitor(evaluationEngine, _errorReporter); |
| 951 evaluationEngine.evaluateConstructorCall( | 953 evaluationEngine.evaluateConstructorCall( |
| 952 node, | 954 node, |
| 953 node.argumentList.arguments, | 955 node.argumentList.arguments, |
| 954 constructor, | 956 constructor, |
| 955 constantVisitor, | 957 constantVisitor, |
| 956 _errorReporter); | 958 _errorReporter); |
| 957 } | 959 } |
| 958 } | 960 } |
| (...skipping 53 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
| 1012 [type.displayName]); | 1014 [type.displayName]); |
| 1013 } | 1015 } |
| 1014 } | 1016 } |
| 1015 } else { | 1017 } else { |
| 1016 // Note: we throw the errors away because this isn't actually a const. | 1018 // Note: we throw the errors away because this isn't actually a const. |
| 1017 AnalysisErrorListener errorListener = | 1019 AnalysisErrorListener errorListener = |
| 1018 AnalysisErrorListener.NULL_LISTENER; | 1020 AnalysisErrorListener.NULL_LISTENER; |
| 1019 ErrorReporter subErrorReporter = | 1021 ErrorReporter subErrorReporter = |
| 1020 new ErrorReporter(errorListener, _errorReporter.source); | 1022 new ErrorReporter(errorListener, _errorReporter.source); |
| 1021 DartObjectImpl result = key.accept(new ConstantVisitor( | 1023 DartObjectImpl result = key.accept(new ConstantVisitor( |
| 1022 new ConstantEvaluationEngine( | 1024 new ConstantEvaluationEngine(_typeProvider, declaredVariables, |
| 1023 _typeProvider, _typeSystem, declaredVariables), | 1025 typeSystem: _typeSystem), |
| 1024 subErrorReporter)); | 1026 subErrorReporter)); |
| 1025 if (result != null) { | 1027 if (result != null) { |
| 1026 if (keys.contains(result)) { | 1028 if (keys.contains(result)) { |
| 1027 invalidKeys.add(key); | 1029 invalidKeys.add(key); |
| 1028 } else { | 1030 } else { |
| 1029 keys.add(result); | 1031 keys.add(result); |
| 1030 } | 1032 } |
| 1031 } else { | 1033 } else { |
| 1032 reportEqualKeys = false; | 1034 reportEqualKeys = false; |
| 1033 } | 1035 } |
| (...skipping 185 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
| 1219 * | 1221 * |
| 1220 * @param expression the expression to be validated | 1222 * @param expression the expression to be validated |
| 1221 * @param errorCode the error code to be used if the expression is not a compi le time constant | 1223 * @param errorCode the error code to be used if the expression is not a compi le time constant |
| 1222 * @return the value of the compile time constant | 1224 * @return the value of the compile time constant |
| 1223 */ | 1225 */ |
| 1224 DartObjectImpl _validate(Expression expression, ErrorCode errorCode) { | 1226 DartObjectImpl _validate(Expression expression, ErrorCode errorCode) { |
| 1225 RecordingErrorListener errorListener = new RecordingErrorListener(); | 1227 RecordingErrorListener errorListener = new RecordingErrorListener(); |
| 1226 ErrorReporter subErrorReporter = | 1228 ErrorReporter subErrorReporter = |
| 1227 new ErrorReporter(errorListener, _errorReporter.source); | 1229 new ErrorReporter(errorListener, _errorReporter.source); |
| 1228 DartObjectImpl result = expression.accept(new ConstantVisitor( | 1230 DartObjectImpl result = expression.accept(new ConstantVisitor( |
| 1229 new ConstantEvaluationEngine( | 1231 new ConstantEvaluationEngine(_typeProvider, declaredVariables, |
| 1230 _typeProvider, _typeSystem, declaredVariables), | 1232 typeSystem: _typeSystem), |
| 1231 subErrorReporter)); | 1233 subErrorReporter)); |
| 1232 _reportErrors(errorListener.errors, errorCode); | 1234 _reportErrors(errorListener.errors, errorCode); |
| 1233 return result; | 1235 return result; |
| 1234 } | 1236 } |
| 1235 | 1237 |
| 1236 /** | 1238 /** |
| 1237 * Validate that if the passed arguments are constant expressions. | 1239 * Validate that if the passed arguments are constant expressions. |
| 1238 * | 1240 * |
| 1239 * @param argumentList the argument list to evaluate | 1241 * @param argumentList the argument list to evaluate |
| 1240 */ | 1242 */ |
| (...skipping 87 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
| 1328 in fieldDeclaration.fields.variables) { | 1330 in fieldDeclaration.fields.variables) { |
| 1329 Expression initializer = variableDeclaration.initializer; | 1331 Expression initializer = variableDeclaration.initializer; |
| 1330 if (initializer != null) { | 1332 if (initializer != null) { |
| 1331 // Ignore any errors produced during validation--if the constant | 1333 // Ignore any errors produced during validation--if the constant |
| 1332 // can't be eavluated we'll just report a single error. | 1334 // can't be eavluated we'll just report a single error. |
| 1333 AnalysisErrorListener errorListener = | 1335 AnalysisErrorListener errorListener = |
| 1334 AnalysisErrorListener.NULL_LISTENER; | 1336 AnalysisErrorListener.NULL_LISTENER; |
| 1335 ErrorReporter subErrorReporter = | 1337 ErrorReporter subErrorReporter = |
| 1336 new ErrorReporter(errorListener, _errorReporter.source); | 1338 new ErrorReporter(errorListener, _errorReporter.source); |
| 1337 DartObjectImpl result = initializer.accept(new ConstantVisitor( | 1339 DartObjectImpl result = initializer.accept(new ConstantVisitor( |
| 1338 new ConstantEvaluationEngine( | 1340 new ConstantEvaluationEngine(_typeProvider, declaredVariables, |
| 1339 _typeProvider, _typeSystem, declaredVariables), | 1341 typeSystem: _typeSystem), |
| 1340 subErrorReporter)); | 1342 subErrorReporter)); |
| 1341 if (result == null) { | 1343 if (result == null) { |
| 1342 _errorReporter.reportErrorForNode( | 1344 _errorReporter.reportErrorForNode( |
| 1343 CompileTimeErrorCode.CONST_CONSTRUCTOR_WITH_FIELD_INITIALIZE D_BY_NON_CONST, | 1345 CompileTimeErrorCode.CONST_CONSTRUCTOR_WITH_FIELD_INITIALIZE D_BY_NON_CONST, |
| 1344 errorSite, | 1346 errorSite, |
| 1345 [variableDeclaration.name.name]); | 1347 [variableDeclaration.name.name]); |
| 1346 } | 1348 } |
| 1347 } | 1349 } |
| 1348 } | 1350 } |
| 1349 } | 1351 } |
| 1350 } | 1352 } |
| 1351 } | 1353 } |
| 1352 } | 1354 } |
| 1353 | 1355 |
| 1354 /** | 1356 /** |
| 1355 * Validates that the given expression is a compile time constant. | 1357 * Validates that the given expression is a compile time constant. |
| 1356 * | 1358 * |
| 1357 * @param parameterElements the elements of parameters of constant constructor , they are | 1359 * @param parameterElements the elements of parameters of constant constructor , they are |
| 1358 * considered as a valid potentially constant expressions | 1360 * considered as a valid potentially constant expressions |
| 1359 * @param expression the expression to validate | 1361 * @param expression the expression to validate |
| 1360 */ | 1362 */ |
| 1361 void _validateInitializerExpression( | 1363 void _validateInitializerExpression( |
| 1362 List<ParameterElement> parameterElements, Expression expression) { | 1364 List<ParameterElement> parameterElements, Expression expression) { |
| 1363 RecordingErrorListener errorListener = new RecordingErrorListener(); | 1365 RecordingErrorListener errorListener = new RecordingErrorListener(); |
| 1364 ErrorReporter subErrorReporter = | 1366 ErrorReporter subErrorReporter = |
| 1365 new ErrorReporter(errorListener, _errorReporter.source); | 1367 new ErrorReporter(errorListener, _errorReporter.source); |
| 1366 DartObjectImpl result = expression.accept( | 1368 DartObjectImpl result = expression.accept( |
| 1367 new _ConstantVerifier_validateInitializerExpression( | 1369 new _ConstantVerifier_validateInitializerExpression(_typeProvider, |
| 1368 _typeProvider, | 1370 subErrorReporter, this, parameterElements, declaredVariables, |
| 1369 _typeSystem, | 1371 typeSystem: _typeSystem)); |
| 1370 subErrorReporter, | |
| 1371 this, | |
| 1372 parameterElements, | |
| 1373 declaredVariables)); | |
| 1374 _reportErrors(errorListener.errors, | 1372 _reportErrors(errorListener.errors, |
| 1375 CompileTimeErrorCode.NON_CONSTANT_VALUE_IN_INITIALIZER); | 1373 CompileTimeErrorCode.NON_CONSTANT_VALUE_IN_INITIALIZER); |
| 1376 if (result != null) { | 1374 if (result != null) { |
| 1377 _reportErrorIfFromDeferredLibrary(expression, | 1375 _reportErrorIfFromDeferredLibrary(expression, |
| 1378 CompileTimeErrorCode.NON_CONSTANT_VALUE_IN_INITIALIZER_FROM_DEFERRED_L IBRARY); | 1376 CompileTimeErrorCode.NON_CONSTANT_VALUE_IN_INITIALIZER_FROM_DEFERRED_L IBRARY); |
| 1379 } | 1377 } |
| 1380 } | 1378 } |
| 1381 | 1379 |
| 1382 /** | 1380 /** |
| 1383 * Validates that all of the arguments of a constructor initializer are compil e time constants. | 1381 * Validates that all of the arguments of a constructor initializer are compil e time constants. |
| (...skipping 113 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
| 1497 /** | 1495 /** |
| 1498 * The type system for this visitor | 1496 * The type system for this visitor |
| 1499 */ | 1497 */ |
| 1500 final TypeSystem _typeSystem; | 1498 final TypeSystem _typeSystem; |
| 1501 | 1499 |
| 1502 /** | 1500 /** |
| 1503 * Create a new instance of the [DeadCodeVerifier]. | 1501 * Create a new instance of the [DeadCodeVerifier]. |
| 1504 * | 1502 * |
| 1505 * @param errorReporter the error reporter | 1503 * @param errorReporter the error reporter |
| 1506 */ | 1504 */ |
| 1507 DeadCodeVerifier(this._errorReporter, this._typeSystem); | 1505 DeadCodeVerifier(this._errorReporter, {TypeSystem typeSystem}) |
| 1506 : this._typeSystem = | |
| 1507 (typeSystem != null) ? typeSystem : new TypeSystemImpl(); | |
| 1508 | 1508 |
| 1509 @override | 1509 @override |
| 1510 Object visitBinaryExpression(BinaryExpression node) { | 1510 Object visitBinaryExpression(BinaryExpression node) { |
| 1511 sc.Token operator = node.operator; | 1511 sc.Token operator = node.operator; |
| 1512 bool isAmpAmp = operator.type == sc.TokenType.AMPERSAND_AMPERSAND; | 1512 bool isAmpAmp = operator.type == sc.TokenType.AMPERSAND_AMPERSAND; |
| 1513 bool isBarBar = operator.type == sc.TokenType.BAR_BAR; | 1513 bool isBarBar = operator.type == sc.TokenType.BAR_BAR; |
| 1514 if (isAmpAmp || isBarBar) { | 1514 if (isAmpAmp || isBarBar) { |
| 1515 Expression lhsCondition = node.leftOperand; | 1515 Expression lhsCondition = node.leftOperand; |
| 1516 if (!_isDebugConstant(lhsCondition)) { | 1516 if (!_isDebugConstant(lhsCondition)) { |
| 1517 EvaluationResultImpl lhsResult = _getConstantBooleanValue(lhsCondition); | 1517 EvaluationResultImpl lhsResult = _getConstantBooleanValue(lhsCondition); |
| (...skipping 3299 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
| 4817 } | 4817 } |
| 4818 _library.accept(new UnusedLocalElementsVerifier( | 4818 _library.accept(new UnusedLocalElementsVerifier( |
| 4819 _errorListener, _usedLocalElementsVisitor.usedElements)); | 4819 _errorListener, _usedLocalElementsVisitor.usedElements)); |
| 4820 }); | 4820 }); |
| 4821 } | 4821 } |
| 4822 | 4822 |
| 4823 void _generateForCompilationUnit(CompilationUnit unit, Source source) { | 4823 void _generateForCompilationUnit(CompilationUnit unit, Source source) { |
| 4824 ErrorReporter errorReporter = new ErrorReporter(_errorListener, source); | 4824 ErrorReporter errorReporter = new ErrorReporter(_errorListener, source); |
| 4825 unit.accept(_usedImportedElementsVisitor); | 4825 unit.accept(_usedImportedElementsVisitor); |
| 4826 // dead code analysis | 4826 // dead code analysis |
| 4827 unit.accept(new DeadCodeVerifier(errorReporter, _context.typeSystem)); | 4827 unit.accept( |
| 4828 new DeadCodeVerifier(errorReporter, typeSystem: _context.typeSystem)); | |
| 4828 unit.accept(_usedLocalElementsVisitor); | 4829 unit.accept(_usedLocalElementsVisitor); |
| 4829 // dart2js analysis | 4830 // dart2js analysis |
| 4830 if (_enableDart2JSHints) { | 4831 if (_enableDart2JSHints) { |
| 4831 unit.accept(new Dart2JSVerifier(errorReporter)); | 4832 unit.accept(new Dart2JSVerifier(errorReporter)); |
| 4832 } | 4833 } |
| 4833 // Dart best practices | 4834 // Dart best practices |
| 4834 unit.accept(new BestPracticesVerifier( | 4835 unit.accept(new BestPracticesVerifier(errorReporter, _context.typeProvider, |
| 4835 errorReporter, _context.typeProvider, _context.typeSystem)); | 4836 typeSystem: _context.typeSystem)); |
| 4836 unit.accept(new OverrideVerifier(errorReporter, _manager)); | 4837 unit.accept(new OverrideVerifier(errorReporter, _manager)); |
| 4837 // Find to-do comments | 4838 // Find to-do comments |
| 4838 new ToDoFinder(errorReporter).findIn(unit); | 4839 new ToDoFinder(errorReporter).findIn(unit); |
| 4839 // pub analysis | 4840 // pub analysis |
| 4840 // TODO(danrubel/jwren) Commented out until bugs in the pub verifier are | 4841 // TODO(danrubel/jwren) Commented out until bugs in the pub verifier are |
| 4841 // fixed | 4842 // fixed |
| 4842 // unit.accept(new PubVerifier(context, errorReporter)); | 4843 // unit.accept(new PubVerifier(context, errorReporter)); |
| 4843 } | 4844 } |
| 4844 } | 4845 } |
| 4845 | 4846 |
| (...skipping 3474 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
| 8320 } | 8321 } |
| 8321 | 8322 |
| 8322 /** | 8323 /** |
| 8323 * Compute a value for all of the constants in the libraries being analyzed. | 8324 * Compute a value for all of the constants in the libraries being analyzed. |
| 8324 */ | 8325 */ |
| 8325 void _performConstantEvaluation() { | 8326 void _performConstantEvaluation() { |
| 8326 PerformanceStatistics.resolve.makeCurrentWhile(() { | 8327 PerformanceStatistics.resolve.makeCurrentWhile(() { |
| 8327 ConstantValueComputer computer = new ConstantValueComputer( | 8328 ConstantValueComputer computer = new ConstantValueComputer( |
| 8328 analysisContext, | 8329 analysisContext, |
| 8329 _typeProvider, | 8330 _typeProvider, |
| 8330 _typeSystem, | 8331 analysisContext.declaredVariables, |
| 8331 analysisContext.declaredVariables); | 8332 null, |
| 8333 _typeSystem); | |
| 8332 for (Library library in _librariesInCycles) { | 8334 for (Library library in _librariesInCycles) { |
| 8333 for (Source source in library.compilationUnitSources) { | 8335 for (Source source in library.compilationUnitSources) { |
| 8334 try { | 8336 try { |
| 8335 CompilationUnit unit = library.getAST(source); | 8337 CompilationUnit unit = library.getAST(source); |
| 8336 if (unit != null) { | 8338 if (unit != null) { |
| 8337 computer.add(unit, source, library.librarySource); | 8339 computer.add(unit, source, library.librarySource); |
| 8338 } | 8340 } |
| 8339 } on AnalysisException catch (exception, stackTrace) { | 8341 } on AnalysisException catch (exception, stackTrace) { |
| 8340 AnalysisEngine.instance.logger.logError( | 8342 AnalysisEngine.instance.logger.logError( |
| 8341 "Internal Error: Could not access AST for ${source.fullName} dur ing constant evaluation", | 8343 "Internal Error: Could not access AST for ${source.fullName} dur ing constant evaluation", |
| 8342 new CaughtException(exception, stackTrace)); | 8344 new CaughtException(exception, stackTrace)); |
| 8343 } | 8345 } |
| 8344 } | 8346 } |
| 8345 } | 8347 } |
| 8346 computer.computeValues(); | 8348 computer.computeValues(); |
| 8347 // As a temporary workaround for issue 21572, run ConstantVerifier now. | 8349 // As a temporary workaround for issue 21572, run ConstantVerifier now. |
| 8348 // TODO(paulberry): remove this workaround once issue 21572 is fixed. | 8350 // TODO(paulberry): remove this workaround once issue 21572 is fixed. |
| 8349 for (Library library in _librariesInCycles) { | 8351 for (Library library in _librariesInCycles) { |
| 8350 for (Source source in library.compilationUnitSources) { | 8352 for (Source source in library.compilationUnitSources) { |
| 8351 try { | 8353 try { |
| 8352 CompilationUnit unit = library.getAST(source); | 8354 CompilationUnit unit = library.getAST(source); |
| 8353 ErrorReporter errorReporter = | 8355 ErrorReporter errorReporter = |
| 8354 new ErrorReporter(_errorListener, source); | 8356 new ErrorReporter(_errorListener, source); |
| 8355 ConstantVerifier constantVerifier = new ConstantVerifier( | 8357 ConstantVerifier constantVerifier = new ConstantVerifier( |
| 8356 errorReporter, | 8358 errorReporter, |
| 8357 library.libraryElement, | 8359 library.libraryElement, |
| 8358 _typeProvider, | 8360 _typeProvider, |
| 8359 _typeSystem, | |
| 8360 analysisContext.declaredVariables); | 8361 analysisContext.declaredVariables); |
| 8361 unit.accept(constantVerifier); | 8362 unit.accept(constantVerifier); |
| 8362 } on AnalysisException catch (exception, stackTrace) { | 8363 } on AnalysisException catch (exception, stackTrace) { |
| 8363 AnalysisEngine.instance.logger.logError( | 8364 AnalysisEngine.instance.logger.logError( |
| 8364 "Internal Error: Could not access AST for ${source.fullName} " | 8365 "Internal Error: Could not access AST for ${source.fullName} " |
| 8365 "during constant verification", | 8366 "during constant verification", |
| 8366 new CaughtException(exception, stackTrace)); | 8367 new CaughtException(exception, stackTrace)); |
| 8367 } | 8368 } |
| 8368 } | 8369 } |
| 8369 } | 8370 } |
| (...skipping 12 matching lines...) Expand all Loading... | |
| 8382 for (Source source in library.compilationUnitSources) { | 8383 for (Source source in library.compilationUnitSources) { |
| 8383 CompilationUnit ast = library.getAST(source); | 8384 CompilationUnit ast = library.getAST(source); |
| 8384 ast.accept(new VariableResolverVisitor(library.libraryElement, source, | 8385 ast.accept(new VariableResolverVisitor(library.libraryElement, source, |
| 8385 _typeProvider, library.errorListener, | 8386 _typeProvider, library.errorListener, |
| 8386 nameScope: library.libraryScope)); | 8387 nameScope: library.libraryScope)); |
| 8387 ResolverVisitorFactory visitorFactory = | 8388 ResolverVisitorFactory visitorFactory = |
| 8388 analysisContext.resolverVisitorFactory; | 8389 analysisContext.resolverVisitorFactory; |
| 8389 ResolverVisitor visitor = visitorFactory != null | 8390 ResolverVisitor visitor = visitorFactory != null |
| 8390 ? visitorFactory(library, source, _typeProvider) | 8391 ? visitorFactory(library, source, _typeProvider) |
| 8391 : new ResolverVisitor(library.libraryElement, source, _typeProvider, | 8392 : new ResolverVisitor(library.libraryElement, source, _typeProvider, |
| 8392 _typeSystem, library.errorListener, | 8393 library.errorListener, |
| 8393 nameScope: library.libraryScope, | 8394 nameScope: library.libraryScope, |
| 8394 inheritanceManager: library.inheritanceManager); | 8395 inheritanceManager: library.inheritanceManager); |
| 8395 ast.accept(visitor); | 8396 ast.accept(visitor); |
| 8396 } | 8397 } |
| 8397 }); | 8398 }); |
| 8398 } | 8399 } |
| 8399 | 8400 |
| 8400 /** | 8401 /** |
| 8401 * Return the result of resolving the URI of the given URI-based directive aga inst the URI of the | 8402 * Return the result of resolving the URI of the given URI-based directive aga inst the URI of the |
| 8402 * given library, or `null` if the URI is not valid. | 8403 * given library, or `null` if the URI is not valid. |
| (...skipping 422 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
| 8825 } | 8826 } |
| 8826 | 8827 |
| 8827 /** | 8828 /** |
| 8828 * Compute a value for all of the constants in the libraries being analyzed. | 8829 * Compute a value for all of the constants in the libraries being analyzed. |
| 8829 */ | 8830 */ |
| 8830 void _performConstantEvaluation() { | 8831 void _performConstantEvaluation() { |
| 8831 PerformanceStatistics.resolve.makeCurrentWhile(() { | 8832 PerformanceStatistics.resolve.makeCurrentWhile(() { |
| 8832 ConstantValueComputer computer = new ConstantValueComputer( | 8833 ConstantValueComputer computer = new ConstantValueComputer( |
| 8833 analysisContext, | 8834 analysisContext, |
| 8834 _typeProvider, | 8835 _typeProvider, |
| 8835 _typeSystem, | 8836 analysisContext.declaredVariables, |
| 8836 analysisContext.declaredVariables); | 8837 null, |
| 8838 _typeSystem); | |
| 8837 for (ResolvableLibrary library in _librariesInCycle) { | 8839 for (ResolvableLibrary library in _librariesInCycle) { |
| 8838 for (ResolvableCompilationUnit unit | 8840 for (ResolvableCompilationUnit unit |
| 8839 in library.resolvableCompilationUnits) { | 8841 in library.resolvableCompilationUnits) { |
| 8840 CompilationUnit ast = unit.compilationUnit; | 8842 CompilationUnit ast = unit.compilationUnit; |
| 8841 if (ast != null) { | 8843 if (ast != null) { |
| 8842 computer.add(ast, unit.source, library.librarySource); | 8844 computer.add(ast, unit.source, library.librarySource); |
| 8843 } | 8845 } |
| 8844 } | 8846 } |
| 8845 } | 8847 } |
| 8846 computer.computeValues(); | 8848 computer.computeValues(); |
| 8847 // As a temporary workaround for issue 21572, run ConstantVerifier now. | 8849 // As a temporary workaround for issue 21572, run ConstantVerifier now. |
| 8848 // TODO(paulberry): remove this workaround once issue 21572 is fixed. | 8850 // TODO(paulberry): remove this workaround once issue 21572 is fixed. |
| 8849 for (ResolvableLibrary library in _librariesInCycle) { | 8851 for (ResolvableLibrary library in _librariesInCycle) { |
| 8850 for (ResolvableCompilationUnit unit | 8852 for (ResolvableCompilationUnit unit |
| 8851 in library.resolvableCompilationUnits) { | 8853 in library.resolvableCompilationUnits) { |
| 8852 CompilationUnit ast = unit.compilationUnit; | 8854 CompilationUnit ast = unit.compilationUnit; |
| 8853 ErrorReporter errorReporter = | 8855 ErrorReporter errorReporter = |
| 8854 new ErrorReporter(_errorListener, unit.source); | 8856 new ErrorReporter(_errorListener, unit.source); |
| 8855 ConstantVerifier constantVerifier = new ConstantVerifier( | 8857 ConstantVerifier constantVerifier = new ConstantVerifier( |
| 8856 errorReporter, | 8858 errorReporter, |
| 8857 library.libraryElement, | 8859 library.libraryElement, |
| 8858 _typeProvider, | 8860 _typeProvider, |
| 8859 _typeSystem, | |
| 8860 analysisContext.declaredVariables); | 8861 analysisContext.declaredVariables); |
| 8861 ast.accept(constantVerifier); | 8862 ast.accept(constantVerifier); |
| 8862 } | 8863 } |
| 8863 } | 8864 } |
| 8864 }); | 8865 }); |
| 8865 } | 8866 } |
| 8866 | 8867 |
| 8867 /** | 8868 /** |
| 8868 * Resolve the identifiers and perform type analysis in the libraries in the c urrent cycle. | 8869 * Resolve the identifiers and perform type analysis in the libraries in the c urrent cycle. |
| 8869 * | 8870 * |
| (...skipping 15 matching lines...) Expand all Loading... | |
| 8885 */ | 8886 */ |
| 8886 void _resolveReferencesAndTypesInLibrary(ResolvableLibrary library) { | 8887 void _resolveReferencesAndTypesInLibrary(ResolvableLibrary library) { |
| 8887 PerformanceStatistics.resolve.makeCurrentWhile(() { | 8888 PerformanceStatistics.resolve.makeCurrentWhile(() { |
| 8888 for (ResolvableCompilationUnit unit | 8889 for (ResolvableCompilationUnit unit |
| 8889 in library.resolvableCompilationUnits) { | 8890 in library.resolvableCompilationUnits) { |
| 8890 Source source = unit.source; | 8891 Source source = unit.source; |
| 8891 CompilationUnit ast = unit.compilationUnit; | 8892 CompilationUnit ast = unit.compilationUnit; |
| 8892 ast.accept(new VariableResolverVisitor(library.libraryElement, source, | 8893 ast.accept(new VariableResolverVisitor(library.libraryElement, source, |
| 8893 _typeProvider, library.libraryScope.errorListener, | 8894 _typeProvider, library.libraryScope.errorListener, |
| 8894 nameScope: library.libraryScope)); | 8895 nameScope: library.libraryScope)); |
| 8895 ResolverVisitor visitor = new ResolverVisitor( | 8896 ResolverVisitor visitor = new ResolverVisitor(library.libraryElement, |
| 8896 library.libraryElement, | 8897 source, _typeProvider, library._libraryScope.errorListener, |
| 8897 source, | |
| 8898 _typeProvider, | |
| 8899 _typeSystem, | |
| 8900 library._libraryScope.errorListener, | |
| 8901 nameScope: library._libraryScope, | 8898 nameScope: library._libraryScope, |
| 8902 inheritanceManager: library.inheritanceManager); | 8899 inheritanceManager: library.inheritanceManager); |
| 8903 ast.accept(visitor); | 8900 ast.accept(visitor); |
| 8904 } | 8901 } |
| 8905 }); | 8902 }); |
| 8906 } | 8903 } |
| 8907 | 8904 |
| 8908 /** | 8905 /** |
| 8909 * Report that the async library could not be resolved in the given | 8906 * Report that the async library could not be resolved in the given |
| 8910 * [analysisContext] and throw an exception. [asyncLibrarySource] is the sour ce | 8907 * [analysisContext] and throw an exception. [asyncLibrarySource] is the sour ce |
| (...skipping 728 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
| 9639 * listener that will be informed of any errors that are found during | 9636 * listener that will be informed of any errors that are found during |
| 9640 * resolution. The [nameScope] is the scope used to resolve identifiers in the | 9637 * resolution. The [nameScope] is the scope used to resolve identifiers in the |
| 9641 * node that will first be visited. If `null` or unspecified, a new | 9638 * node that will first be visited. If `null` or unspecified, a new |
| 9642 * [LibraryScope] will be created based on [definingLibrary] and | 9639 * [LibraryScope] will be created based on [definingLibrary] and |
| 9643 * [typeProvider]. The [inheritanceManager] is used to perform inheritance | 9640 * [typeProvider]. The [inheritanceManager] is used to perform inheritance |
| 9644 * lookups. If `null` or unspecified, a new [InheritanceManager] will be | 9641 * lookups. If `null` or unspecified, a new [InheritanceManager] will be |
| 9645 * created based on [definingLibrary]. The [typeAnalyzerFactory] is used to | 9642 * created based on [definingLibrary]. The [typeAnalyzerFactory] is used to |
| 9646 * create the type analyzer. If `null` or unspecified, a type analyzer of | 9643 * create the type analyzer. If `null` or unspecified, a type analyzer of |
| 9647 * type [StaticTypeAnalyzer] will be created. | 9644 * type [StaticTypeAnalyzer] will be created. |
| 9648 */ | 9645 */ |
| 9649 PartialResolverVisitor( | 9646 PartialResolverVisitor(LibraryElement definingLibrary, Source source, |
| 9650 LibraryElement definingLibrary, | 9647 TypeProvider typeProvider, AnalysisErrorListener errorListener, |
| 9651 Source source, | |
| 9652 TypeProvider typeProvider, | |
| 9653 TypeSystem typeSystem, | |
| 9654 AnalysisErrorListener errorListener, | |
| 9655 {Scope nameScope, | 9648 {Scope nameScope, |
| 9656 InheritanceManager inheritanceManager, | 9649 InheritanceManager inheritanceManager, |
| 9657 StaticTypeAnalyzerFactory typeAnalyzerFactory}) | 9650 StaticTypeAnalyzerFactory typeAnalyzerFactory}) |
| 9658 : strongMode = definingLibrary.context.analysisOptions.strongMode, | 9651 : strongMode = definingLibrary.context.analysisOptions.strongMode, |
| 9659 super(definingLibrary, source, typeProvider, typeSystem, | 9652 super(definingLibrary, source, typeProvider, |
| 9660 new DisablableErrorListener(errorListener)); | 9653 new DisablableErrorListener(errorListener)); |
| 9661 | 9654 |
| 9662 @override | 9655 @override |
| 9663 Object visitBlockFunctionBody(BlockFunctionBody node) { | 9656 Object visitBlockFunctionBody(BlockFunctionBody node) { |
| 9664 if (_shouldBeSkipped(node)) { | 9657 if (_shouldBeSkipped(node)) { |
| 9665 return null; | 9658 return null; |
| 9666 } | 9659 } |
| 9667 return super.visitBlockFunctionBody(node); | 9660 return super.visitBlockFunctionBody(node); |
| 9668 } | 9661 } |
| 9669 | 9662 |
| (...skipping 611 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
| 10281 /** | 10274 /** |
| 10282 * The object used to resolve the element associated with the current node. | 10275 * The object used to resolve the element associated with the current node. |
| 10283 */ | 10276 */ |
| 10284 ElementResolver elementResolver; | 10277 ElementResolver elementResolver; |
| 10285 | 10278 |
| 10286 /** | 10279 /** |
| 10287 * The object used to compute the type associated with the current node. | 10280 * The object used to compute the type associated with the current node. |
| 10288 */ | 10281 */ |
| 10289 StaticTypeAnalyzer typeAnalyzer; | 10282 StaticTypeAnalyzer typeAnalyzer; |
| 10290 | 10283 |
| 10284 /* | |
| 10285 * The type system in use during resolution. | |
| 10286 */ | |
| 10287 TypeSystem typeSystem; | |
| 10288 | |
| 10291 /** | 10289 /** |
| 10292 * The class element representing the class containing the current node, | 10290 * The class element representing the class containing the current node, |
| 10293 * or `null` if the current node is not contained in a class. | 10291 * or `null` if the current node is not contained in a class. |
| 10294 */ | 10292 */ |
| 10295 ClassElement enclosingClass = null; | 10293 ClassElement enclosingClass = null; |
| 10296 | 10294 |
| 10297 /** | 10295 /** |
| 10298 * The class declaration representing the class containing the current node, o r `null` if | 10296 * The class declaration representing the class containing the current node, o r `null` if |
| 10299 * the current node is not contained in a class. | 10297 * the current node is not contained in a class. |
| 10300 */ | 10298 */ |
| (...skipping 47 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
| 10348 * listener that will be informed of any errors that are found during | 10346 * listener that will be informed of any errors that are found during |
| 10349 * resolution. The [nameScope] is the scope used to resolve identifiers in the | 10347 * resolution. The [nameScope] is the scope used to resolve identifiers in the |
| 10350 * node that will first be visited. If `null` or unspecified, a new | 10348 * node that will first be visited. If `null` or unspecified, a new |
| 10351 * [LibraryScope] will be created based on [definingLibrary] and | 10349 * [LibraryScope] will be created based on [definingLibrary] and |
| 10352 * [typeProvider]. The [inheritanceManager] is used to perform inheritance | 10350 * [typeProvider]. The [inheritanceManager] is used to perform inheritance |
| 10353 * lookups. If `null` or unspecified, a new [InheritanceManager] will be | 10351 * lookups. If `null` or unspecified, a new [InheritanceManager] will be |
| 10354 * created based on [definingLibrary]. The [typeAnalyzerFactory] is used to | 10352 * created based on [definingLibrary]. The [typeAnalyzerFactory] is used to |
| 10355 * create the type analyzer. If `null` or unspecified, a type analyzer of | 10353 * create the type analyzer. If `null` or unspecified, a type analyzer of |
| 10356 * type [StaticTypeAnalyzer] will be created. | 10354 * type [StaticTypeAnalyzer] will be created. |
| 10357 */ | 10355 */ |
| 10358 ResolverVisitor( | 10356 ResolverVisitor(LibraryElement definingLibrary, Source source, |
| 10359 LibraryElement definingLibrary, | 10357 TypeProvider typeProvider, AnalysisErrorListener errorListener, |
| 10360 Source source, | |
| 10361 TypeProvider typeProvider, | |
| 10362 TypeSystem typeSystem, | |
| 10363 AnalysisErrorListener errorListener, | |
| 10364 {Scope nameScope, | 10358 {Scope nameScope, |
| 10365 InheritanceManager inheritanceManager, | 10359 InheritanceManager inheritanceManager, |
| 10366 StaticTypeAnalyzerFactory typeAnalyzerFactory}) | 10360 StaticTypeAnalyzerFactory typeAnalyzerFactory}) |
| 10367 : super(definingLibrary, source, typeProvider, errorListener, | 10361 : super(definingLibrary, source, typeProvider, errorListener, |
| 10368 nameScope: nameScope) { | 10362 nameScope: nameScope) { |
| 10369 if (inheritanceManager == null) { | 10363 if (inheritanceManager == null) { |
| 10370 this._inheritanceManager = new InheritanceManager(definingLibrary); | 10364 this._inheritanceManager = new InheritanceManager(definingLibrary); |
| 10371 } else { | 10365 } else { |
| 10372 this._inheritanceManager = inheritanceManager; | 10366 this._inheritanceManager = inheritanceManager; |
| 10373 } | 10367 } |
| 10374 this.elementResolver = new ElementResolver(this); | 10368 this.elementResolver = new ElementResolver(this); |
| 10369 this.typeSystem = definingLibrary.context.typeSystem; | |
| 10375 if (typeAnalyzerFactory == null) { | 10370 if (typeAnalyzerFactory == null) { |
| 10376 this.typeAnalyzer = new StaticTypeAnalyzer(this, typeSystem); | 10371 this.typeAnalyzer = new StaticTypeAnalyzer(this); |
| 10377 } else { | 10372 } else { |
| 10378 this.typeAnalyzer = typeAnalyzerFactory(this); | 10373 this.typeAnalyzer = typeAnalyzerFactory(this); |
| 10379 } | 10374 } |
| 10380 } | 10375 } |
| 10381 | 10376 |
| 10382 /** | 10377 /** |
| 10383 * Initialize a newly created visitor to resolve the nodes in a compilation un it. | 10378 * Initialize a newly created visitor to resolve the nodes in a compilation un it. |
| 10384 * | 10379 * |
| 10385 * @param library the library containing the compilation unit being resolved | 10380 * @param library the library containing the compilation unit being resolved |
| 10386 * @param source the source representing the compilation unit being visited | 10381 * @param source the source representing the compilation unit being visited |
| 10387 * @param typeProvider the object used to access the types from the core libra ry | 10382 * @param typeProvider the object used to access the types from the core libra ry |
| 10388 * | 10383 * |
| 10389 * Deprecated. Please use unnamed constructor instead. | 10384 * Deprecated. Please use unnamed constructor instead. |
| 10390 */ | 10385 */ |
| 10391 @deprecated | 10386 @deprecated |
| 10392 ResolverVisitor.con1(Library library, Source source, | 10387 ResolverVisitor.con1( |
| 10393 TypeProvider typeProvider, TypeSystem typeSystem, | 10388 Library library, Source source, TypeProvider typeProvider, |
| 10394 {StaticTypeAnalyzerFactory typeAnalyzerFactory}) | 10389 {StaticTypeAnalyzerFactory typeAnalyzerFactory}) |
| 10395 : this(library.libraryElement, source, typeProvider, typeSystem, | 10390 : this( |
| 10396 library.errorListener, | 10391 library.libraryElement, source, typeProvider, library.errorListener, |
| 10397 nameScope: library.libraryScope, | 10392 nameScope: library.libraryScope, |
| 10398 inheritanceManager: library.inheritanceManager, | 10393 inheritanceManager: library.inheritanceManager, |
| 10399 typeAnalyzerFactory: typeAnalyzerFactory); | 10394 typeAnalyzerFactory: typeAnalyzerFactory); |
| 10400 | 10395 |
| 10401 /** | 10396 /** |
| 10402 * Return the element representing the function containing the current node, o r `null` if | 10397 * Return the element representing the function containing the current node, o r `null` if |
| 10403 * the current node is not contained in a function. | 10398 * the current node is not contained in a function. |
| 10404 * | 10399 * |
| 10405 * @return the element representing the function containing the current node | 10400 * @return the element representing the function containing the current node |
| 10406 */ | 10401 */ |
| (...skipping 5385 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
| 15792 | 15787 |
| 15793 class _ConstantVerifier_validateInitializerExpression extends ConstantVisitor { | 15788 class _ConstantVerifier_validateInitializerExpression extends ConstantVisitor { |
| 15794 final ConstantVerifier verifier; | 15789 final ConstantVerifier verifier; |
| 15795 | 15790 |
| 15796 List<ParameterElement> parameterElements; | 15791 List<ParameterElement> parameterElements; |
| 15797 | 15792 |
| 15798 TypeSystem _typeSystem; | 15793 TypeSystem _typeSystem; |
| 15799 | 15794 |
| 15800 _ConstantVerifier_validateInitializerExpression( | 15795 _ConstantVerifier_validateInitializerExpression( |
| 15801 TypeProvider typeProvider, | 15796 TypeProvider typeProvider, |
| 15802 TypeSystem typeSystem, | |
| 15803 ErrorReporter errorReporter, | 15797 ErrorReporter errorReporter, |
| 15804 this.verifier, | 15798 this.verifier, |
| 15805 this.parameterElements, | 15799 this.parameterElements, |
| 15806 DeclaredVariables declaredVariables) | 15800 DeclaredVariables declaredVariables, |
| 15807 : _typeSystem = typeSystem, | 15801 {TypeSystem typeSystem}) |
| 15802 : _typeSystem = (typeSystem != null) ? typeSystem : new TypeSystemImpl(), | |
| 15808 super( | 15803 super( |
| 15809 new ConstantEvaluationEngine( | 15804 new ConstantEvaluationEngine(typeProvider, declaredVariables, |
| 15810 typeProvider, typeSystem, declaredVariables), | 15805 typeSystem: typeSystem), |
| 15811 errorReporter); | 15806 errorReporter); |
| 15812 | 15807 |
| 15813 @override | 15808 @override |
| 15814 DartObjectImpl visitSimpleIdentifier(SimpleIdentifier node) { | 15809 DartObjectImpl visitSimpleIdentifier(SimpleIdentifier node) { |
| 15815 Element element = node.staticElement; | 15810 Element element = node.staticElement; |
| 15816 for (ParameterElement parameterElement in parameterElements) { | 15811 for (ParameterElement parameterElement in parameterElements) { |
| 15817 if (identical(parameterElement, element) && parameterElement != null) { | 15812 if (identical(parameterElement, element) && parameterElement != null) { |
| 15818 DartType type = parameterElement.type; | 15813 DartType type = parameterElement.type; |
| 15819 if (type != null) { | 15814 if (type != null) { |
| 15820 if (type.isDynamic) { | 15815 if (type.isDynamic) { |
| (...skipping 138 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
| 15959 nonFields.add(node); | 15954 nonFields.add(node); |
| 15960 return null; | 15955 return null; |
| 15961 } | 15956 } |
| 15962 | 15957 |
| 15963 @override | 15958 @override |
| 15964 Object visitNode(AstNode node) => node.accept(TypeResolverVisitor_this); | 15959 Object visitNode(AstNode node) => node.accept(TypeResolverVisitor_this); |
| 15965 | 15960 |
| 15966 @override | 15961 @override |
| 15967 Object visitWithClause(WithClause node) => null; | 15962 Object visitWithClause(WithClause node) => null; |
| 15968 } | 15963 } |
| OLD | NEW |