OLD | NEW |
1 // Copyright (c) 2012, the Dart project authors. Please see the AUTHORS file | 1 // Copyright (c) 2012, 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 part of dart2js; | 5 part of dart2js; |
6 | 6 |
7 class TypeCheckerTask extends CompilerTask { | 7 class TypeCheckerTask extends CompilerTask { |
8 TypeCheckerTask(Compiler compiler) : super(compiler); | 8 TypeCheckerTask(Compiler compiler) : super(compiler); |
9 String get name => "Type checker"; | 9 String get name => "Type checker"; |
10 | 10 |
(...skipping 167 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
178 messages.add(new TypePromotionMessage(api.Diagnostic.HINT, | 178 messages.add(new TypePromotionMessage(api.Diagnostic.HINT, |
179 spannable, kind, arguments)); | 179 spannable, kind, arguments)); |
180 } | 180 } |
181 | 181 |
182 void addInfo(Spannable spannable, MessageKind kind, [Map arguments]) { | 182 void addInfo(Spannable spannable, MessageKind kind, [Map arguments]) { |
183 messages.add(new TypePromotionMessage(api.Diagnostic.INFO, | 183 messages.add(new TypePromotionMessage(api.Diagnostic.INFO, |
184 spannable, kind, arguments)); | 184 spannable, kind, arguments)); |
185 } | 185 } |
186 | 186 |
187 String toString() { | 187 String toString() { |
188 return 'Promote ${variable} to ${type}'; | 188 return 'Promote ${variable} to ${type}${isValid ? '' : ' (invalid)'}'; |
189 } | 189 } |
190 } | 190 } |
191 | 191 |
192 /// A hint or info message attached to a type promotion. | 192 /// A hint or info message attached to a type promotion. |
193 class TypePromotionMessage { | 193 class TypePromotionMessage { |
194 api.Diagnostic diagnostic; | 194 api.Diagnostic diagnostic; |
195 Spannable spannable; | 195 Spannable spannable; |
196 MessageKind messageKind; | 196 MessageKind messageKind; |
197 Map messageArguments; | 197 Map messageArguments; |
198 | 198 |
(...skipping 204 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
403 } | 403 } |
404 for (Node mutation in mutations) { | 404 for (Node mutation in mutations) { |
405 typePromotion.addInfo(mutation, | 405 typePromotion.addInfo(mutation, |
406 MessageKind.POTENTIAL_MUTATION_HERE, | 406 MessageKind.POTENTIAL_MUTATION_HERE, |
407 {'variableName': variableName}); | 407 {'variableName': variableName}); |
408 } | 408 } |
409 } | 409 } |
410 } | 410 } |
411 } | 411 } |
412 | 412 |
413 void reshowTypePromotions(Node node, Node receiver, Node argument) { | 413 /// Show type promotions from [left] and [right] in [node] given that the |
414 for (TypePromotion typePromotion in getShownTypePromotionsFor(receiver)) { | 414 /// promoted variables are not potentially mutated in [right]. |
| 415 void reshowTypePromotions(Node node, Node left, Node right) { |
| 416 for (TypePromotion typePromotion in getShownTypePromotionsFor(left)) { |
415 typePromotion = typePromotion.copy(); | 417 typePromotion = typePromotion.copy(); |
416 checkTypePromotion(argument, typePromotion); | 418 checkTypePromotion(right, typePromotion); |
417 showTypePromotion(node, typePromotion); | 419 showTypePromotion(node, typePromotion); |
418 } | 420 } |
419 | 421 |
420 for (TypePromotion typePromotion in getShownTypePromotionsFor(argument)) { | 422 for (TypePromotion typePromotion in getShownTypePromotionsFor(right)) { |
421 typePromotion = typePromotion.copy(); | 423 typePromotion = typePromotion.copy(); |
422 checkTypePromotion(argument, typePromotion); | 424 checkTypePromotion(right, typePromotion); |
423 showTypePromotion(node, typePromotion); | 425 showTypePromotion(node, typePromotion); |
424 } | 426 } |
425 } | 427 } |
426 | 428 |
427 /// Analyze [node] in the context of the known types shown in [context]. | 429 /// Analyze [node] in the context of the known types shown in [context]. |
428 DartType analyzeInPromotedContext(Node context, Node node) { | 430 DartType analyzeInPromotedContext(Node context, Node node) { |
429 Link<TypePromotion> knownForNode = const Link<TypePromotion>(); | 431 Link<TypePromotion> knownForNode = const Link<TypePromotion>(); |
430 for (TypePromotion typePromotion in getShownTypePromotionsFor(context)) { | 432 for (TypePromotion typePromotion in getShownTypePromotionsFor(context)) { |
431 typePromotion = typePromotion.copy(); | 433 typePromotion = typePromotion.copy(); |
432 checkTypePromotion(node, typePromotion, checkAccesses: true); | 434 checkTypePromotion(node, typePromotion, checkAccesses: true); |
(...skipping 491 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
924 } | 926 } |
925 } | 927 } |
926 | 928 |
927 Identifier selector = node.selector.asIdentifier(); | 929 Identifier selector = node.selector.asIdentifier(); |
928 String name = selector.source; | 930 String name = selector.source; |
929 | 931 |
930 if (node.isOperator && identical(name, 'is')) { | 932 if (node.isOperator && identical(name, 'is')) { |
931 analyze(node.receiver); | 933 analyze(node.receiver); |
932 if (!node.isIsNotCheck) { | 934 if (!node.isIsNotCheck) { |
933 Element variable = elements[node.receiver]; | 935 Element variable = elements[node.receiver]; |
| 936 if (variable == null) { |
| 937 // Look for the variable element within parenthesized expressions. |
| 938 ParenthesizedExpression parentheses = |
| 939 node.receiver.asParenthesizedExpression(); |
| 940 while (parentheses != null) { |
| 941 variable = elements[parentheses.expression]; |
| 942 if (variable != null) break; |
| 943 parentheses = parentheses.expression.asParenthesizedExpression(); |
| 944 } |
| 945 } |
| 946 |
934 if (variable != null && | 947 if (variable != null && |
935 (variable.isVariable() || variable.isParameter())) { | 948 (variable.isVariable() || variable.isParameter())) { |
936 DartType knownType = getKnownType(variable); | 949 DartType knownType = getKnownType(variable); |
937 if (!knownType.isDynamic) { | 950 if (!knownType.isDynamic) { |
938 DartType shownType = elements.getType(node.arguments.head); | 951 DartType shownType = elements.getType(node.arguments.head); |
939 TypePromotion typePromotion = | 952 TypePromotion typePromotion = |
940 new TypePromotion(node, variable, shownType); | 953 new TypePromotion(node, variable, shownType); |
941 if (!types.isMoreSpecific(shownType, knownType)) { | 954 if (!types.isMoreSpecific(shownType, knownType)) { |
942 String variableName = variable.name; | 955 String variableName = variable.name; |
943 // TODO(johnniwinther): Provide a how-to-fix in the case one tries | 956 // TODO(johnniwinther): Provide a how-to-fix in the case one tries |
(...skipping 459 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
1403 // TODO(karlklose): this should be StatementType.RETURNING unless there | 1416 // TODO(karlklose): this should be StatementType.RETURNING unless there |
1404 // is a break in the loop body that has the loop or a label outside the | 1417 // is a break in the loop body that has the loop or a label outside the |
1405 // loop as a target. | 1418 // loop as a target. |
1406 return bodyType; | 1419 return bodyType; |
1407 } else { | 1420 } else { |
1408 return bodyType.join(StatementType.NOT_RETURNING); | 1421 return bodyType.join(StatementType.NOT_RETURNING); |
1409 } | 1422 } |
1410 } | 1423 } |
1411 | 1424 |
1412 DartType visitParenthesizedExpression(ParenthesizedExpression node) { | 1425 DartType visitParenthesizedExpression(ParenthesizedExpression node) { |
1413 return analyze(node.expression); | 1426 Expression expression = node.expression; |
| 1427 DartType type = analyze(expression); |
| 1428 for (TypePromotion typePromotion in getShownTypePromotionsFor(expression)) { |
| 1429 showTypePromotion(node, typePromotion); |
| 1430 } |
| 1431 return type; |
1414 } | 1432 } |
1415 | 1433 |
1416 DartType visitConditional(Conditional node) { | 1434 DartType visitConditional(Conditional node) { |
1417 Expression condition = node.condition; | 1435 Expression condition = node.condition; |
1418 Expression thenExpression = node.thenExpression; | 1436 Expression thenExpression = node.thenExpression; |
1419 | 1437 |
1420 checkCondition(condition); | 1438 checkCondition(condition); |
1421 | 1439 |
1422 DartType thenType = analyzeInPromotedContext(condition, thenExpression); | 1440 DartType thenType = analyzeInPromotedContext(condition, thenExpression); |
1423 | 1441 |
(...skipping 154 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
1578 visitTypedef(Typedef node) { | 1596 visitTypedef(Typedef node) { |
1579 // Do not typecheck [Typedef] nodes. | 1597 // Do not typecheck [Typedef] nodes. |
1580 } | 1598 } |
1581 | 1599 |
1582 visitNode(Node node) { | 1600 visitNode(Node node) { |
1583 compiler.internalError( | 1601 compiler.internalError( |
1584 'Unexpected node ${node.getObjectDescription()} in the type checker.', | 1602 'Unexpected node ${node.getObjectDescription()} in the type checker.', |
1585 node: node); | 1603 node: node); |
1586 } | 1604 } |
1587 } | 1605 } |
OLD | NEW |