| OLD | NEW |
| 1 // Copyright (c) 2015, the Dart project authors. Please see the AUTHORS file | 1 // Copyright (c) 2015, 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 summary_resynthesizer; | 5 library summary_resynthesizer; |
| 6 | 6 |
| 7 import 'dart:collection'; | 7 import 'dart:collection'; |
| 8 | 8 |
| 9 import 'package:analyzer/dart/ast/ast.dart'; | 9 import 'package:analyzer/dart/ast/ast.dart'; |
| 10 import 'package:analyzer/dart/element/element.dart'; | 10 import 'package:analyzer/dart/element/element.dart'; |
| 11 import 'package:analyzer/dart/element/type.dart'; | 11 import 'package:analyzer/dart/element/type.dart'; |
| 12 import 'package:analyzer/src/dart/element/element.dart'; | 12 import 'package:analyzer/src/dart/element/element.dart'; |
| 13 import 'package:analyzer/src/dart/element/type.dart'; | 13 import 'package:analyzer/src/dart/element/type.dart'; |
| 14 import 'package:analyzer/src/generated/constant.dart'; | |
| 15 import 'package:analyzer/src/generated/element_handle.dart'; | 14 import 'package:analyzer/src/generated/element_handle.dart'; |
| 16 import 'package:analyzer/src/generated/engine.dart'; | 15 import 'package:analyzer/src/generated/engine.dart'; |
| 17 import 'package:analyzer/src/generated/resolver.dart'; | 16 import 'package:analyzer/src/generated/resolver.dart'; |
| 18 import 'package:analyzer/src/generated/scanner.dart'; | 17 import 'package:analyzer/src/generated/scanner.dart'; |
| 19 import 'package:analyzer/src/generated/source_io.dart'; | 18 import 'package:analyzer/src/generated/source_io.dart'; |
| 20 import 'package:analyzer/src/generated/testing/ast_factory.dart'; | 19 import 'package:analyzer/src/generated/testing/ast_factory.dart'; |
| 21 import 'package:analyzer/src/generated/testing/token_factory.dart'; | 20 import 'package:analyzer/src/generated/testing/token_factory.dart'; |
| 22 import 'package:analyzer/src/generated/utilities_dart.dart'; | 21 import 'package:analyzer/src/generated/utilities_dart.dart'; |
| 23 import 'package:analyzer/src/summary/format.dart'; | 22 import 'package:analyzer/src/summary/format.dart'; |
| 24 import 'package:analyzer/src/task/dart.dart' show ConstantEvaluationTarget; | |
| 25 | 23 |
| 26 /** | 24 /** |
| 27 * Implementation of [ElementResynthesizer] used when resynthesizing an element | 25 * Implementation of [ElementResynthesizer] used when resynthesizing an element |
| 28 * model from summaries. | 26 * model from summaries. |
| 29 */ | 27 */ |
| 30 abstract class SummaryResynthesizer extends ElementResynthesizer { | 28 abstract class SummaryResynthesizer extends ElementResynthesizer { |
| 31 /** | 29 /** |
| 32 * The parent [SummaryResynthesizer] which is asked to resynthesize elements | 30 * The parent [SummaryResynthesizer] which is asked to resynthesize elements |
| 33 * and get summaries before this resynthesizer attempts to do this. | 31 * and get summaries before this resynthesizer attempts to do this. |
| 34 * Can be `null`. | 32 * Can be `null`. |
| (...skipping 275 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 310 Expression expr = _pop(); | 308 Expression expr = _pop(); |
| 311 InterpolationElement element = _newInterpolationElement(expr); | 309 InterpolationElement element = _newInterpolationElement(expr); |
| 312 elements.insert(0, element); | 310 elements.insert(0, element); |
| 313 } | 311 } |
| 314 _push(AstFactory.string(elements)); | 312 _push(AstFactory.string(elements)); |
| 315 break; | 313 break; |
| 316 // binary | 314 // binary |
| 317 case UnlinkedConstOperation.equal: | 315 case UnlinkedConstOperation.equal: |
| 318 _pushBinary(TokenType.EQ_EQ); | 316 _pushBinary(TokenType.EQ_EQ); |
| 319 break; | 317 break; |
| 318 case UnlinkedConstOperation.notEqual: |
| 319 _pushBinary(TokenType.BANG_EQ); |
| 320 break; |
| 320 case UnlinkedConstOperation.and: | 321 case UnlinkedConstOperation.and: |
| 321 _pushBinary(TokenType.AMPERSAND_AMPERSAND); | 322 _pushBinary(TokenType.AMPERSAND_AMPERSAND); |
| 322 break; | 323 break; |
| 323 case UnlinkedConstOperation.or: | 324 case UnlinkedConstOperation.or: |
| 324 _pushBinary(TokenType.BAR_BAR); | 325 _pushBinary(TokenType.BAR_BAR); |
| 325 break; | 326 break; |
| 326 case UnlinkedConstOperation.bitXor: | 327 case UnlinkedConstOperation.bitXor: |
| 327 _pushBinary(TokenType.CARET); | 328 _pushBinary(TokenType.CARET); |
| 328 break; | 329 break; |
| 329 case UnlinkedConstOperation.bitAnd: | 330 case UnlinkedConstOperation.bitAnd: |
| (...skipping 56 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 386 _push( | 387 _push( |
| 387 AstFactory.conditionalExpression(condition, thenExpr, elseExpr)); | 388 AstFactory.conditionalExpression(condition, thenExpr, elseExpr)); |
| 388 break; | 389 break; |
| 389 // identical | 390 // identical |
| 390 case UnlinkedConstOperation.identical: | 391 case UnlinkedConstOperation.identical: |
| 391 Expression second = _pop(); | 392 Expression second = _pop(); |
| 392 Expression first = _pop(); | 393 Expression first = _pop(); |
| 393 _push(AstFactory.methodInvocation( | 394 _push(AstFactory.methodInvocation( |
| 394 null, 'identical', <Expression>[first, second])); | 395 null, 'identical', <Expression>[first, second])); |
| 395 break; | 396 break; |
| 397 // containers |
| 396 case UnlinkedConstOperation.makeUntypedList: | 398 case UnlinkedConstOperation.makeUntypedList: |
| 397 _pushList(null); | 399 _pushList(null); |
| 398 break; | 400 break; |
| 399 case UnlinkedConstOperation.makeTypedList: | 401 case UnlinkedConstOperation.makeTypedList: |
| 400 TypeName itemType = _newTypeName(); | 402 TypeName itemType = _newTypeName(); |
| 401 _pushList(AstFactory.typeArgumentList(<TypeName>[itemType])); | 403 _pushList(AstFactory.typeArgumentList(<TypeName>[itemType])); |
| 402 break; | 404 break; |
| 403 case UnlinkedConstOperation.makeUntypedMap: | 405 case UnlinkedConstOperation.makeUntypedMap: |
| 404 _pushMap(null); | 406 _pushMap(null); |
| 405 break; | 407 break; |
| 406 case UnlinkedConstOperation.makeTypedMap: | 408 case UnlinkedConstOperation.makeTypedMap: |
| 407 TypeName keyType = _newTypeName(); | 409 TypeName keyType = _newTypeName(); |
| 408 TypeName valueType = _newTypeName(); | 410 TypeName valueType = _newTypeName(); |
| 409 _pushMap(AstFactory.typeArgumentList(<TypeName>[keyType, valueType])); | 411 _pushMap(AstFactory.typeArgumentList(<TypeName>[keyType, valueType])); |
| 410 break; | 412 break; |
| 411 case UnlinkedConstOperation.pushReference: | 413 case UnlinkedConstOperation.pushReference: |
| 412 case UnlinkedConstOperation.invokeConstructor: | 414 case UnlinkedConstOperation.invokeConstructor: |
| 413 case UnlinkedConstOperation.length: | 415 case UnlinkedConstOperation.length: |
| 414 return AstFactory.nullLiteral(); | 416 return AstFactory.nullLiteral(); |
| 415 // throw new StateError('Unsupported constant operation $operation'); | 417 // throw new StateError('Unsupported constant operation $operation'); |
| 416 } | 418 } |
| 417 } | 419 } |
| 418 return stack.single; | 420 return stack.single; |
| 419 } | 421 } |
| 420 | 422 |
| 421 void _pushMap(TypeArgumentList typeArguments) { | |
| 422 int count = uc.ints[intPtr++]; | |
| 423 List<MapLiteralEntry> entries = <MapLiteralEntry>[]; | |
| 424 for (int i = 0; i < count; i++) { | |
| 425 Expression value = _pop(); | |
| 426 Expression key = _pop(); | |
| 427 entries.insert(0, AstFactory.mapLiteralEntry2(key, value)); | |
| 428 } | |
| 429 _push(AstFactory.mapLiteral(Keyword.CONST, typeArguments, entries)); | |
| 430 } | |
| 431 | |
| 432 TypeName _buildTypeAst(DartType type) { | 423 TypeName _buildTypeAst(DartType type) { |
| 433 if (type is DynamicTypeImpl) { | 424 if (type is DynamicTypeImpl) { |
| 434 return AstFactory.typeName4('dynamic')..type = type; | 425 TypeName node = AstFactory.typeName4('dynamic'); |
| 426 node.type = type; |
| 427 (node.name as SimpleIdentifier).staticElement = type.element; |
| 428 return node; |
| 435 } else if (type is InterfaceType) { | 429 } else if (type is InterfaceType) { |
| 436 List<TypeName> argumentNodes = | 430 List<TypeName> argumentNodes = |
| 437 type.typeArguments.map(_buildTypeAst).toList(); | 431 type.typeArguments.map(_buildTypeAst).toList(); |
| 438 TypeName node = AstFactory.typeName4(type.name, argumentNodes); | 432 TypeName node = AstFactory.typeName4(type.name, argumentNodes); |
| 439 node.type = type; | 433 node.type = type; |
| 434 (node.name as SimpleIdentifier).staticElement = type.element; |
| 440 return node; | 435 return node; |
| 441 } | 436 } |
| 442 throw new StateError('Unsupported type $type'); | 437 throw new StateError('Unsupported type $type'); |
| 443 } | 438 } |
| 444 | 439 |
| 445 InterpolationElement _newInterpolationElement(Expression expr) { | 440 InterpolationElement _newInterpolationElement(Expression expr) { |
| 446 if (expr is SimpleStringLiteral) { | 441 if (expr is SimpleStringLiteral) { |
| 447 return new InterpolationString(expr.literal, expr.value); | 442 return new InterpolationString(expr.literal, expr.value); |
| 448 } else { | 443 } else { |
| 449 return new InterpolationExpression( | 444 return new InterpolationExpression( |
| (...skipping 27 matching lines...) Expand all Loading... |
| 477 | 472 |
| 478 void _pushList(TypeArgumentList typeArguments) { | 473 void _pushList(TypeArgumentList typeArguments) { |
| 479 int count = uc.ints[intPtr++]; | 474 int count = uc.ints[intPtr++]; |
| 480 List<Expression> elements = <Expression>[]; | 475 List<Expression> elements = <Expression>[]; |
| 481 for (int i = 0; i < count; i++) { | 476 for (int i = 0; i < count; i++) { |
| 482 elements.insert(0, _pop()); | 477 elements.insert(0, _pop()); |
| 483 } | 478 } |
| 484 _push(AstFactory.listLiteral2(Keyword.CONST, typeArguments, elements)); | 479 _push(AstFactory.listLiteral2(Keyword.CONST, typeArguments, elements)); |
| 485 } | 480 } |
| 486 | 481 |
| 482 void _pushMap(TypeArgumentList typeArguments) { |
| 483 int count = uc.ints[intPtr++]; |
| 484 List<MapLiteralEntry> entries = <MapLiteralEntry>[]; |
| 485 for (int i = 0; i < count; i++) { |
| 486 Expression value = _pop(); |
| 487 Expression key = _pop(); |
| 488 entries.insert(0, AstFactory.mapLiteralEntry2(key, value)); |
| 489 } |
| 490 _push(AstFactory.mapLiteral(Keyword.CONST, typeArguments, entries)); |
| 491 } |
| 492 |
| 487 void _pushPrefix(TokenType operator) { | 493 void _pushPrefix(TokenType operator) { |
| 488 Expression operand = _pop(); | 494 Expression operand = _pop(); |
| 489 _push(AstFactory.prefixExpression(operator, operand)); | 495 _push(AstFactory.prefixExpression(operator, operand)); |
| 490 } | 496 } |
| 491 } | 497 } |
| 492 | 498 |
| 493 /** | 499 /** |
| 494 * A single constant variable for which the constant value should be computed. | |
| 495 * | |
| 496 * TODO(scheglov) we will probably need to add dependency list | |
| 497 */ | |
| 498 class _ConstVariable { | |
| 499 final ConstVariableElement element; | |
| 500 | |
| 501 _ConstVariable(this.element); | |
| 502 } | |
| 503 | |
| 504 /** | |
| 505 * An instance of [_LibraryResynthesizer] is responsible for resynthesizing the | 500 * An instance of [_LibraryResynthesizer] is responsible for resynthesizing the |
| 506 * elements in a single library from that library's summary. | 501 * elements in a single library from that library's summary. |
| 507 */ | 502 */ |
| 508 class _LibraryResynthesizer { | 503 class _LibraryResynthesizer { |
| 509 /** | 504 /** |
| 510 * The [SummaryResynthesizer] which is being used to obtain summaries. | 505 * The [SummaryResynthesizer] which is being used to obtain summaries. |
| 511 */ | 506 */ |
| 512 final SummaryResynthesizer summaryResynthesizer; | 507 final SummaryResynthesizer summaryResynthesizer; |
| 513 | 508 |
| 514 /** | 509 /** |
| (...skipping 65 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 580 List<TypeParameterElement> currentTypeParameters = <TypeParameterElement>[]; | 575 List<TypeParameterElement> currentTypeParameters = <TypeParameterElement>[]; |
| 581 | 576 |
| 582 /** | 577 /** |
| 583 * If a class is currently being resynthesized, map from field name to the | 578 * If a class is currently being resynthesized, map from field name to the |
| 584 * corresponding field element. This is used when resynthesizing | 579 * corresponding field element. This is used when resynthesizing |
| 585 * initializing formal parameters. | 580 * initializing formal parameters. |
| 586 */ | 581 */ |
| 587 Map<String, FieldElementImpl> fields; | 582 Map<String, FieldElementImpl> fields; |
| 588 | 583 |
| 589 /** | 584 /** |
| 590 * List of constant variables to compute values for. | |
| 591 */ | |
| 592 List<_ConstVariable> constVariables = <_ConstVariable>[]; | |
| 593 | |
| 594 /** | |
| 595 * List of [_ReferenceInfo] objects describing the references in the current | 585 * List of [_ReferenceInfo] objects describing the references in the current |
| 596 * compilation unit. | 586 * compilation unit. |
| 597 */ | 587 */ |
| 598 List<_ReferenceInfo> referenceInfos; | 588 List<_ReferenceInfo> referenceInfos; |
| 599 | 589 |
| 600 _LibraryResynthesizer(this.summaryResynthesizer, this.linkedLibrary, | 590 _LibraryResynthesizer(this.summaryResynthesizer, this.linkedLibrary, |
| 601 this.unlinkedUnits, this.librarySource) { | 591 this.unlinkedUnits, this.librarySource) { |
| 602 isCoreLibrary = librarySource.uri.toString() == 'dart:core'; | 592 isCoreLibrary = librarySource.uri.toString() == 'dart:core'; |
| 603 } | 593 } |
| 604 | 594 |
| (...skipping 557 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 1162 library.entryPoint = entryPoint; | 1152 library.entryPoint = entryPoint; |
| 1163 } | 1153 } |
| 1164 // Create the synthetic element for `loadLibrary`. | 1154 // Create the synthetic element for `loadLibrary`. |
| 1165 // Until the client received dart:core and dart:async, we cannot do this, | 1155 // Until the client received dart:core and dart:async, we cannot do this, |
| 1166 // because the TypeProvider is not fully initialized. So, it is up to the | 1156 // because the TypeProvider is not fully initialized. So, it is up to the |
| 1167 // Dart SDK client to initialize TypeProvider and finish the dart:core and | 1157 // Dart SDK client to initialize TypeProvider and finish the dart:core and |
| 1168 // dart:async libraries creation. | 1158 // dart:async libraries creation. |
| 1169 if (library.name != 'dart.core' && library.name != 'dart.async') { | 1159 if (library.name != 'dart.core' && library.name != 'dart.async') { |
| 1170 library.createLoadLibraryFunction(summaryResynthesizer.typeProvider); | 1160 library.createLoadLibraryFunction(summaryResynthesizer.typeProvider); |
| 1171 } | 1161 } |
| 1172 // Compute constants. | |
| 1173 for (_ConstVariable constVariable in constVariables) { | |
| 1174 AnalysisContext context = summaryResynthesizer.context; | |
| 1175 ConstantEvaluationEngine constantEvaluationEngine = | |
| 1176 new ConstantEvaluationEngine( | |
| 1177 summaryResynthesizer.typeProvider, context.declaredVariables, | |
| 1178 typeSystem: context.typeSystem); | |
| 1179 ConstantEvaluationTarget constTarget = | |
| 1180 constVariable.element as ConstantEvaluationTarget; | |
| 1181 constantEvaluationEngine.computeConstantValue(constTarget); | |
| 1182 } | |
| 1183 // Done. | 1162 // Done. |
| 1184 return library; | 1163 return library; |
| 1185 } | 1164 } |
| 1186 | 1165 |
| 1187 /** | 1166 /** |
| 1188 * Build the appropriate [DartType] object corresponding to a slot id in the | 1167 * Build the appropriate [DartType] object corresponding to a slot id in the |
| 1189 * [LinkedUnit.types] table. | 1168 * [LinkedUnit.types] table. |
| 1190 */ | 1169 */ |
| 1191 DartType buildLinkedType(int slot) { | 1170 DartType buildLinkedType(int slot) { |
| 1192 if (slot == 0) { | 1171 if (slot == 0) { |
| (...skipping 166 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 1359 TopLevelVariableElementImpl element; | 1338 TopLevelVariableElementImpl element; |
| 1360 if (serializedVariable.constExpr != null) { | 1339 if (serializedVariable.constExpr != null) { |
| 1361 ConstTopLevelVariableElementImpl constElement = | 1340 ConstTopLevelVariableElementImpl constElement = |
| 1362 new ConstTopLevelVariableElementImpl( | 1341 new ConstTopLevelVariableElementImpl( |
| 1363 serializedVariable.name, serializedVariable.nameOffset); | 1342 serializedVariable.name, serializedVariable.nameOffset); |
| 1364 element = constElement; | 1343 element = constElement; |
| 1365 // TODO(scheglov) share const builder? | 1344 // TODO(scheglov) share const builder? |
| 1366 _ConstExprBuilder builder = | 1345 _ConstExprBuilder builder = |
| 1367 new _ConstExprBuilder(this, serializedVariable.constExpr); | 1346 new _ConstExprBuilder(this, serializedVariable.constExpr); |
| 1368 constElement.constantInitializer = builder.build(); | 1347 constElement.constantInitializer = builder.build(); |
| 1369 constVariables.add(new _ConstVariable(constElement)); | |
| 1370 } else { | 1348 } else { |
| 1371 element = new TopLevelVariableElementImpl( | 1349 element = new TopLevelVariableElementImpl( |
| 1372 serializedVariable.name, serializedVariable.nameOffset); | 1350 serializedVariable.name, serializedVariable.nameOffset); |
| 1373 } | 1351 } |
| 1374 buildVariableCommonParts(element, serializedVariable); | 1352 buildVariableCommonParts(element, serializedVariable); |
| 1375 unitHolder.addTopLevelVariable(element); | 1353 unitHolder.addTopLevelVariable(element); |
| 1376 buildImplicitAccessors(element, unitHolder); | 1354 buildImplicitAccessors(element, unitHolder); |
| 1377 } else { | 1355 } else { |
| 1378 FieldElementImpl element = new FieldElementImpl( | 1356 FieldElementImpl element = new FieldElementImpl( |
| 1379 serializedVariable.name, serializedVariable.nameOffset); | 1357 serializedVariable.name, serializedVariable.nameOffset); |
| (...skipping 263 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 1643 return new InterfaceTypeImpl.elementWithNameAndArgs( | 1621 return new InterfaceTypeImpl.elementWithNameAndArgs( |
| 1644 element, name, typeArguments); | 1622 element, name, typeArguments); |
| 1645 } else if (element is FunctionTypeAliasElementHandle) { | 1623 } else if (element is FunctionTypeAliasElementHandle) { |
| 1646 return new FunctionTypeImpl.elementWithNameAndArgs( | 1624 return new FunctionTypeImpl.elementWithNameAndArgs( |
| 1647 element, name, typeArguments, typeArguments.isNotEmpty); | 1625 element, name, typeArguments, typeArguments.isNotEmpty); |
| 1648 } else { | 1626 } else { |
| 1649 return null; | 1627 return null; |
| 1650 } | 1628 } |
| 1651 } | 1629 } |
| 1652 } | 1630 } |
| OLD | NEW |