Chromium Code Reviews| 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 506 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
| 517 } | 517 } |
| 518 | 518 |
| 519 ast.Statement buildMandatoryFunctionBody(FunctionBody body) { | 519 ast.Statement buildMandatoryFunctionBody(FunctionBody body) { |
| 520 try { | 520 try { |
| 521 if (body is BlockFunctionBody) { | 521 if (body is BlockFunctionBody) { |
| 522 return buildStatement(body.block); | 522 return buildStatement(body.block); |
| 523 } else if (body is ExpressionFunctionBody) { | 523 } else if (body is ExpressionFunctionBody) { |
| 524 if (bodyHasVoidReturn(body)) { | 524 if (bodyHasVoidReturn(body)) { |
| 525 return new ast.ExpressionStatement(buildExpression(body.expression)); | 525 return new ast.ExpressionStatement(buildExpression(body.expression)); |
| 526 } else { | 526 } else { |
| 527 return new ast.ReturnStatement(buildExpression(body.expression)); | 527 return new ast.ReturnStatement(buildExpression(body.expression)) |
| 528 ..fileOffset = body.expression.offset; | |
| 528 } | 529 } |
| 529 } else { | 530 } else { |
| 530 return internalError('Missing function body'); | 531 return internalError('Missing function body'); |
| 531 } | 532 } |
| 532 } on _CompilationError catch (e) { | 533 } on _CompilationError catch (e) { |
| 533 return new ast.ExpressionStatement(buildThrowCompileTimeError(e.message)); | 534 return new ast.ExpressionStatement(buildThrowCompileTimeError(e.message)); |
| 534 } | 535 } |
| 535 } | 536 } |
| 536 | 537 |
| 537 ast.AsyncMarker getAsyncMarker({bool isAsync: false, bool isStar: false}) { | 538 ast.AsyncMarker getAsyncMarker({bool isAsync: false, bool isStar: false}) { |
| (...skipping 119 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
| 657 return buildType(element.type); | 658 return buildType(element.type); |
| 658 } else if (element is VariableElement) { | 659 } else if (element is VariableElement) { |
| 659 return buildType(element.type); | 660 return buildType(element.type); |
| 660 } else { | 661 } else { |
| 661 log.severe('Unexpected variable element: $element'); | 662 log.severe('Unexpected variable element: $element'); |
| 662 return const ast.DynamicType(); | 663 return const ast.DynamicType(); |
| 663 } | 664 } |
| 664 } | 665 } |
| 665 | 666 |
| 666 ast.VariableDeclaration makeVariableDeclaration(LocalElement element, | 667 ast.VariableDeclaration makeVariableDeclaration(LocalElement element, |
| 667 {ast.DartType type, ast.Expression initializer}) { | 668 {ast.DartType type, ast.Expression initializer, int equalsOffset}) { |
| 668 var declaration = getVariableReference(element); | 669 var declaration = getVariableReference(element); |
| 670 if (equalsOffset != null) declaration.fileEqualsOffset = equalsOffset; | |
| 669 declaration.type = type ?? getInferredVariableType(element); | 671 declaration.type = type ?? getInferredVariableType(element); |
| 670 if (initializer != null) { | 672 if (initializer != null) { |
| 671 declaration.initializer = initializer..parent = declaration; | 673 declaration.initializer = initializer..parent = declaration; |
| 672 } | 674 } |
| 673 return declaration; | 675 return declaration; |
| 674 } | 676 } |
| 675 | 677 |
| 676 /// Returns true if [arguments] can be accepted by [target] | 678 /// Returns true if [arguments] can be accepted by [target] |
| 677 /// (not taking type checks into account). | 679 /// (not taking type checks into account). |
| 678 bool areArgumentsCompatible( | 680 bool areArgumentsCompatible( |
| (...skipping 275 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
| 954 LabeledStatement labeled = node; | 956 LabeledStatement labeled = node; |
| 955 node = labeled.statement; | 957 node = labeled.statement; |
| 956 } | 958 } |
| 957 if (node is VariableDeclarationStatement) { | 959 if (node is VariableDeclarationStatement) { |
| 958 VariableDeclarationList list = node.variables; | 960 VariableDeclarationList list = node.variables; |
| 959 ast.DartType type = scope.buildOptionalTypeAnnotation(list.type); | 961 ast.DartType type = scope.buildOptionalTypeAnnotation(list.type); |
| 960 for (VariableDeclaration decl in list.variables) { | 962 for (VariableDeclaration decl in list.variables) { |
| 961 LocalElement local = decl.element as dynamic; // Cross cast. | 963 LocalElement local = decl.element as dynamic; // Cross cast. |
| 962 output.add(scope.makeVariableDeclaration(local, | 964 output.add(scope.makeVariableDeclaration(local, |
| 963 type: type, | 965 type: type, |
| 964 initializer: scope.buildOptionalExpression(decl.initializer))); | 966 initializer: scope.buildOptionalExpression(decl.initializer), |
| 967 equalsOffset: decl.equals?.offset)); | |
| 965 } | 968 } |
| 966 } else { | 969 } else { |
| 967 output.add(build(node)); | 970 output.add(build(node)); |
| 968 } | 971 } |
| 969 } | 972 } |
| 970 | 973 |
| 971 ast.Statement makeBreakTarget(ast.Statement node, LabelStack stackNode) { | 974 ast.Statement makeBreakTarget(ast.Statement node, LabelStack stackNode) { |
| 972 if (stackNode.jumps.isEmpty) return node; | 975 if (stackNode.jumps.isEmpty) return node; |
| 973 var labeled = new ast.LabeledStatement(node); | 976 var labeled = new ast.LabeledStatement(node); |
| 974 for (var jump in stackNode.jumps) { | 977 for (var jump in stackNode.jumps) { |
| (...skipping 193 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
| 1168 ast.Statement visitForStatement(ForStatement node) { | 1171 ast.Statement visitForStatement(ForStatement node) { |
| 1169 List<ast.VariableDeclaration> variables = <ast.VariableDeclaration>[]; | 1172 List<ast.VariableDeclaration> variables = <ast.VariableDeclaration>[]; |
| 1170 ast.Expression initialExpression; | 1173 ast.Expression initialExpression; |
| 1171 if (node.variables != null) { | 1174 if (node.variables != null) { |
| 1172 VariableDeclarationList list = node.variables; | 1175 VariableDeclarationList list = node.variables; |
| 1173 var type = scope.buildOptionalTypeAnnotation(list.type); | 1176 var type = scope.buildOptionalTypeAnnotation(list.type); |
| 1174 for (var variable in list.variables) { | 1177 for (var variable in list.variables) { |
| 1175 LocalElement local = variable.element as dynamic; // Cross cast. | 1178 LocalElement local = variable.element as dynamic; // Cross cast. |
| 1176 variables.add(scope.makeVariableDeclaration(local, | 1179 variables.add(scope.makeVariableDeclaration(local, |
| 1177 initializer: scope.buildOptionalExpression(variable.initializer), | 1180 initializer: scope.buildOptionalExpression(variable.initializer), |
| 1178 type: type)); | 1181 type: type, |
| 1182 equalsOffset: variable.equals?.offset)); | |
| 1179 } | 1183 } |
| 1180 } else if (node.initialization != null) { | 1184 } else if (node.initialization != null) { |
| 1181 initialExpression = scope.buildExpression(node.initialization); | 1185 initialExpression = scope.buildExpression(node.initialization); |
| 1182 } | 1186 } |
| 1183 var breakNode = new LabelStack.unlabeled(breakStack); | 1187 var breakNode = new LabelStack.unlabeled(breakStack); |
| 1184 var continueNode = new LabelStack.unlabeled(continueStack); | 1188 var continueNode = new LabelStack.unlabeled(continueStack); |
| 1185 addLoopLabels(node, continueNode); | 1189 addLoopLabels(node, continueNode); |
| 1186 var body = buildInScope(node.body, breakNode, continueNode); | 1190 var body = buildInScope(node.body, breakNode, continueNode); |
| 1187 var loop = new ast.ForStatement( | 1191 var loop = new ast.ForStatement( |
| 1188 variables, | 1192 variables, |
| (...skipping 168 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
| 1357 extends GeneralizingAstVisitor /* <ast.Expression | Accessor> */ { | 1361 extends GeneralizingAstVisitor /* <ast.Expression | Accessor> */ { |
| 1358 final ExpressionScope scope; | 1362 final ExpressionScope scope; |
| 1359 ast.VariableDeclaration cascadeReceiver; | 1363 ast.VariableDeclaration cascadeReceiver; |
| 1360 ExpressionBuilder(this.scope); | 1364 ExpressionBuilder(this.scope); |
| 1361 | 1365 |
| 1362 ast.Expression build(Expression node) { | 1366 ast.Expression build(Expression node) { |
| 1363 var result = node.accept(this); | 1367 var result = node.accept(this); |
| 1364 if (result is Accessor) { | 1368 if (result is Accessor) { |
| 1365 result = result.buildSimpleRead(); | 1369 result = result.buildSimpleRead(); |
| 1366 } | 1370 } |
| 1367 return result..fileOffset = _getOffset(node); | 1371 return result..fileOffset = _getOffset(node, result); |
| 1368 } | 1372 } |
| 1369 | 1373 |
| 1370 int _getOffset(AstNode node) { | 1374 int _getOffset(AstNode node, ast.Expression expression) { |
|
Kevin Millikin (Google)
2017/02/08 15:37:51
This is a warty API. It takes an analyzer AstNode
jensj
2017/02/13 14:04:15
Done.
| |
| 1371 if (node is MethodInvocation) { | 1375 if (node is MethodInvocation) { |
| 1376 if (expression.fileOffset >= 0) return expression.fileOffset; | |
| 1372 return node.methodName.offset; | 1377 return node.methodName.offset; |
| 1373 } else if (node is InstanceCreationExpression) { | 1378 } else if (node is InstanceCreationExpression) { |
| 1374 return node.constructorName.offset; | 1379 return node.constructorName.offset; |
| 1375 } else if (node is BinaryExpression) { | 1380 } else if (node is BinaryExpression) { |
| 1376 return node.operator.offset; | 1381 return node.operator.offset; |
| 1377 } else if (node is PrefixedIdentifier) { | 1382 } else if (node is PrefixedIdentifier) { |
| 1378 return node.identifier.offset; | 1383 return node.identifier.offset; |
| 1379 } else if (node is AssignmentExpression) { | 1384 } else if (node is AssignmentExpression) { |
| 1380 return _getOffset(node.leftHandSide); | 1385 return _getOffset(node.leftHandSide, expression); |
| 1381 } else if (node is PropertyAccess) { | 1386 } else if (node is PropertyAccess) { |
| 1382 return node.propertyName.offset; | 1387 return node.propertyName.offset; |
| 1383 } else if (node is IsExpression) { | 1388 } else if (node is IsExpression) { |
| 1384 return node.isOperator.offset; | 1389 return node.isOperator.offset; |
| 1390 } else if (node is AsExpression) { | |
| 1391 return node.asOperator.offset; | |
| 1385 } else if (node is StringLiteral) { | 1392 } else if (node is StringLiteral) { |
| 1386 // Use a catch-all for StringInterpolation and AdjacentStrings: | 1393 // Use a catch-all for StringInterpolation and AdjacentStrings: |
| 1387 // the debugger stops at the end. | 1394 // the debugger stops at the end. |
| 1388 return node.end; | 1395 return node.end; |
| 1396 } else if (node is IndexExpression) { | |
| 1397 return node.leftBracket.offset; | |
| 1389 } | 1398 } |
| 1390 return node.offset; | 1399 return node.offset; |
| 1391 } | 1400 } |
| 1392 | 1401 |
| 1393 Accessor buildLeftHandValue(Expression node) { | 1402 Accessor buildLeftHandValue(Expression node) { |
| 1394 var result = node.accept(this); | 1403 var result = node.accept(this); |
| 1395 if (result is Accessor) { | 1404 if (result is Accessor) { |
| 1396 return result; | 1405 return result; |
| 1397 } else { | 1406 } else { |
| 1398 return new ReadOnlyAccessor(result); | 1407 return new ReadOnlyAccessor(result); |
| (...skipping 461 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
| 1860 return new ast.ConstructorInvocation(constructor, arguments, | 1869 return new ast.ConstructorInvocation(constructor, arguments, |
| 1861 isConst: node.isConst); | 1870 isConst: node.isConst); |
| 1862 } else { | 1871 } else { |
| 1863 return noSuchMethodError(); | 1872 return noSuchMethodError(); |
| 1864 } | 1873 } |
| 1865 } | 1874 } |
| 1866 | 1875 |
| 1867 ast.Expression visitIsExpression(IsExpression node) { | 1876 ast.Expression visitIsExpression(IsExpression node) { |
| 1868 if (node.notOperator != null) { | 1877 if (node.notOperator != null) { |
| 1869 return new ast.Not(new ast.IsExpression( | 1878 return new ast.Not(new ast.IsExpression( |
| 1870 build(node.expression), scope.buildTypeAnnotation(node.type))); | 1879 build(node.expression), scope.buildTypeAnnotation(node.type)) |
| 1880 ..fileOffset = node.isOperator.offset); | |
|
Kevin Millikin (Google)
2017/02/08 15:37:51
It seems weird that the IsExpression that comes fr
jensj
2017/02/13 14:04:15
Done.
| |
| 1871 } else { | 1881 } else { |
| 1872 return new ast.IsExpression( | 1882 return new ast.IsExpression( |
| 1873 build(node.expression), scope.buildTypeAnnotation(node.type)); | 1883 build(node.expression), scope.buildTypeAnnotation(node.type)); |
| 1874 } | 1884 } |
| 1875 } | 1885 } |
| 1876 | 1886 |
| 1877 /// Emit a method invocation, either as a direct call `o.f(x)` or decomposed | 1887 /// Emit a method invocation, either as a direct call `o.f(x)` or decomposed |
| 1878 /// into a getter and function invocation `o.f.call(x)`. | 1888 /// into a getter and function invocation `o.f.call(x)`. |
| 1879 ast.Expression buildDecomposableMethodInvocation(ast.Expression receiver, | 1889 ast.Expression buildDecomposableMethodInvocation(ast.Expression receiver, |
| 1880 ast.Name name, ast.Arguments arguments, Element targetElement) { | 1890 ast.Name name, ast.Arguments arguments, Element targetElement) { |
| (...skipping 32 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
| 1913 scope.addTransformerFlag(TransformerFlag.superCalls); | 1923 scope.addTransformerFlag(TransformerFlag.superCalls); |
| 1914 return new ast.SuperMethodInvocation( | 1924 return new ast.SuperMethodInvocation( |
| 1915 scope.buildName(node.methodName), | 1925 scope.buildName(node.methodName), |
| 1916 buildArgumentsForInvocation(node), | 1926 buildArgumentsForInvocation(node), |
| 1917 scope.resolveConcreteMethod(element)); | 1927 scope.resolveConcreteMethod(element)); |
| 1918 } else if (isLocal(element)) { | 1928 } else if (isLocal(element)) { |
| 1919 return new ast.MethodInvocation( | 1929 return new ast.MethodInvocation( |
| 1920 new ast.VariableGet(scope.getVariableReference(element)), | 1930 new ast.VariableGet(scope.getVariableReference(element)), |
| 1921 callName, | 1931 callName, |
| 1922 buildArgumentsForInvocation(node), | 1932 buildArgumentsForInvocation(node), |
| 1923 scope.resolveInterfaceFunctionCall(element)); | 1933 scope.resolveInterfaceFunctionCall(element)) |
| 1934 ..fileOffset = node.methodName.end; | |
|
Kevin Millikin (Google)
2017/02/08 15:37:51
This definitely needs a comment. We are explicitl
jensj
2017/02/13 14:04:15
Done.
| |
| 1924 } else if (isStaticMethod(element)) { | 1935 } else if (isStaticMethod(element)) { |
| 1925 var method = scope.resolveConcreteMethod(element); | 1936 var method = scope.resolveConcreteMethod(element); |
| 1926 var arguments = buildArgumentsForInvocation(node); | 1937 var arguments = buildArgumentsForInvocation(node); |
| 1927 if (method == null || !scope.areArgumentsCompatible(element, arguments)) { | 1938 if (method == null || !scope.areArgumentsCompatible(element, arguments)) { |
| 1928 return scope.buildThrowNoSuchMethodError( | 1939 return scope.buildThrowNoSuchMethodError( |
| 1929 new ast.NullLiteral(), node.methodName.name, arguments, | 1940 new ast.NullLiteral(), node.methodName.name, arguments, |
| 1930 candidateTarget: element); | 1941 candidateTarget: element); |
| 1931 } | 1942 } |
| 1932 return new ast.StaticInvocation(method, arguments); | 1943 return new ast.StaticInvocation(method, arguments); |
| 1933 } else if (isStaticVariableOrGetter(element)) { | 1944 } else if (isStaticVariableOrGetter(element)) { |
| (...skipping 59 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
| 1993 } | 2004 } |
| 1994 | 2005 |
| 1995 ast.Expression visitPostfixExpression(PostfixExpression node) { | 2006 ast.Expression visitPostfixExpression(PostfixExpression node) { |
| 1996 String operator = node.operator.value(); | 2007 String operator = node.operator.value(); |
| 1997 switch (operator) { | 2008 switch (operator) { |
| 1998 case '++': | 2009 case '++': |
| 1999 case '--': | 2010 case '--': |
| 2000 var leftHand = buildLeftHandValue(node.operand); | 2011 var leftHand = buildLeftHandValue(node.operand); |
| 2001 var binaryOperator = new ast.Name(operator[0]); | 2012 var binaryOperator = new ast.Name(operator[0]); |
| 2002 return leftHand.buildPostfixIncrement(binaryOperator, | 2013 return leftHand.buildPostfixIncrement(binaryOperator, |
| 2003 offset: node.offset, | 2014 offset: node.operator.offset, |
| 2004 voidContext: isInVoidContext(node), | 2015 voidContext: isInVoidContext(node), |
| 2005 interfaceTarget: scope.resolveInterfaceMethod(node.staticElement)); | 2016 interfaceTarget: scope.resolveInterfaceMethod(node.staticElement)); |
| 2006 | 2017 |
| 2007 default: | 2018 default: |
| 2008 return scope.internalError('Invalid postfix operator $operator'); | 2019 return scope.internalError('Invalid postfix operator $operator'); |
| 2009 } | 2020 } |
| 2010 } | 2021 } |
| 2011 | 2022 |
| 2012 ast.Expression visitPrefixExpression(PrefixExpression node) { | 2023 ast.Expression visitPrefixExpression(PrefixExpression node) { |
| 2013 String operator = node.operator.value(); | 2024 String operator = node.operator.value(); |
| (...skipping 1025 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
| 3039 if (list[i - 1].compareTo(item) == 0) { | 3050 if (list[i - 1].compareTo(item) == 0) { |
| 3040 ++deleted; | 3051 ++deleted; |
| 3041 } else if (deleted > 0) { | 3052 } else if (deleted > 0) { |
| 3042 list[i - deleted] = item; | 3053 list[i - deleted] = item; |
| 3043 } | 3054 } |
| 3044 } | 3055 } |
| 3045 if (deleted > 0) { | 3056 if (deleted > 0) { |
| 3046 list.length -= deleted; | 3057 list.length -= deleted; |
| 3047 } | 3058 } |
| 3048 } | 3059 } |
| OLD | NEW |