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 abstract class CoercionInfo extends StaticInfo { |
113 abstract class Conversion extends Expression with StaticInfo { | |
114 final TypeRules rules; | 111 final TypeRules rules; |
115 | 112 |
116 // TODO(jmesserly): should probably rename this "operand" for consistency with | 113 final Expression node; |
117 // analyzer's unary expressions (e.g. PrefixExpression). | |
118 final Expression expression; | |
119 | 114 |
120 AstNode get node => expression; | 115 DartType get convertedType; |
121 DartType _convertedType; | |
122 | 116 |
123 Conversion(this.rules, this.expression) { | 117 CoercionInfo(this.rules, this.node); |
124 this._convertedType = _getConvertedType(); | |
125 } | |
126 | 118 |
127 DartType get baseType => rules.getStaticType(expression); | 119 DartType get baseType => rules.getStaticType(node); |
128 DartType get convertedType => _convertedType; | 120 DartType get staticType => convertedType; |
129 DartType get staticType => _convertedType; | |
130 | |
131 DartType _getConvertedType(); | |
132 | 121 |
133 // safe iff this cannot throw | 122 // safe iff this cannot throw |
134 bool get safe => false; | 123 bool get safe => false; |
135 | 124 |
136 Level get level => safe ? Level.CONFIG : Level.INFO; | 125 Level get level => safe ? Level.CONFIG : Level.INFO; |
137 | 126 |
138 String get description => '${this.runtimeType}: $baseType to $convertedType'; | 127 String get description => '${this.runtimeType}: $baseType to $convertedType'; |
139 | 128 |
140 Token get beginToken => expression.beginToken; | 129 static const String _propertyName = 'dev_compiler.Conversion'; |
141 Token get endToken => expression.endToken; | |
142 | 130 |
143 @override | 131 /// Gets the coercion info associated with this node. |
144 void visitChildren(AstVisitor visitor) { | 132 static CoercionInfo get(AstNode node) => node.getProperty(_propertyName); |
145 expression.accept(visitor); | 133 |
| 134 /// Sets the coercion info associated with this node. |
| 135 static CoercionInfo set(AstNode node, CoercionInfo info) { |
| 136 node.setProperty(_propertyName, info); |
| 137 return info; |
146 } | 138 } |
147 | |
148 // Use same precedence as MethodInvocation. | |
149 int get precedence => 15; | |
150 | |
151 @override | |
152 Iterable get childEntities => new ChildEntities()..add(expression); | |
153 } | 139 } |
154 | 140 |
155 // Base class for all casts from base type to sub type. | 141 // Base class for all casts from base type to sub type. |
156 abstract class DownCast extends Conversion { | 142 abstract class DownCast extends CoercionInfo { |
157 Cast _cast; | 143 Cast _cast; |
158 | 144 |
159 DownCast._internal(TypeRules rules, Expression expression, this._cast) | 145 DownCast._internal(TypeRules rules, Expression expression, this._cast) |
160 : super(rules, expression) { | 146 : super(rules, expression) { |
161 assert(_cast.toType != baseType && | 147 assert(_cast.toType != baseType && |
162 _cast.fromType == baseType && | 148 _cast.fromType == baseType && |
163 (baseType.isDynamic || | 149 (baseType.isDynamic || |
164 // Call methods make the following non-redundant | 150 // Call methods make the following non-redundant |
165 _cast.toType.isSubtypeOf(baseType) || | 151 _cast.toType.isSubtypeOf(baseType) || |
166 baseType.isAssignableTo(_cast.toType))); | 152 baseType.isAssignableTo(_cast.toType))); |
167 } | 153 } |
168 | 154 |
169 Cast get cast => _cast; | 155 Cast get cast => _cast; |
170 | 156 |
171 DartType _getConvertedType() => _cast.toType; | 157 DartType get convertedType => _cast.toType; |
172 | 158 |
173 String get message => '$expression ($baseType) will need runtime check ' | 159 String get message => '$node ($baseType) will need runtime check ' |
174 'to cast to type $convertedType'; | 160 'to cast to type $convertedType'; |
175 | 161 |
176 // Factory to create correct DownCast variant. | 162 // Factory to create correct DownCast variant. |
177 static StaticInfo create(TypeRules rules, Expression expression, Cast cast, | 163 static StaticInfo create(TypeRules rules, Expression expression, Cast cast, |
178 {String reason}) { | 164 {String reason}) { |
179 final fromT = cast.fromType; | 165 final fromT = cast.fromType; |
180 final toT = cast.toType; | 166 final toT = cast.toType; |
181 | 167 |
182 // toT <:_R fromT => to <: fromT | 168 // toT <:_R fromT => to <: fromT |
183 // NB: classes with call methods are subtypes of function | 169 // NB: classes with call methods are subtypes of function |
(...skipping 44 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
228 | 214 |
229 // Assignment cast | 215 // Assignment cast |
230 var parent = expression.parent; | 216 var parent = expression.parent; |
231 if (parent is VariableDeclaration && (parent.initializer == expression)) { | 217 if (parent is VariableDeclaration && (parent.initializer == expression)) { |
232 return new AssignmentCast(rules, expression, cast); | 218 return new AssignmentCast(rules, expression, cast); |
233 } | 219 } |
234 | 220 |
235 // Other casts | 221 // Other casts |
236 return new DownCastImplicit(rules, expression, cast); | 222 return new DownCastImplicit(rules, expression, cast); |
237 } | 223 } |
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 } | 224 } |
247 | 225 |
248 // | 226 // |
249 // Standard down casts. These casts are implicitly injected by the compiler. | 227 // Standard down casts. These casts are implicitly injected by the compiler. |
250 // | 228 // |
251 | 229 |
252 // A down cast from dynamic to T. | 230 // A down cast from dynamic to T. |
253 class DynamicCast extends DownCast { | 231 class DynamicCast extends DownCast { |
254 DynamicCast(TypeRules rules, Expression expression, Cast cast) | 232 DynamicCast(TypeRules rules, Expression expression, Cast cast) |
255 : super._internal(rules, expression, cast); | 233 : super._internal(rules, expression, cast); |
(...skipping 46 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
302 // Dart and may be more likely to fail at runtime. | 280 // Dart and may be more likely to fail at runtime. |
303 class DownCastImplicit extends DownCast { | 281 class DownCastImplicit extends DownCast { |
304 DownCastImplicit(TypeRules rules, Expression expression, Cast cast) | 282 DownCastImplicit(TypeRules rules, Expression expression, Cast cast) |
305 : super._internal(rules, expression, cast); | 283 : super._internal(rules, expression, cast); |
306 | 284 |
307 final Level level = Level.WARNING; | 285 final Level level = Level.WARNING; |
308 } | 286 } |
309 | 287 |
310 // An inferred type for the wrapped expression, which may need to be | 288 // An inferred type for the wrapped expression, which may need to be |
311 // reified into the term | 289 // reified into the term |
312 abstract class InferredTypeBase extends Conversion { | 290 abstract class InferredTypeBase extends CoercionInfo { |
313 DartType _type; | 291 final DartType _type; |
314 | 292 |
315 InferredTypeBase._internal(TypeRules rules, Expression expression, this._type) | 293 InferredTypeBase._internal(TypeRules rules, Expression expression, this._type) |
316 : super(rules, expression); | 294 : super(rules, expression); |
317 | 295 |
318 DartType get type => _type; | 296 DartType get type => _type; |
319 | 297 DartType get convertedType => type; |
320 DartType _getConvertedType() => type; | 298 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; | 299 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 } | 300 } |
334 | 301 |
335 // Standard / unspecialized inferred type | 302 // Standard / unspecialized inferred type |
336 class InferredType extends InferredTypeBase { | 303 class InferredType extends InferredTypeBase { |
337 InferredType(TypeRules rules, Expression expression, DartType type) | 304 InferredType(TypeRules rules, Expression expression, DartType type) |
338 : super._internal(rules, expression, type); | 305 : super._internal(rules, expression, type); |
339 | 306 |
340 // Factory to create correct InferredType variant. | 307 // Factory to create correct InferredType variant. |
341 static InferredTypeBase create( | 308 static InferredTypeBase create( |
342 TypeRules rules, Expression expression, DartType type) { | 309 TypeRules rules, Expression expression, DartType type) { |
(...skipping 23 matching lines...) Expand all Loading... |
366 InferredTypeAllocation(TypeRules rules, Expression expression, DartType type) | 333 InferredTypeAllocation(TypeRules rules, Expression expression, DartType type) |
367 : super._internal(rules, expression, type); | 334 : super._internal(rules, expression, type); |
368 } | 335 } |
369 | 336 |
370 // An inferred type for a closure expression | 337 // An inferred type for a closure expression |
371 class InferredTypeClosure extends InferredTypeBase { | 338 class InferredTypeClosure extends InferredTypeBase { |
372 InferredTypeClosure(TypeRules rules, Expression expression, DartType type) | 339 InferredTypeClosure(TypeRules rules, Expression expression, DartType type) |
373 : super._internal(rules, expression, type); | 340 : super._internal(rules, expression, type); |
374 } | 341 } |
375 | 342 |
376 class DynamicInvoke extends Conversion { | 343 class DynamicInvoke extends CoercionInfo { |
377 DynamicInvoke(TypeRules rules, Expression expression) | 344 DynamicInvoke(TypeRules rules, Expression expression) |
378 : super(rules, expression); | 345 : super(rules, expression); |
379 | 346 |
380 DartType _getConvertedType() => rules.provider.dynamicType; | 347 DartType get convertedType => rules.provider.dynamicType; |
381 | 348 String get message => '$node requires dynamic invoke'; |
382 String get message => '$expression requires dynamic invoke'; | |
383 Level get level => Level.INFO; | 349 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 } | 350 } |
393 | 351 |
394 abstract class StaticError extends StaticInfo { | 352 abstract class StaticError extends StaticInfo { |
395 final AstNode node; | 353 final AstNode node; |
396 | 354 |
397 StaticError(this.node); | 355 StaticError(this.node); |
398 | 356 |
399 Level get level => Level.SEVERE; | 357 Level get level => Level.SEVERE; |
400 } | 358 } |
401 | 359 |
(...skipping 147 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
549 /// <http://goo.gl/q1T4BB> | 507 /// <http://goo.gl/q1T4BB> |
550 /// | 508 /// |
551 /// For now this is the only pattern we support. | 509 /// For now this is the only pattern we support. |
552 class InvalidSuperInvocation extends StaticError { | 510 class InvalidSuperInvocation extends StaticError { |
553 InvalidSuperInvocation(SuperConstructorInvocation node) : super(node); | 511 InvalidSuperInvocation(SuperConstructorInvocation node) : super(node); |
554 | 512 |
555 String get message => "super call must be last in an initializer list " | 513 String get message => "super call must be last in an initializer list " |
556 "(see http://goo.gl/q1T4BB): $node"; | 514 "(see http://goo.gl/q1T4BB): $node"; |
557 } | 515 } |
558 | 516 |
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. | 517 /// Automatically infer list of types by scanning this library using mirrors. |
576 final List<Type> infoTypes = () { | 518 final List<Type> infoTypes = () { |
577 var allTypes = new Set(); | 519 var allTypes = new Set(); |
578 var baseTypes = new Set(); | 520 var baseTypes = new Set(); |
579 var infoMirror = reflectClass(StaticInfo); | 521 var infoMirror = reflectClass(StaticInfo); |
580 var libMirror = infoMirror.owner as LibraryMirror; | 522 var libMirror = infoMirror.owner as LibraryMirror; |
581 var declarations = libMirror.declarations.values; | 523 var declarations = libMirror.declarations.values; |
582 for (ClassMirror cls in declarations.where((d) => d is ClassMirror)) { | 524 for (ClassMirror cls in declarations.where((d) => d is ClassMirror)) { |
583 if (cls.isSubtypeOf(infoMirror)) { | 525 if (cls.isSubtypeOf(infoMirror)) { |
584 allTypes.add(cls); | 526 allTypes.add(cls); |
(...skipping 11 matching lines...) Expand all Loading... |
596 var isError = severity == analyzer.ErrorSeverity.WARNING; | 538 var isError = severity == analyzer.ErrorSeverity.WARNING; |
597 var level = isError ? Level.SEVERE : Level.WARNING; | 539 var level = isError ? Level.SEVERE : Level.WARNING; |
598 int begin = error.offset; | 540 int begin = error.offset; |
599 int end = begin + error.length; | 541 int end = begin + error.length; |
600 return new AnalyzerError(error.message, level, begin, end); | 542 return new AnalyzerError(error.message, level, begin, end); |
601 } | 543 } |
602 | 544 |
603 const AnalyzerError(String message, Level level, int begin, int end) | 545 const AnalyzerError(String message, Level level, int begin, int end) |
604 : super(message, level, begin, end); | 546 : super(message, level, begin, end); |
605 } | 547 } |
OLD | NEW |