| OLD | NEW |
| 1 // Copyright (c) 2016, the Dart project authors. Please see the AUTHORS file | 1 // Copyright (c) 2016, 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 library kernel.analyzer.ast_from_analyzer; | 4 library kernel.analyzer.ast_from_analyzer; |
| 5 | 5 |
| 6 import '../ast.dart' as ast; | 6 import '../ast.dart' as ast; |
| 7 import '../frontend/accessors.dart'; | 7 import '../frontend/accessors.dart'; |
| 8 import '../frontend/super_initializers.dart'; | 8 import '../frontend/super_initializers.dart'; |
| 9 import '../log.dart'; | 9 import '../log.dart'; |
| 10 import '../type_algebra.dart'; | 10 import '../type_algebra.dart'; |
| (...skipping 312 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 323 ast.Supertype buildSupertype(DartType type) { | 323 ast.Supertype buildSupertype(DartType type) { |
| 324 if (type is InterfaceType) { | 324 if (type is InterfaceType) { |
| 325 var classElement = type.element; | 325 var classElement = type.element; |
| 326 if (classElement == null) return getRootClassReference().asRawSupertype; | 326 if (classElement == null) return getRootClassReference().asRawSupertype; |
| 327 var classNode = getClassReference(classElement); | 327 var classNode = getClassReference(classElement); |
| 328 if (classNode.typeParameters.isEmpty || | 328 if (classNode.typeParameters.isEmpty || |
| 329 classNode.typeParameters.length != type.typeArguments.length) { | 329 classNode.typeParameters.length != type.typeArguments.length) { |
| 330 return classNode.asRawSupertype; | 330 return classNode.asRawSupertype; |
| 331 } else { | 331 } else { |
| 332 return new ast.Supertype(classNode, | 332 return new ast.Supertype(classNode, |
| 333 type.typeArguments.map(buildType).toList(growable: false)); | 333 type.typeArguments.map(buildType).toList(growable: false)); |
| 334 } | 334 } |
| 335 } | 335 } |
| 336 return getRootClassReference().asRawSupertype; | 336 return getRootClassReference().asRawSupertype; |
| 337 } | 337 } |
| 338 | 338 |
| 339 ast.DartType buildTypeAnnotation(AstNode node) { | 339 ast.DartType buildTypeAnnotation(AstNode node) { |
| 340 return new TypeAnnotationBuilder(this).build(node); | 340 return new TypeAnnotationBuilder(this).build(node); |
| 341 } | 341 } |
| 342 | 342 |
| 343 ast.DartType buildOptionalTypeAnnotation(AstNode node) { | 343 ast.DartType buildOptionalTypeAnnotation(AstNode node) { |
| (...skipping 52 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 396 } | 396 } |
| 397 | 397 |
| 398 List<ast.TypeParameter> buildOptionalTypeParameterList( | 398 List<ast.TypeParameter> buildOptionalTypeParameterList( |
| 399 TypeParameterList node) { | 399 TypeParameterList node) { |
| 400 if (node == null) return <ast.TypeParameter>[]; | 400 if (node == null) return <ast.TypeParameter>[]; |
| 401 return node.typeParameters.map(buildTypeParameter).toList(); | 401 return node.typeParameters.map(buildTypeParameter).toList(); |
| 402 } | 402 } |
| 403 | 403 |
| 404 ast.TypeParameter buildTypeParameter(TypeParameter node) { | 404 ast.TypeParameter buildTypeParameter(TypeParameter node) { |
| 405 return makeTypeParameter(node.element, | 405 return makeTypeParameter(node.element, |
| 406 bound: | 406 bound: buildOptionalTypeAnnotation(node.bound) ?? |
| 407 buildOptionalTypeAnnotation(node.bound) ?? | |
| 408 defaultTypeParameterBound); | 407 defaultTypeParameterBound); |
| 409 } | 408 } |
| 410 | 409 |
| 411 ConstructorElement findDefaultConstructor(ClassElement class_) { | 410 ConstructorElement findDefaultConstructor(ClassElement class_) { |
| 412 for (var constructor in class_.constructors) { | 411 for (var constructor in class_.constructors) { |
| 413 // Note: isDefaultConstructor checks if the constructor is suitable for | 412 // Note: isDefaultConstructor checks if the constructor is suitable for |
| 414 // being invoked without arguments. It does not imply that it is | 413 // being invoked without arguments. It does not imply that it is |
| 415 // synthetic. | 414 // synthetic. |
| 416 if (constructor.isDefaultConstructor && !constructor.isFactory) { | 415 if (constructor.isDefaultConstructor && !constructor.isFactory) { |
| 417 return constructor; | 416 return constructor; |
| (...skipping 257 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 675 if (positionals.isNotEmpty && | 674 if (positionals.isNotEmpty && |
| 676 parameters[positionals.length - 1].parameterKind == named) { | 675 parameters[positionals.length - 1].parameterKind == named) { |
| 677 return false; // Too many positional arguments. | 676 return false; // Too many positional arguments. |
| 678 } | 677 } |
| 679 if (arguments.named.isEmpty) return true; | 678 if (arguments.named.isEmpty) return true; |
| 680 int firstNamedParameter = positionals.length; | 679 int firstNamedParameter = positionals.length; |
| 681 while (firstNamedParameter < parameters.length && | 680 while (firstNamedParameter < parameters.length && |
| 682 parameters[firstNamedParameter].parameterKind != ParameterKind.NAMED) { | 681 parameters[firstNamedParameter].parameterKind != ParameterKind.NAMED) { |
| 683 ++firstNamedParameter; | 682 ++firstNamedParameter; |
| 684 } | 683 } |
| 685 namedLoop: for (int i = 0; i < arguments.named.length; ++i) { | 684 namedLoop: |
| 685 for (int i = 0; i < arguments.named.length; ++i) { |
| 686 String name = arguments.named[i].name; | 686 String name = arguments.named[i].name; |
| 687 for (int j = firstNamedParameter; j < parameters.length; ++j) { | 687 for (int j = firstNamedParameter; j < parameters.length; ++j) { |
| 688 if (parameters[j].parameterKind == ParameterKind.NAMED && | 688 if (parameters[j].parameterKind == ParameterKind.NAMED && |
| 689 parameters[j].name == name) { | 689 parameters[j].name == name) { |
| 690 continue namedLoop; | 690 continue namedLoop; |
| 691 } | 691 } |
| 692 } | 692 } |
| 693 return false; | 693 return false; |
| 694 } | 694 } |
| 695 return true; | 695 return true; |
| (...skipping 621 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 1317 } | 1317 } |
| 1318 | 1318 |
| 1319 ast.Expression visitAssignmentExpression(AssignmentExpression node) { | 1319 ast.Expression visitAssignmentExpression(AssignmentExpression node) { |
| 1320 bool voidContext = isInVoidContext(node); | 1320 bool voidContext = isInVoidContext(node); |
| 1321 String operator = node.operator.value(); | 1321 String operator = node.operator.value(); |
| 1322 var leftHand = buildLeftHandValue(node.leftHandSide); | 1322 var leftHand = buildLeftHandValue(node.leftHandSide); |
| 1323 var rightHand = build(node.rightHandSide); | 1323 var rightHand = build(node.rightHandSide); |
| 1324 if (operator == '=') { | 1324 if (operator == '=') { |
| 1325 return leftHand.buildAssignment(rightHand, voidContext: voidContext); | 1325 return leftHand.buildAssignment(rightHand, voidContext: voidContext); |
| 1326 } else if (operator == '??=') { | 1326 } else if (operator == '??=') { |
| 1327 return leftHand.buildNullAwareAssignment(rightHand, | 1327 return leftHand.buildNullAwareAssignment( |
| 1328 rightHand, scope.buildType(node.staticType), |
| 1328 voidContext: voidContext); | 1329 voidContext: voidContext); |
| 1329 } else { | 1330 } else { |
| 1330 // Cut off the trailing '='. | 1331 // Cut off the trailing '='. |
| 1331 var name = new ast.Name(operator.substring(0, operator.length - 1)); | 1332 var name = new ast.Name(operator.substring(0, operator.length - 1)); |
| 1332 return leftHand.buildCompoundAssignment(name, rightHand, | 1333 return leftHand.buildCompoundAssignment(name, rightHand, |
| 1333 voidContext: voidContext, | 1334 voidContext: voidContext, |
| 1334 interfaceTarget: scope.resolveInterfaceMethod(node.staticElement)); | 1335 interfaceTarget: scope.resolveInterfaceMethod(node.staticElement)); |
| 1335 } | 1336 } |
| 1336 } | 1337 } |
| 1337 | 1338 |
| (...skipping 345 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 1683 var inferredType = scope.getInferredType(node); | 1684 var inferredType = scope.getInferredType(node); |
| 1684 if (inferredType is ast.InterfaceType) { | 1685 if (inferredType is ast.InterfaceType) { |
| 1685 return inferredType.typeArguments.toList(); | 1686 return inferredType.typeArguments.toList(); |
| 1686 } | 1687 } |
| 1687 int numberOfTypeArguments = | 1688 int numberOfTypeArguments = |
| 1688 classElement == null ? 0 : classElement.typeParameters.length; | 1689 classElement == null ? 0 : classElement.typeParameters.length; |
| 1689 return new List<ast.DartType>.filled( | 1690 return new List<ast.DartType>.filled( |
| 1690 numberOfTypeArguments, const ast.DynamicType(), | 1691 numberOfTypeArguments, const ast.DynamicType(), |
| 1691 growable: true); | 1692 growable: true); |
| 1692 } | 1693 } |
| 1694 |
| 1693 var arguments = buildArguments(node.argumentList, | 1695 var arguments = buildArguments(node.argumentList, |
| 1694 explicitTypeArguments: node.constructorName.type.typeArguments, | 1696 explicitTypeArguments: node.constructorName.type.typeArguments, |
| 1695 inferTypeArguments: inferTypeArguments); | 1697 inferTypeArguments: inferTypeArguments); |
| 1696 ast.Expression noSuchMethodError() { | 1698 ast.Expression noSuchMethodError() { |
| 1697 return node.isConst | 1699 return node.isConst |
| 1698 ? scope.emitInvalidConstant() | 1700 ? scope.emitInvalidConstant() |
| 1699 : scope.buildThrowNoSuchMethodError( | 1701 : scope.buildThrowNoSuchMethodError( |
| 1700 new ast.NullLiteral(), '${node.constructorName}', arguments, | 1702 new ast.NullLiteral(), '${node.constructorName}', arguments, |
| 1701 candidateTarget: element); | 1703 candidateTarget: element); |
| 1702 } | 1704 } |
| 1705 |
| 1703 if (element == null) { | 1706 if (element == null) { |
| 1704 return noSuchMethodError(); | 1707 return noSuchMethodError(); |
| 1705 } | 1708 } |
| 1706 assert(classElement != null); | 1709 assert(classElement != null); |
| 1707 var redirect = getEffectiveFactoryTarget(element); | 1710 var redirect = getEffectiveFactoryTarget(element); |
| 1708 if (redirect == null) { | 1711 if (redirect == null) { |
| 1709 return scope.buildThrowCompileTimeError( | 1712 return scope.buildThrowCompileTimeError( |
| 1710 CompileTimeErrorCode.RECURSIVE_FACTORY_REDIRECT.message); | 1713 CompileTimeErrorCode.RECURSIVE_FACTORY_REDIRECT.message); |
| 1711 } | 1714 } |
| 1712 if (redirect != element) { | 1715 if (redirect != element) { |
| (...skipping 131 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 1844 var receiver = makeOrReuseVariable(build(target)); | 1847 var receiver = makeOrReuseVariable(build(target)); |
| 1845 return makeLet( | 1848 return makeLet( |
| 1846 receiver, | 1849 receiver, |
| 1847 new ast.ConditionalExpression( | 1850 new ast.ConditionalExpression( |
| 1848 buildIsNull(new ast.VariableGet(receiver)), | 1851 buildIsNull(new ast.VariableGet(receiver)), |
| 1849 new ast.NullLiteral(), | 1852 new ast.NullLiteral(), |
| 1850 buildDecomposableMethodInvocation( | 1853 buildDecomposableMethodInvocation( |
| 1851 new ast.VariableGet(receiver), | 1854 new ast.VariableGet(receiver), |
| 1852 scope.buildName(node.methodName), | 1855 scope.buildName(node.methodName), |
| 1853 buildArgumentsForInvocation(node), | 1856 buildArgumentsForInvocation(node), |
| 1854 element))); | 1857 element), |
| 1858 scope.buildType(node.staticType))); |
| 1855 } else { | 1859 } else { |
| 1856 return buildDecomposableMethodInvocation( | 1860 return buildDecomposableMethodInvocation( |
| 1857 build(node.target), | 1861 build(node.target), |
| 1858 scope.buildName(node.methodName), | 1862 scope.buildName(node.methodName), |
| 1859 buildArgumentsForInvocation(node), | 1863 buildArgumentsForInvocation(node), |
| 1860 element); | 1864 element); |
| 1861 } | 1865 } |
| 1862 } | 1866 } |
| 1863 | 1867 |
| 1864 ast.Expression visitNamedExpression(NamedExpression node) { | 1868 ast.Expression visitNamedExpression(NamedExpression node) { |
| (...skipping 74 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 1939 return new SuperPropertyAccessor( | 1943 return new SuperPropertyAccessor( |
| 1940 scope.buildName(node.propertyName), | 1944 scope.buildName(node.propertyName), |
| 1941 scope.resolveConcreteGet(element, auxiliary), | 1945 scope.resolveConcreteGet(element, auxiliary), |
| 1942 scope.resolveConcreteSet(element, auxiliary)); | 1946 scope.resolveConcreteSet(element, auxiliary)); |
| 1943 } else if (target is Identifier && target.staticElement is ClassElement) { | 1947 } else if (target is Identifier && target.staticElement is ClassElement) { |
| 1944 // Note that this case also covers null-aware static access on a class, | 1948 // Note that this case also covers null-aware static access on a class, |
| 1945 // which is equivalent to a regular static access. | 1949 // which is equivalent to a regular static access. |
| 1946 return scope.staticAccess(node.propertyName.name, element, auxiliary); | 1950 return scope.staticAccess(node.propertyName.name, element, auxiliary); |
| 1947 } else if (node.operator.value() == '?.') { | 1951 } else if (node.operator.value() == '?.') { |
| 1948 return new NullAwarePropertyAccessor( | 1952 return new NullAwarePropertyAccessor( |
| 1949 build(target), scope.buildName(node.propertyName), getter, setter); | 1953 build(target), scope.buildName(node.propertyName), getter, setter, |
| 1954 scope.buildType(node.staticType)); |
| 1950 } else { | 1955 } else { |
| 1951 return PropertyAccessor.make( | 1956 return PropertyAccessor.make( |
| 1952 build(target), scope.buildName(node.propertyName), getter, setter); | 1957 build(target), scope.buildName(node.propertyName), getter, setter); |
| 1953 } | 1958 } |
| 1954 } | 1959 } |
| 1955 | 1960 |
| 1956 ast.Expression visitRethrowExpression(RethrowExpression node) { | 1961 ast.Expression visitRethrowExpression(RethrowExpression node) { |
| 1957 return new ast.Rethrow(); | 1962 return new ast.Rethrow(); |
| 1958 } | 1963 } |
| 1959 | 1964 |
| (...skipping 664 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 2624 // Redirecting factories with resolved targets don't show up here. | 2629 // Redirecting factories with resolved targets don't show up here. |
| 2625 assert(node.element.redirectedConstructor == null); | 2630 assert(node.element.redirectedConstructor == null); |
| 2626 var function = procedure.function; | 2631 var function = procedure.function; |
| 2627 var name = node.redirectedConstructor.type.name.name; | 2632 var name = node.redirectedConstructor.type.name.name; |
| 2628 if (node.redirectedConstructor.name != null) { | 2633 if (node.redirectedConstructor.name != null) { |
| 2629 name += '.' + node.redirectedConstructor.name.name; | 2634 name += '.' + node.redirectedConstructor.name.name; |
| 2630 } | 2635 } |
| 2631 // TODO(asgerf): Sometimes a TypeError should be thrown. | 2636 // TODO(asgerf): Sometimes a TypeError should be thrown. |
| 2632 function.body = new ast.ExpressionStatement( | 2637 function.body = new ast.ExpressionStatement( |
| 2633 scope.buildThrowNoSuchMethodError( | 2638 scope.buildThrowNoSuchMethodError( |
| 2634 new ast.NullLiteral(), | 2639 new ast.NullLiteral(), name, new ast.Arguments.empty())) |
| 2635 name, | 2640 ..parent = function; |
| 2636 new ast.Arguments.empty()))..parent = function; | |
| 2637 } | 2641 } |
| 2638 } | 2642 } |
| 2639 | 2643 |
| 2640 visitMethodDeclaration(MethodDeclaration node) { | 2644 visitMethodDeclaration(MethodDeclaration node) { |
| 2641 addAnnotations(node.metadata); | 2645 addAnnotations(node.metadata); |
| 2642 ast.Procedure procedure = currentMember; | 2646 ast.Procedure procedure = currentMember; |
| 2643 procedure.function = scope.buildFunctionNode(node.parameters, node.body, | 2647 procedure.function = scope.buildFunctionNode(node.parameters, node.body, |
| 2644 returnType: node.returnType, | 2648 returnType: node.returnType, |
| 2645 inferredReturnType: scope.buildType(node.element.returnType), | 2649 inferredReturnType: scope.buildType(node.element.returnType), |
| 2646 typeParameters: | 2650 typeParameters: |
| (...skipping 125 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 2772 if (element is FieldElement) return element.getter; | 2776 if (element is FieldElement) return element.getter; |
| 2773 return element; | 2777 return element; |
| 2774 } | 2778 } |
| 2775 | 2779 |
| 2776 Element desynthesizeSetter(Element element) { | 2780 Element desynthesizeSetter(Element element) { |
| 2777 if (element == null || !element.isSynthetic) return element; | 2781 if (element == null || !element.isSynthetic) return element; |
| 2778 if (element is PropertyAccessorElement) return element.variable; | 2782 if (element is PropertyAccessorElement) return element.variable; |
| 2779 if (element is FieldElement) return element.setter; | 2783 if (element is FieldElement) return element.setter; |
| 2780 return element; | 2784 return element; |
| 2781 } | 2785 } |
| OLD | NEW |