OLD | NEW |
---|---|
1 // Copyright (c) 2015, the Dart project authors. Please see the AUTHORS file | 1 // Copyright (c) 2015, 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 /// Defines static information collected by the type checker and used later by | 5 /// Defines static information collected by the type checker and used later by |
6 /// emitters to generate code. | 6 /// emitters to generate code. |
7 library dev_compiler.src.info; | 7 library dev_compiler.src.info; |
8 | 8 |
9 import 'dart:mirrors'; | 9 import 'dart:mirrors'; |
10 | 10 |
11 import 'package:analyzer/src/generated/ast.dart'; | 11 import 'package:analyzer/src/generated/ast.dart'; |
12 import 'package:analyzer/src/generated/element.dart'; | 12 import 'package:analyzer/src/generated/element.dart'; |
13 import 'package:analyzer/src/generated/error.dart' as analyzer; | 13 import 'package:analyzer/src/generated/error.dart' as analyzer; |
14 import 'package:analyzer/src/generated/scanner.dart' | |
15 show Token, TokenType, SyntheticStringToken; | |
16 import 'package:logging/logging.dart' show Level; | 14 import 'package:logging/logging.dart' show Level; |
17 | 15 |
18 import 'package:dev_compiler/src/checker/rules.dart'; | 16 import 'package:dev_compiler/src/checker/rules.dart'; |
19 import 'package:dev_compiler/src/utils.dart' as utils; | 17 import 'package:dev_compiler/src/utils.dart' as utils; |
20 | 18 |
21 import 'report.dart' show Message; | 19 import 'report.dart' show Message; |
22 | 20 |
23 /// Represents a summary of the results collected by running the program | 21 /// Represents a summary of the results collected by running the program |
24 /// checker. | 22 /// checker. |
25 class CheckerResults { | 23 class CheckerResults { |
(...skipping 76 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
102 @override | 100 @override |
103 int get begin => node is AnnotatedNode | 101 int get begin => node is AnnotatedNode |
104 ? (node as AnnotatedNode).firstTokenAfterCommentAndMetadata.offset | 102 ? (node as AnnotatedNode).firstTokenAfterCommentAndMetadata.offset |
105 : node.offset; | 103 : node.offset; |
106 | 104 |
107 @override | 105 @override |
108 int get end => node.end; | 106 int get end => node.end; |
109 } | 107 } |
110 | 108 |
111 /// Implicitly injected expression conversion. | 109 /// Implicitly injected expression conversion. |
112 // TODO(jmesserly): rename to have Expression suffix? | 110 // TODO(jmesserly): better name for this? Coercion is taken (above). |
vsm
2015/06/08 23:31:51
Perhaps CoercionInfo? Particularly now that this
Jennifer Messerly
2015/06/08 23:51:37
Nice, +1. Done.
| |
113 abstract class Conversion extends Expression with StaticInfo { | 111 abstract class Conversion extends StaticInfo { |
114 final TypeRules rules; | 112 final TypeRules rules; |
115 | 113 |
116 // TODO(jmesserly): should probably rename this "operand" for consistency with | 114 final Expression node; |
117 // analyzer's unary expressions (e.g. PrefixExpression). | |
118 final Expression expression; | |
119 | 115 |
120 AstNode get node => expression; | 116 DartType get convertedType; |
121 DartType _convertedType; | |
122 | 117 |
123 Conversion(this.rules, this.expression) { | 118 Conversion(this.rules, this.node); |
124 this._convertedType = _getConvertedType(); | |
125 } | |
126 | 119 |
127 DartType get baseType => rules.getStaticType(expression); | 120 DartType get baseType => rules.getStaticType(node); |
128 DartType get convertedType => _convertedType; | 121 DartType get staticType => convertedType; |
129 DartType get staticType => _convertedType; | |
130 | |
131 DartType _getConvertedType(); | |
132 | 122 |
133 // safe iff this cannot throw | 123 // safe iff this cannot throw |
134 bool get safe => false; | 124 bool get safe => false; |
135 | 125 |
136 Level get level => safe ? Level.CONFIG : Level.INFO; | 126 Level get level => safe ? Level.CONFIG : Level.INFO; |
137 | 127 |
138 String get description => '${this.runtimeType}: $baseType to $convertedType'; | 128 String get description => '${this.runtimeType}: $baseType to $convertedType'; |
139 | 129 |
140 Token get beginToken => expression.beginToken; | 130 static const String _propertyName = 'dev_compiler.Conversion'; |
141 Token get endToken => expression.endToken; | |
142 | 131 |
143 @override | 132 /// Gets the static info associated with this node. |
144 void visitChildren(AstVisitor visitor) { | 133 static Conversion get(AstNode node) => node.getProperty(_propertyName); |
145 expression.accept(visitor); | 134 |
135 /// Sets the static info associated with this node. | |
136 static Conversion set(AstNode node, Conversion info) { | |
137 node.setProperty(_propertyName, info); | |
138 return info; | |
146 } | 139 } |
147 | |
148 // Use same precedence as MethodInvocation. | |
149 int get precedence => 15; | |
150 | |
151 @override | |
152 Iterable get childEntities => new ChildEntities()..add(expression); | |
153 } | 140 } |
154 | 141 |
155 // Base class for all casts from base type to sub type. | 142 // Base class for all casts from base type to sub type. |
156 abstract class DownCast extends Conversion { | 143 abstract class DownCast extends Conversion { |
157 Cast _cast; | 144 Cast _cast; |
158 | 145 |
159 DownCast._internal(TypeRules rules, Expression expression, this._cast) | 146 DownCast._internal(TypeRules rules, Expression expression, this._cast) |
160 : super(rules, expression) { | 147 : super(rules, expression) { |
161 assert(_cast.toType != baseType && | 148 assert(_cast.toType != baseType && |
162 _cast.fromType == baseType && | 149 _cast.fromType == baseType && |
163 (baseType.isDynamic || | 150 (baseType.isDynamic || |
164 // Call methods make the following non-redundant | 151 // Call methods make the following non-redundant |
165 _cast.toType.isSubtypeOf(baseType) || | 152 _cast.toType.isSubtypeOf(baseType) || |
166 baseType.isAssignableTo(_cast.toType))); | 153 baseType.isAssignableTo(_cast.toType))); |
167 } | 154 } |
168 | 155 |
169 Cast get cast => _cast; | 156 Cast get cast => _cast; |
170 | 157 |
171 DartType _getConvertedType() => _cast.toType; | 158 DartType get convertedType => _cast.toType; |
172 | 159 |
173 String get message => '$expression ($baseType) will need runtime check ' | 160 String get message => '$node ($baseType) will need runtime check ' |
174 'to cast to type $convertedType'; | 161 'to cast to type $convertedType'; |
175 | 162 |
176 // Factory to create correct DownCast variant. | 163 // Factory to create correct DownCast variant. |
177 static StaticInfo create(TypeRules rules, Expression expression, Cast cast, | 164 static StaticInfo create(TypeRules rules, Expression expression, Cast cast, |
178 {String reason}) { | 165 {String reason}) { |
179 final fromT = cast.fromType; | 166 final fromT = cast.fromType; |
180 final toT = cast.toType; | 167 final toT = cast.toType; |
181 | 168 |
182 // toT <:_R fromT => to <: fromT | 169 // toT <:_R fromT => to <: fromT |
183 // NB: classes with call methods are subtypes of function | 170 // NB: classes with call methods are subtypes of function |
(...skipping 44 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
228 | 215 |
229 // Assignment cast | 216 // Assignment cast |
230 var parent = expression.parent; | 217 var parent = expression.parent; |
231 if (parent is VariableDeclaration && (parent.initializer == expression)) { | 218 if (parent is VariableDeclaration && (parent.initializer == expression)) { |
232 return new AssignmentCast(rules, expression, cast); | 219 return new AssignmentCast(rules, expression, cast); |
233 } | 220 } |
234 | 221 |
235 // Other casts | 222 // Other casts |
236 return new DownCastImplicit(rules, expression, cast); | 223 return new DownCastImplicit(rules, expression, cast); |
237 } | 224 } |
238 | |
239 accept(AstVisitor visitor) { | |
240 if (visitor is ConversionVisitor) { | |
241 return visitor.visitDownCast(this); | |
242 } else { | |
243 return expression.accept(visitor); | |
244 } | |
245 } | |
246 } | 225 } |
247 | 226 |
248 // | 227 // |
249 // Standard down casts. These casts are implicitly injected by the compiler. | 228 // Standard down casts. These casts are implicitly injected by the compiler. |
250 // | 229 // |
251 | 230 |
252 // A down cast from dynamic to T. | 231 // A down cast from dynamic to T. |
253 class DynamicCast extends DownCast { | 232 class DynamicCast extends DownCast { |
254 DynamicCast(TypeRules rules, Expression expression, Cast cast) | 233 DynamicCast(TypeRules rules, Expression expression, Cast cast) |
255 : super._internal(rules, expression, cast); | 234 : super._internal(rules, expression, cast); |
(...skipping 47 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
303 class DownCastImplicit extends DownCast { | 282 class DownCastImplicit extends DownCast { |
304 DownCastImplicit(TypeRules rules, Expression expression, Cast cast) | 283 DownCastImplicit(TypeRules rules, Expression expression, Cast cast) |
305 : super._internal(rules, expression, cast); | 284 : super._internal(rules, expression, cast); |
306 | 285 |
307 final Level level = Level.WARNING; | 286 final Level level = Level.WARNING; |
308 } | 287 } |
309 | 288 |
310 // An inferred type for the wrapped expression, which may need to be | 289 // An inferred type for the wrapped expression, which may need to be |
311 // reified into the term | 290 // reified into the term |
312 abstract class InferredTypeBase extends Conversion { | 291 abstract class InferredTypeBase extends Conversion { |
313 DartType _type; | 292 final DartType _type; |
314 | 293 |
315 InferredTypeBase._internal(TypeRules rules, Expression expression, this._type) | 294 InferredTypeBase._internal(TypeRules rules, Expression expression, this._type) |
316 : super(rules, expression); | 295 : super(rules, expression); |
317 | 296 |
318 DartType get type => _type; | 297 DartType get type => _type; |
319 | 298 DartType get convertedType => type; |
320 DartType _getConvertedType() => type; | 299 String get message => '$node has inferred type $type'; |
321 | |
322 String get message => '$expression has inferred type $type'; | |
323 | |
324 Level get level => Level.INFO; | 300 Level get level => Level.INFO; |
325 | |
326 accept(AstVisitor visitor) { | |
327 if (visitor is ConversionVisitor) { | |
328 return visitor.visitInferredTypeBase(this); | |
329 } else { | |
330 return expression.accept(visitor); | |
331 } | |
332 } | |
333 } | 301 } |
334 | 302 |
335 // Standard / unspecialized inferred type | 303 // Standard / unspecialized inferred type |
336 class InferredType extends InferredTypeBase { | 304 class InferredType extends InferredTypeBase { |
337 InferredType(TypeRules rules, Expression expression, DartType type) | 305 InferredType(TypeRules rules, Expression expression, DartType type) |
338 : super._internal(rules, expression, type); | 306 : super._internal(rules, expression, type); |
339 | 307 |
340 // Factory to create correct InferredType variant. | 308 // Factory to create correct InferredType variant. |
341 static InferredTypeBase create( | 309 static InferredTypeBase create( |
342 TypeRules rules, Expression expression, DartType type) { | 310 TypeRules rules, Expression expression, DartType type) { |
(...skipping 27 matching lines...) Expand all Loading... | |
370 // An inferred type for a closure expression | 338 // An inferred type for a closure expression |
371 class InferredTypeClosure extends InferredTypeBase { | 339 class InferredTypeClosure extends InferredTypeBase { |
372 InferredTypeClosure(TypeRules rules, Expression expression, DartType type) | 340 InferredTypeClosure(TypeRules rules, Expression expression, DartType type) |
373 : super._internal(rules, expression, type); | 341 : super._internal(rules, expression, type); |
374 } | 342 } |
375 | 343 |
376 class DynamicInvoke extends Conversion { | 344 class DynamicInvoke extends Conversion { |
377 DynamicInvoke(TypeRules rules, Expression expression) | 345 DynamicInvoke(TypeRules rules, Expression expression) |
378 : super(rules, expression); | 346 : super(rules, expression); |
379 | 347 |
380 DartType _getConvertedType() => rules.provider.dynamicType; | 348 DartType get convertedType => rules.provider.dynamicType; |
381 | 349 String get message => '$node requires dynamic invoke'; |
382 String get message => '$expression requires dynamic invoke'; | |
383 Level get level => Level.INFO; | 350 Level get level => Level.INFO; |
384 | |
385 accept(AstVisitor visitor) { | |
386 if (visitor is ConversionVisitor) { | |
387 return visitor.visitDynamicInvoke(this); | |
388 } else { | |
389 return expression.accept(visitor); | |
390 } | |
391 } | |
392 } | 351 } |
393 | 352 |
394 abstract class StaticError extends StaticInfo { | 353 abstract class StaticError extends StaticInfo { |
395 final AstNode node; | 354 final AstNode node; |
396 | 355 |
397 StaticError(this.node); | 356 StaticError(this.node); |
398 | 357 |
399 Level get level => Level.SEVERE; | 358 Level get level => Level.SEVERE; |
400 } | 359 } |
401 | 360 |
(...skipping 147 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
549 /// <http://goo.gl/q1T4BB> | 508 /// <http://goo.gl/q1T4BB> |
550 /// | 509 /// |
551 /// For now this is the only pattern we support. | 510 /// For now this is the only pattern we support. |
552 class InvalidSuperInvocation extends StaticError { | 511 class InvalidSuperInvocation extends StaticError { |
553 InvalidSuperInvocation(SuperConstructorInvocation node) : super(node); | 512 InvalidSuperInvocation(SuperConstructorInvocation node) : super(node); |
554 | 513 |
555 String get message => "super call must be last in an initializer list " | 514 String get message => "super call must be last in an initializer list " |
556 "(see http://goo.gl/q1T4BB): $node"; | 515 "(see http://goo.gl/q1T4BB): $node"; |
557 } | 516 } |
558 | 517 |
559 /// A simple generalizing visitor interface for the conversion nodes. | |
560 /// This can be mixed in to your visitor if the AST can contain these nodes. | |
561 abstract class ConversionVisitor<R> implements AstVisitor<R> { | |
562 /// This method must be implemented. It is typically supplied by the base | |
563 /// GeneralizingAstVisitor<R>. | |
564 R visitNode(AstNode node); | |
565 | |
566 /// The catch-all for any kind of conversion | |
567 R visitConversion(Conversion node) => visitNode(node); | |
568 | |
569 // Methods for conversion subtypes: | |
570 R visitDownCast(DownCast node) => visitConversion(node); | |
571 R visitDynamicInvoke(DynamicInvoke node) => visitConversion(node); | |
572 R visitInferredTypeBase(InferredTypeBase node) => visitConversion(node); | |
573 } | |
574 | |
575 /// Automatically infer list of types by scanning this library using mirrors. | 518 /// Automatically infer list of types by scanning this library using mirrors. |
576 final List<Type> infoTypes = () { | 519 final List<Type> infoTypes = () { |
577 var allTypes = new Set(); | 520 var allTypes = new Set(); |
578 var baseTypes = new Set(); | 521 var baseTypes = new Set(); |
579 var infoMirror = reflectClass(StaticInfo); | 522 var infoMirror = reflectClass(StaticInfo); |
580 var libMirror = infoMirror.owner as LibraryMirror; | 523 var libMirror = infoMirror.owner as LibraryMirror; |
581 var declarations = libMirror.declarations.values; | 524 var declarations = libMirror.declarations.values; |
582 for (ClassMirror cls in declarations.where((d) => d is ClassMirror)) { | 525 for (ClassMirror cls in declarations.where((d) => d is ClassMirror)) { |
583 if (cls.isSubtypeOf(infoMirror)) { | 526 if (cls.isSubtypeOf(infoMirror)) { |
584 allTypes.add(cls); | 527 allTypes.add(cls); |
(...skipping 11 matching lines...) Expand all Loading... | |
596 var isError = severity == analyzer.ErrorSeverity.WARNING; | 539 var isError = severity == analyzer.ErrorSeverity.WARNING; |
597 var level = isError ? Level.SEVERE : Level.WARNING; | 540 var level = isError ? Level.SEVERE : Level.WARNING; |
598 int begin = error.offset; | 541 int begin = error.offset; |
599 int end = begin + error.length; | 542 int end = begin + error.length; |
600 return new AnalyzerError(error.message, level, begin, end); | 543 return new AnalyzerError(error.message, level, begin, end); |
601 } | 544 } |
602 | 545 |
603 const AnalyzerError(String message, Level level, int begin, int end) | 546 const AnalyzerError(String message, Level level, int begin, int end) |
604 : super(message, level, begin, end); | 547 : super(message, level, begin, end); |
605 } | 548 } |
OLD | NEW |