| OLD | NEW |
| 1 // Copyright (c) 2017, the Dart project authors. Please see the AUTHORS file | 1 // Copyright (c) 2017, 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:front_end/src/fasta/type_inference/type_inference_listener.dart'
; | 5 import 'package:front_end/src/fasta/type_inference/type_inference_listener.dart'
; |
| 6 import 'package:kernel/ast.dart'; | 6 import 'package:kernel/ast.dart'; |
| 7 | 7 |
| 8 /// Type inference listener that records inferred types and file offsets for | 8 /// Type inference listener that records inferred types and file offsets for |
| 9 /// later use by [ValidatingResolutionApplier]. | 9 /// later use by [ValidatingResolutionApplier]. |
| 10 class InstrumentedResolutionStorer extends ResolutionStorer { | 10 class InstrumentedResolutionStorer extends ResolutionStorer { |
| 11 /// Indicates whether debug messages should be printed. | 11 /// Indicates whether debug messages should be printed. |
| 12 static const bool _debug = false; | 12 static const bool _debug = false; |
| 13 | 13 |
| 14 final List<int> _typeOffsets; | 14 final List<int> _typeOffsets; |
| 15 | 15 |
| 16 InstrumentedResolutionStorer(List<DartType> types, this._typeOffsets) | 16 InstrumentedResolutionStorer(List<DartType> types, this._typeOffsets) |
| 17 : super(types); | 17 : super(types); |
| 18 | 18 |
| 19 @override | 19 @override |
| 20 void _recordType(DartType type, int offset) { | 20 int _recordType(DartType type, int offset) { |
| 21 if (_debug) { | 21 if (_debug) { |
| 22 print('Recording type $type for offset $offset'); | 22 print('Recording type $type for offset $offset'); |
| 23 } | 23 } |
| 24 assert(_types.length == _typeOffsets.length); | 24 assert(_types.length == _typeOffsets.length); |
| 25 _typeOffsets.add(offset); | 25 _typeOffsets.add(offset); |
| 26 super._recordType(type, offset); | 26 return super._recordType(type, offset); |
| 27 } | 27 } |
| 28 } | 28 } |
| 29 | 29 |
| 30 /// Type inference listener that records inferred types for later use by | 30 /// Type inference listener that records inferred types for later use by |
| 31 /// [ResolutionApplier]. | 31 /// [ResolutionApplier]. |
| 32 class ResolutionStorer extends TypeInferenceListener { | 32 class ResolutionStorer extends TypeInferenceListener { |
| 33 final List<DartType> _types; | 33 final List<DartType> _types; |
| 34 | 34 |
| 35 /// Indices into [_types] which need to be filled in later. |
| 36 final _deferredTypeSlots = <int>[]; |
| 37 |
| 35 ResolutionStorer(this._types); | 38 ResolutionStorer(this._types); |
| 36 | 39 |
| 40 /// Verifies that all deferred work has been completed. |
| 41 void finished() { |
| 42 assert(_deferredTypeSlots.isEmpty); |
| 43 } |
| 44 |
| 37 @override | 45 @override |
| 38 bool genericExpressionEnter( | 46 bool genericExpressionEnter( |
| 39 String expressionType, Expression expression, DartType typeContext) { | 47 String expressionType, Expression expression, DartType typeContext) { |
| 40 super.genericExpressionEnter(expressionType, expression, typeContext); | 48 super.genericExpressionEnter(expressionType, expression, typeContext); |
| 41 return true; | 49 return true; |
| 42 } | 50 } |
| 43 | 51 |
| 44 @override | 52 @override |
| 45 void genericExpressionExit( | 53 void genericExpressionExit( |
| 46 String expressionType, Expression expression, DartType inferredType) { | 54 String expressionType, Expression expression, DartType inferredType) { |
| 47 _recordType(inferredType, expression.fileOffset); | 55 _recordType(inferredType, expression.fileOffset); |
| 48 super.genericExpressionExit(expressionType, expression, inferredType); | 56 super.genericExpressionExit(expressionType, expression, inferredType); |
| 49 } | 57 } |
| 50 | 58 |
| 51 @override | 59 @override |
| 60 void methodInvocationBeforeArgs(Expression expression, bool isImplicitCall) { |
| 61 if (!isImplicitCall) { |
| 62 // We are visiting a method invocation like: a.f(args). We have visited a |
| 63 // but we haven't visited the args yet. |
| 64 // |
| 65 // The analyzer AST will expect a type for f at this point. (It can't |
| 66 // wait until later, because for all it knows, a.f might be a property |
| 67 // access, in which case the appropriate time for the type is now). But |
| 68 // the type isn't known yet (because it may depend on type inference based |
| 69 // on arguments). |
| 70 // |
| 71 // So we add a `null` to our list of types; we'll update it with the |
| 72 // actual type later. |
| 73 _deferredTypeSlots.add(_recordType(null, expression.fileOffset)); |
| 74 } |
| 75 super.methodInvocationBeforeArgs(expression, isImplicitCall); |
| 76 } |
| 77 |
| 78 @override |
| 79 void methodInvocationExit(Expression expression, Arguments arguments, |
| 80 bool isImplicitCall, DartType inferredType) { |
| 81 if (!isImplicitCall) { |
| 82 // TODO(paulberry): get the actual callee function type from the inference |
| 83 // engine |
| 84 var calleeType = const DynamicType(); |
| 85 _types[_deferredTypeSlots.removeLast()] = calleeType; |
| 86 } |
| 87 _recordType(inferredType, arguments.fileOffset); |
| 88 super.genericExpressionExit("methodInvocation", expression, inferredType); |
| 89 } |
| 90 |
| 91 @override |
| 92 bool staticInvocationEnter( |
| 93 StaticInvocation expression, DartType typeContext) { |
| 94 // We are visiting a static invocation like: f(args), and we haven't visited |
| 95 // args yet. |
| 96 // |
| 97 // The analyzer AST will expect a type for f at this point. (It can't wait |
| 98 // until later, because for all it knows, f is a method on `this`, and |
| 99 // methods need a type for f at this point--see comments in |
| 100 // [methodInvocationBeforeArgs]). But the type isn't known yet (because it |
| 101 // may depend on type inference based on arguments). |
| 102 // |
| 103 // So we add a `null` to our list of types; we'll update it with the actual |
| 104 // type later. |
| 105 _deferredTypeSlots.add(_recordType(null, expression.fileOffset)); |
| 106 return super.staticInvocationEnter(expression, typeContext); |
| 107 } |
| 108 |
| 109 @override |
| 110 void staticInvocationExit( |
| 111 StaticInvocation expression, DartType inferredType) { |
| 112 // TODO(paulberry): get the actual callee function type from the inference |
| 113 // engine |
| 114 var calleeType = const DynamicType(); |
| 115 _types[_deferredTypeSlots.removeLast()] = calleeType; |
| 116 _recordType(inferredType, expression.arguments.fileOffset); |
| 117 super.genericExpressionExit("staticInvocation", expression, inferredType); |
| 118 } |
| 119 |
| 120 @override |
| 52 void variableDeclarationEnter(VariableDeclaration statement) { | 121 void variableDeclarationEnter(VariableDeclaration statement) { |
| 53 _recordType(statement.type, statement.fileOffset); | 122 _recordType(statement.type, statement.fileOffset); |
| 54 super.variableDeclarationEnter(statement); | 123 super.variableDeclarationEnter(statement); |
| 55 } | 124 } |
| 56 | 125 |
| 57 void _recordType(DartType type, int offset) { | 126 int _recordType(DartType type, int offset) { |
| 127 int slot = _types.length; |
| 58 _types.add(type); | 128 _types.add(type); |
| 129 return slot; |
| 59 } | 130 } |
| 60 } | 131 } |
| OLD | NEW |