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 | 4 |
5 import 'package:kernel/ast.dart' as ir; | 5 import 'package:kernel/ast.dart' as ir; |
6 | 6 |
7 import '../common.dart'; | 7 import '../common.dart'; |
8 import '../common/names.dart'; | 8 import '../common/names.dart'; |
9 import '../compiler.dart'; | 9 import '../compiler.dart'; |
10 import '../constants/expressions.dart'; | 10 import '../constants/expressions.dart'; |
(...skipping 54 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
65 | 65 |
66 /// Add a checked-mode type use of [type] if it is not `dynamic`. | 66 /// Add a checked-mode type use of [type] if it is not `dynamic`. |
67 DartType checkType(ir.DartType irType) { | 67 DartType checkType(ir.DartType irType) { |
68 DartType type = astAdapter.getDartType(irType); | 68 DartType type = astAdapter.getDartType(irType); |
69 if (!type.isDynamic) { | 69 if (!type.isDynamic) { |
70 impactBuilder.registerTypeUse(new TypeUse.checkedModeCheck(type)); | 70 impactBuilder.registerTypeUse(new TypeUse.checkedModeCheck(type)); |
71 } | 71 } |
72 return type; | 72 return type; |
73 } | 73 } |
74 | 74 |
75 /// Add a checked-mode type use of return type and parameters of [node]. | |
76 void checkFunctionTypes(ir.FunctionNode node) { | |
77 checkType(node.returnType); | |
78 node.positionalParameters.forEach((v) => checkType(v.type)); | |
79 node.namedParameters.forEach((v) => checkType(v.type)); | |
80 } | |
81 | |
75 ResolutionImpact buildField(ir.Field field) { | 82 ResolutionImpact buildField(ir.Field field) { |
76 checkType(field.type); | 83 checkType(field.type); |
77 if (field.initializer != null) { | 84 if (field.initializer != null) { |
78 field.initializer.accept(this); | 85 field.initializer.accept(this); |
79 } else { | 86 } else { |
80 impactBuilder.registerFeature(Feature.FIELD_WITHOUT_INITIALIZER); | 87 impactBuilder.registerFeature(Feature.FIELD_WITHOUT_INITIALIZER); |
81 } | 88 } |
82 return impactBuilder; | 89 return impactBuilder; |
83 } | 90 } |
84 | 91 |
85 ResolutionImpact buildProcedure(ir.Procedure procedure) { | 92 ResolutionImpact buildProcedure(ir.Procedure procedure) { |
86 if (procedure.kind == ir.ProcedureKind.Method || | 93 if (procedure.kind == ir.ProcedureKind.Method || |
87 procedure.kind == ir.ProcedureKind.Operator) { | 94 procedure.kind == ir.ProcedureKind.Operator) { |
88 checkType(procedure.function.returnType); | 95 checkFunctionTypes(procedure.function); |
89 procedure.function.positionalParameters.forEach((v) => checkType(v.type)); | |
90 procedure.function.namedParameters.forEach((v) => checkType(v.type)); | |
91 procedure.function.body.accept(this); | 96 procedure.function.body.accept(this); |
92 } else { | 97 } else { |
93 compiler.reporter.internalError( | 98 compiler.reporter.internalError( |
94 resolvedAst.element, | 99 resolvedAst.element, |
95 "Unable to compute resolution impact for this kind of Kernel " | 100 "Unable to compute resolution impact for this kind of Kernel " |
96 "procedure: ${procedure.kind}"); | 101 "procedure: ${procedure.kind}"); |
97 } | 102 } |
98 return impactBuilder; | 103 return impactBuilder; |
99 } | 104 } |
100 | 105 |
106 void visitNode(ir.Node node) => node?.accept(this); | |
Harry Terkelsen
2016/09/22 19:20:15
if you have this, you should use it consistently t
Johnni Winther
2016/09/23 09:01:50
I thought I had ;) - Done.
| |
107 | |
101 void visitNodes(Iterable<ir.Node> nodes) { | 108 void visitNodes(Iterable<ir.Node> nodes) { |
102 nodes.forEach((ir.Node node) => node.accept(this)); | 109 nodes.forEach((ir.Node node) => node.accept(this)); |
103 } | 110 } |
104 | 111 |
105 @override | 112 @override |
106 void visitBlock(ir.Block block) => visitNodes(block.statements); | 113 void visitBlock(ir.Block block) => visitNodes(block.statements); |
107 | 114 |
108 @override | 115 @override |
109 void visitExpressionStatement(ir.ExpressionStatement exprStatement) { | 116 void visitExpressionStatement(ir.ExpressionStatement exprStatement) { |
110 exprStatement.expression.accept(this); | 117 exprStatement.expression.accept(this); |
(...skipping 120 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
231 impactBuilder.registerFeature(Feature.TYPE_VARIABLE_BOUNDS_CHECK); | 238 impactBuilder.registerFeature(Feature.TYPE_VARIABLE_BOUNDS_CHECK); |
232 } | 239 } |
233 } else { | 240 } else { |
234 impactBuilder.registerStaticUse(new StaticUse.staticInvoke( | 241 impactBuilder.registerStaticUse(new StaticUse.staticInvoke( |
235 target, astAdapter.getCallStructure(invocation.arguments))); | 242 target, astAdapter.getCallStructure(invocation.arguments))); |
236 } | 243 } |
237 } | 244 } |
238 | 245 |
239 @override | 246 @override |
240 void visitStaticGet(ir.StaticGet node) { | 247 void visitStaticGet(ir.StaticGet node) { |
241 Element target = astAdapter.getElement(node.target).declaration; | 248 ir.Member target = node.target; |
242 impactBuilder.registerStaticUse(new StaticUse.staticGet(target)); | 249 Element element = astAdapter.getElement(target).declaration; |
250 if (target is ir.Procedure && target.kind == ir.ProcedureKind.Method) { | |
251 impactBuilder.registerStaticUse(new StaticUse.staticTearOff(element)); | |
252 } else { | |
253 impactBuilder.registerStaticUse(new StaticUse.staticGet(element)); | |
254 } | |
243 } | 255 } |
244 | 256 |
245 @override | 257 @override |
246 void visitMethodInvocation(ir.MethodInvocation invocation) { | 258 void visitMethodInvocation(ir.MethodInvocation invocation) { |
247 var receiver = invocation.receiver; | 259 var receiver = invocation.receiver; |
248 if (receiver is ir.VariableGet && | 260 if (receiver is ir.VariableGet && |
249 receiver.variable.isFinal && | 261 receiver.variable.isFinal && |
250 receiver.variable.parent is ir.FunctionDeclaration) { | 262 receiver.variable.parent is ir.FunctionDeclaration) { |
251 // Invocation of a local function. No need for dynamic use. | 263 // Invocation of a local function. No need for dynamic use. |
252 } else { | 264 } else { |
(...skipping 16 matching lines...) Expand all Loading... | |
269 node.receiver.accept(this); | 281 node.receiver.accept(this); |
270 node.value.accept(this); | 282 node.value.accept(this); |
271 impactBuilder.registerDynamicUse(new DynamicUse( | 283 impactBuilder.registerDynamicUse(new DynamicUse( |
272 new Selector.setter(astAdapter.getName(node.name)), null)); | 284 new Selector.setter(astAdapter.getName(node.name)), null)); |
273 } | 285 } |
274 | 286 |
275 @override | 287 @override |
276 void visitAssertStatement(ir.AssertStatement node) { | 288 void visitAssertStatement(ir.AssertStatement node) { |
277 impactBuilder.registerFeature( | 289 impactBuilder.registerFeature( |
278 node.message != null ? Feature.ASSERT_WITH_MESSAGE : Feature.ASSERT); | 290 node.message != null ? Feature.ASSERT_WITH_MESSAGE : Feature.ASSERT); |
279 node.visitChildren(this); | 291 visitNode(node.condition); |
292 visitNode(node.message); | |
280 } | 293 } |
281 | 294 |
282 @override | 295 @override |
283 void visitStringConcatenation(ir.StringConcatenation node) { | 296 void visitStringConcatenation(ir.StringConcatenation node) { |
284 impactBuilder.registerFeature(Feature.STRING_INTERPOLATION); | 297 impactBuilder.registerFeature(Feature.STRING_INTERPOLATION); |
285 impactBuilder.registerFeature(Feature.STRING_JUXTAPOSITION); | 298 impactBuilder.registerFeature(Feature.STRING_JUXTAPOSITION); |
286 node.visitChildren(this); | 299 visitNodes(node.expressions); |
287 } | 300 } |
288 | 301 |
289 @override | 302 @override |
290 void visitFunctionDeclaration(ir.FunctionDeclaration node) { | 303 void visitFunctionDeclaration(ir.FunctionDeclaration node) { |
291 impactBuilder | 304 impactBuilder |
292 .registerStaticUse(new StaticUse.closure(astAdapter.getElement(node))); | 305 .registerStaticUse(new StaticUse.closure(astAdapter.getElement(node))); |
293 node.visitChildren(this); | 306 checkFunctionTypes(node.function); |
307 visitNode(node.function.body); | |
294 } | 308 } |
295 | 309 |
296 @override | 310 @override |
311 void visitFunctionExpression(ir.FunctionExpression node) { | |
312 impactBuilder | |
313 .registerStaticUse(new StaticUse.closure(astAdapter.getElement(node))); | |
314 checkFunctionTypes(node.function); | |
315 visitNode(node.function.body); | |
316 } | |
317 | |
318 @override | |
319 void visitVariableDeclaration(ir.VariableDeclaration node) { | |
320 checkType(node.type); | |
321 if (node.initializer != null) { | |
322 visitNode(node.initializer); | |
323 } else { | |
324 impactBuilder.registerFeature(Feature.LOCAL_WITHOUT_INITIALIZER); | |
325 } | |
326 } | |
327 | |
328 // TODO(johnniwinther): Make this throw and visit child nodes explicitly | |
329 // instead to ensure that we don't visit unwanted parts of the ir. | |
330 @override | |
297 void defaultNode(ir.Node node) => node.visitChildren(this); | 331 void defaultNode(ir.Node node) => node.visitChildren(this); |
298 } | 332 } |
OLD | NEW |