OLD | NEW |
1 // Copyright (c) 2013, the Dart project authors. Please see the AUTHORS file | 1 // Copyright (c) 2013, 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 library dart2js.mirrors_used; | 5 library dart2js.mirrors_used; |
6 | 6 |
7 import 'dart2jslib.dart' show | 7 import 'dart2jslib.dart' show |
8 Compiler, | 8 Compiler, |
9 CompilerTask, | 9 CompilerTask, |
10 Constant, | 10 Constant, |
(...skipping 129 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
140 new ConstantMapper(compiler.constantHandler, mapping, compiler); | 140 new ConstantMapper(compiler.constantHandler, mapping, compiler); |
141 named.expression.accept(mapper); | 141 named.expression.accept(mapper); |
142 | 142 |
143 MirrorUsageBuilder builder = | 143 MirrorUsageBuilder builder = |
144 new MirrorUsageBuilder( | 144 new MirrorUsageBuilder( |
145 analyzer, mapping.currentElement.getLibrary(), named.expression, | 145 analyzer, mapping.currentElement.getLibrary(), named.expression, |
146 value, mapper.constantToNodeMap); | 146 value, mapper.constantToNodeMap); |
147 | 147 |
148 if (named.name.source == 'symbols') { | 148 if (named.name.source == 'symbols') { |
149 analyzer.cachedStrings[value] = | 149 analyzer.cachedStrings[value] = |
150 builder.convertToListOfStrings( | 150 builder.convertConstantToUsageList(value, onlyStrings: true); |
151 builder.convertConstantToUsageList(value, onlyStrings: true)); | |
152 } else if (named.name.source == 'targets') { | 151 } else if (named.name.source == 'targets') { |
153 analyzer.cachedElements[value] = | 152 analyzer.cachedElements[value] = |
154 builder.resolveUsageList(builder.convertConstantToUsageList(value)); | 153 builder.resolveUsageList(builder.convertConstantToUsageList(value)); |
155 } else if (named.name.source == 'metaTargets') { | 154 } else if (named.name.source == 'metaTargets') { |
156 analyzer.cachedElements[value] = | 155 analyzer.cachedElements[value] = |
157 builder.resolveUsageList(builder.convertConstantToUsageList(value)); | 156 builder.resolveUsageList(builder.convertConstantToUsageList(value)); |
158 } else if (named.name.source == 'override') { | 157 } else if (named.name.source == 'override') { |
159 analyzer.cachedElements[value] = | 158 analyzer.cachedElements[value] = |
160 builder.resolveUsageList(builder.convertConstantToUsageList(value)); | 159 builder.resolveUsageList(builder.convertConstantToUsageList(value)); |
161 } | 160 } |
(...skipping 221 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
383 this.spannable, | 382 this.spannable, |
384 this.constant, | 383 this.constant, |
385 this.constantToNodeMap); | 384 this.constantToNodeMap); |
386 | 385 |
387 Compiler get compiler => analyzer.compiler; | 386 Compiler get compiler => analyzer.compiler; |
388 | 387 |
389 /// Convert a constant to a list of [String] and [Type] values. If the | 388 /// Convert a constant to a list of [String] and [Type] values. If the |
390 /// constant is a single [String], it is assumed to be a comma-separated list | 389 /// constant is a single [String], it is assumed to be a comma-separated list |
391 /// of qualified names. If the constant is a [Type] t, the result is [:[t]:]. | 390 /// of qualified names. If the constant is a [Type] t, the result is [:[t]:]. |
392 /// Otherwise, the constant is assumed to represent a list of strings (each a | 391 /// Otherwise, the constant is assumed to represent a list of strings (each a |
393 /// qualified name) and types, and such a list is constructed. | 392 /// qualified name) and types, and such a list is constructed. If |
| 393 /// [onlyStrings] is true, the returned list is a [:List<String>:] and any |
| 394 /// [Type] values are treated as an error (meaning that the value is ignored |
| 395 /// and a hint is emitted). |
394 List convertConstantToUsageList( | 396 List convertConstantToUsageList( |
395 Constant constant, { bool onlyStrings: false }) { | 397 Constant constant, { bool onlyStrings: false }) { |
396 if (constant.isNull()) { | 398 if (constant.isNull()) { |
397 return null; | 399 return null; |
398 } else if (constant.isList()) { | 400 } else if (constant.isList()) { |
399 ListConstant list = constant; | 401 ListConstant list = constant; |
400 List result = []; | 402 List result = onlyStrings ? <String> [] : []; |
401 for (Constant entry in list.entries) { | 403 for (Constant entry in list.entries) { |
402 if (entry.isString()) { | 404 if (entry.isString()) { |
403 StringConstant string = entry; | 405 StringConstant string = entry; |
404 result.add(string.value.slowToString()); | 406 result.add(string.value.slowToString()); |
405 } else if (!onlyStrings && entry.isType()) { | 407 } else if (!onlyStrings && entry.isType()) { |
406 TypeConstant type = entry; | 408 TypeConstant type = entry; |
407 result.add(type.representedType); | 409 result.add(type.representedType); |
408 } else { | 410 } else { |
409 Spannable node = positionOf(entry); | 411 Spannable node = positionOf(entry); |
410 MessageKind kind = onlyStrings | 412 MessageKind kind = onlyStrings |
411 ? MessageKind.MIRRORS_EXPECTED_STRING | 413 ? MessageKind.MIRRORS_EXPECTED_STRING |
412 : MessageKind.MIRRORS_EXPECTED_STRING_OR_TYPE; | 414 : MessageKind.MIRRORS_EXPECTED_STRING_OR_TYPE; |
413 compiler.reportHint( | 415 compiler.reportHint( |
414 node, | 416 node, |
415 kind, {'name': node, 'type': apiTypeOf(entry)}); | 417 kind, {'name': node, 'type': apiTypeOf(entry)}); |
416 } | 418 } |
417 } | 419 } |
418 return result; | 420 return result; |
419 } else if (!onlyStrings && constant.isType()) { | 421 } else if (!onlyStrings && constant.isType()) { |
420 TypeConstant type = constant; | 422 TypeConstant type = constant; |
421 return [type.representedType]; | 423 return [type.representedType]; |
422 } else if (constant.isString()) { | 424 } else if (constant.isString()) { |
423 StringConstant string = constant; | 425 StringConstant string = constant; |
424 return | 426 var iterable = |
425 string.value.slowToString().split(',').map((e) => e.trim()).toList(); | 427 string.value.slowToString().split(',').map((e) => e.trim()); |
| 428 return onlyStrings ? new List<String>.from(iterable) : iterable.toList(); |
426 } else { | 429 } else { |
427 Spannable node = positionOf(constant); | 430 Spannable node = positionOf(constant); |
428 MessageKind kind = onlyStrings | 431 MessageKind kind = onlyStrings |
429 ? MessageKind.MIRRORS_EXPECTED_STRING_OR_LIST | 432 ? MessageKind.MIRRORS_EXPECTED_STRING_OR_LIST |
430 : MessageKind.MIRRORS_EXPECTED_STRING_TYPE_OR_LIST; | 433 : MessageKind.MIRRORS_EXPECTED_STRING_TYPE_OR_LIST; |
431 compiler.reportHint( | 434 compiler.reportHint( |
432 node, | 435 node, |
433 kind, {'name': node, 'type': apiTypeOf(constant)}); | 436 kind, {'name': node, 'type': apiTypeOf(constant)}); |
434 return null; | 437 return null; |
435 } | 438 } |
436 } | 439 } |
437 | 440 |
438 /// Find the first non-implementation interface of constant. | 441 /// Find the first non-implementation interface of constant. |
439 DartType apiTypeOf(Constant constant) { | 442 DartType apiTypeOf(Constant constant) { |
440 DartType type = constant.computeType(compiler); | 443 DartType type = constant.computeType(compiler); |
441 LibraryElement library = type.element.getLibrary(); | 444 LibraryElement library = type.element.getLibrary(); |
442 if (type.kind == TypeKind.INTERFACE && library.isInternalLibrary) { | 445 if (type.kind == TypeKind.INTERFACE && library.isInternalLibrary) { |
443 InterfaceType interface = type; | 446 InterfaceType interface = type; |
444 ClassElement cls = type.element; | 447 ClassElement cls = type.element; |
445 for (DartType supertype in cls.ensureResolved(compiler).allSupertypes) { | 448 for (DartType supertype in cls.ensureResolved(compiler).allSupertypes) { |
446 if (supertype.kind == TypeKind.INTERFACE | 449 if (supertype.kind == TypeKind.INTERFACE |
447 && !supertype.element.getLibrary().isInternalLibrary) { | 450 && !supertype.element.getLibrary().isInternalLibrary) { |
448 return interface.asInstanceOf(supertype.element); | 451 return interface.asInstanceOf(supertype.element); |
449 } | 452 } |
450 } | 453 } |
451 } | 454 } |
452 return type; | 455 return type; |
453 } | 456 } |
454 | 457 |
455 /// Ensure a list contains only strings. | |
456 List<String> convertToListOfStrings(List list) { | |
457 if (list == null) return null; | |
458 List<String> result = new List<String>(list.length); | |
459 int count = 0; | |
460 for (var entry in list) { | |
461 assert(invariant(spannable, entry is String)); | |
462 result[count++] = entry; | |
463 } | |
464 return result; | |
465 } | |
466 | |
467 /// Convert a list of strings and types to a list of elements. Types are | 458 /// Convert a list of strings and types to a list of elements. Types are |
468 /// converted to their corresponding element, and strings are resolved as | 459 /// converted to their corresponding element, and strings are resolved as |
469 /// follows: | 460 /// follows: |
470 /// | 461 /// |
471 /// First find the longest library name that is a prefix of the string, if | 462 /// First find the longest library name that is a prefix of the string, if |
472 /// there are none, resolve using [resolveExpression]. Otherwise, resolve the | 463 /// there are none, resolve using [resolveExpression]. Otherwise, resolve the |
473 /// rest of the string using [resolveLocalExpression]. | 464 /// rest of the string using [resolveLocalExpression]. |
474 List<Element> resolveUsageList(List list) { | 465 List<Element> resolveUsageList(List list) { |
475 if (list == null) return null; | 466 if (list == null) return null; |
476 if (list.length == 1 && list[0] == '*') { | 467 if (list.length == 1 && list[0] == '*') { |
(...skipping 114 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
591 // @MirrorsUsed(targets: fisk) | 582 // @MirrorsUsed(targets: fisk) |
592 // ^^^^ | 583 // ^^^^ |
593 // | 584 // |
594 // Instead of saying 'fisk' should pretty print the problematic constant | 585 // Instead of saying 'fisk' should pretty print the problematic constant |
595 // value. | 586 // value. |
596 return spannable; | 587 return spannable; |
597 } | 588 } |
598 return node; | 589 return node; |
599 } | 590 } |
600 } | 591 } |
OLD | NEW |