| 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 |