| 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 'common.dart'; | 7 import 'common.dart'; |
| 8 import 'common/tasks.dart' show | 8 import 'common/tasks.dart' show CompilerTask; |
| 9 CompilerTask; | 9 import 'compile_time_constants.dart' show ConstantCompiler; |
| 10 import 'compile_time_constants.dart' show | 10 import 'compiler.dart' show Compiler; |
| 11 ConstantCompiler; | |
| 12 import 'compiler.dart' show | |
| 13 Compiler; | |
| 14 import 'constants/expressions.dart'; | 11 import 'constants/expressions.dart'; |
| 15 import 'constants/values.dart' show | 12 import 'constants/values.dart' |
| 16 ConstantValue, | 13 show |
| 17 ConstructedConstantValue, | 14 ConstantValue, |
| 18 ListConstantValue, | 15 ConstructedConstantValue, |
| 19 StringConstantValue, | 16 ListConstantValue, |
| 20 TypeConstantValue; | 17 StringConstantValue, |
| 21 import 'dart_types.dart' show | 18 TypeConstantValue; |
| 22 DartType, | 19 import 'dart_types.dart' show DartType, InterfaceType, TypeKind; |
| 23 InterfaceType, | 20 import 'elements/elements.dart' |
| 24 TypeKind; | 21 show |
| 25 import 'elements/elements.dart' show | 22 ClassElement, |
| 26 ClassElement, | 23 Element, |
| 27 Element, | 24 ImportElement, |
| 28 ImportElement, | 25 LibraryElement, |
| 29 LibraryElement, | 26 MetadataAnnotation, |
| 30 MetadataAnnotation, | 27 ScopeContainerElement, |
| 31 ScopeContainerElement, | 28 VariableElement; |
| 32 VariableElement; | 29 import 'resolution/tree_elements.dart' show TreeElements; |
| 33 import 'resolution/tree_elements.dart' show | 30 import 'tree/tree.dart' |
| 34 TreeElements; | 31 show Import, LibraryTag, NamedArgument, NewExpression, Node; |
| 35 import 'tree/tree.dart' show | |
| 36 Import, | |
| 37 LibraryTag, | |
| 38 NamedArgument, | |
| 39 NewExpression, | |
| 40 Node; | |
| 41 | 32 |
| 42 /** | 33 /** |
| 43 * Compiler task that analyzes MirrorsUsed annotations. | 34 * Compiler task that analyzes MirrorsUsed annotations. |
| 44 * | 35 * |
| 45 * When importing 'dart:mirrors', it is possible to annotate the import with | 36 * When importing 'dart:mirrors', it is possible to annotate the import with |
| 46 * MirrorsUsed annotation. This is a way to declare what elements will be | 37 * MirrorsUsed annotation. This is a way to declare what elements will be |
| 47 * reflected on at runtime. Such elements, even they would normally be | 38 * reflected on at runtime. Such elements, even they would normally be |
| 48 * discarded by the implicit tree-shaking algorithm must be preserved in the | 39 * discarded by the implicit tree-shaking algorithm must be preserved in the |
| 49 * final output. | 40 * final output. |
| 50 * | 41 * |
| (...skipping 33 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 84 * MirrorsUsed annotation, these annotations are merged. | 75 * MirrorsUsed annotation, these annotations are merged. |
| 85 * | 76 * |
| 86 * MERGING MIRRORSUSED | 77 * MERGING MIRRORSUSED |
| 87 * | 78 * |
| 88 * TBD. | 79 * TBD. |
| 89 */ | 80 */ |
| 90 class MirrorUsageAnalyzerTask extends CompilerTask { | 81 class MirrorUsageAnalyzerTask extends CompilerTask { |
| 91 Set<LibraryElement> librariesWithUsage; | 82 Set<LibraryElement> librariesWithUsage; |
| 92 MirrorUsageAnalyzer analyzer; | 83 MirrorUsageAnalyzer analyzer; |
| 93 | 84 |
| 94 MirrorUsageAnalyzerTask(Compiler compiler) | 85 MirrorUsageAnalyzerTask(Compiler compiler) : super(compiler) { |
| 95 : super(compiler) { | |
| 96 analyzer = new MirrorUsageAnalyzer(compiler, this); | 86 analyzer = new MirrorUsageAnalyzer(compiler, this); |
| 97 } | 87 } |
| 98 | 88 |
| 99 /// Collect @MirrorsUsed annotations in all libraries. Called by the | 89 /// Collect @MirrorsUsed annotations in all libraries. Called by the |
| 100 /// compiler after all libraries are loaded, but before resolution. | 90 /// compiler after all libraries are loaded, but before resolution. |
| 101 void analyzeUsage(LibraryElement mainApp) { | 91 void analyzeUsage(LibraryElement mainApp) { |
| 102 if (mainApp == null || compiler.mirrorsLibrary == null) return; | 92 if (mainApp == null || compiler.mirrorsLibrary == null) return; |
| 103 measure(analyzer.run); | 93 measure(analyzer.run); |
| 104 List<String> symbols = analyzer.mergedMirrorUsage.symbols; | 94 List<String> symbols = analyzer.mergedMirrorUsage.symbols; |
| 105 List<Element> targets = analyzer.mergedMirrorUsage.targets; | 95 List<Element> targets = analyzer.mergedMirrorUsage.targets; |
| 106 List<Element> metaTargets = analyzer.mergedMirrorUsage.metaTargets; | 96 List<Element> metaTargets = analyzer.mergedMirrorUsage.metaTargets; |
| 107 compiler.backend.registerMirrorUsage( | 97 compiler.backend.registerMirrorUsage( |
| 108 symbols == null ? null : new Set<String>.from(symbols), | 98 symbols == null ? null : new Set<String>.from(symbols), |
| 109 targets == null ? null : new Set<Element>.from(targets), | 99 targets == null ? null : new Set<Element>.from(targets), |
| 110 metaTargets == null ? null : new Set<Element>.from(metaTargets)); | 100 metaTargets == null ? null : new Set<Element>.from(metaTargets)); |
| 111 librariesWithUsage = analyzer.librariesWithUsage; | 101 librariesWithUsage = analyzer.librariesWithUsage; |
| 112 } | 102 } |
| 113 | 103 |
| 114 /// Is there a @MirrorsUsed annotation in the library of [element]? Used by | 104 /// Is there a @MirrorsUsed annotation in the library of [element]? Used by |
| 115 /// the resolver to suppress hints about using new Symbol or | 105 /// the resolver to suppress hints about using new Symbol or |
| 116 /// MirrorSystem.getName. | 106 /// MirrorSystem.getName. |
| 117 bool hasMirrorUsage(Element element) { | 107 bool hasMirrorUsage(Element element) { |
| 118 LibraryElement library = element.library; | 108 LibraryElement library = element.library; |
| 119 // Internal libraries always have implicit mirror usage. | 109 // Internal libraries always have implicit mirror usage. |
| 120 return library.isInternalLibrary | 110 return library.isInternalLibrary || |
| 121 || (librariesWithUsage != null | 111 (librariesWithUsage != null && librariesWithUsage.contains(library)); |
| 122 && librariesWithUsage.contains(library)); | |
| 123 } | 112 } |
| 124 | 113 |
| 125 /// Call-back from the resolver to analyze MirorsUsed annotations. The result | 114 /// Call-back from the resolver to analyze MirorsUsed annotations. The result |
| 126 /// is stored in [analyzer] and later used to compute | 115 /// is stored in [analyzer] and later used to compute |
| 127 /// [:analyzer.mergedMirrorUsage:]. | 116 /// [:analyzer.mergedMirrorUsage:]. |
| 128 void validate(NewExpression node, TreeElements mapping) { | 117 void validate(NewExpression node, TreeElements mapping) { |
| 129 for (Node argument in node.send.arguments) { | 118 for (Node argument in node.send.arguments) { |
| 130 NamedArgument named = argument.asNamedArgument(); | 119 NamedArgument named = argument.asNamedArgument(); |
| 131 if (named == null) continue; | 120 if (named == null) continue; |
| 132 ConstantCompiler constantCompiler = compiler.resolver.constantCompiler; | 121 ConstantCompiler constantCompiler = compiler.resolver.constantCompiler; |
| 133 ConstantValue value = | 122 ConstantValue value = constantCompiler.getConstantValue( |
| 134 constantCompiler.getConstantValue( | 123 constantCompiler.compileNode(named.expression, mapping)); |
| 135 constantCompiler.compileNode(named.expression, mapping)); | |
| 136 | 124 |
| 137 MirrorUsageBuilder builder = | 125 MirrorUsageBuilder builder = new MirrorUsageBuilder(analyzer, |
| 138 new MirrorUsageBuilder( | 126 mapping.analyzedElement.library, named.expression, value, mapping); |
| 139 analyzer, mapping.analyzedElement.library, named.expression, | |
| 140 value, mapping); | |
| 141 | 127 |
| 142 if (named.name.source == 'symbols') { | 128 if (named.name.source == 'symbols') { |
| 143 analyzer.cachedStrings[value] = | 129 analyzer.cachedStrings[value] = |
| 144 builder.convertConstantToUsageList(value, onlyStrings: true); | 130 builder.convertConstantToUsageList(value, onlyStrings: true); |
| 145 } else if (named.name.source == 'targets') { | 131 } else if (named.name.source == 'targets') { |
| 146 analyzer.cachedElements[value] = | 132 analyzer.cachedElements[value] = |
| 147 builder.resolveUsageList(builder.convertConstantToUsageList(value)); | 133 builder.resolveUsageList(builder.convertConstantToUsageList(value)); |
| 148 } else if (named.name.source == 'metaTargets') { | 134 } else if (named.name.source == 'metaTargets') { |
| 149 analyzer.cachedElements[value] = | 135 analyzer.cachedElements[value] = |
| 150 builder.resolveUsageList(builder.convertConstantToUsageList(value)); | 136 builder.resolveUsageList(builder.convertConstantToUsageList(value)); |
| (...skipping 43 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 194 | 180 |
| 195 /// Collect all @MirrorsUsed from all libraries and represent them as | 181 /// Collect all @MirrorsUsed from all libraries and represent them as |
| 196 /// [MirrorUsage]. | 182 /// [MirrorUsage]. |
| 197 Map<LibraryElement, List<MirrorUsage>> collectMirrorsUsedAnnotation() { | 183 Map<LibraryElement, List<MirrorUsage>> collectMirrorsUsedAnnotation() { |
| 198 Map<LibraryElement, List<MirrorUsage>> result = | 184 Map<LibraryElement, List<MirrorUsage>> result = |
| 199 new Map<LibraryElement, List<MirrorUsage>>(); | 185 new Map<LibraryElement, List<MirrorUsage>>(); |
| 200 for (LibraryElement library in compiler.libraryLoader.libraries) { | 186 for (LibraryElement library in compiler.libraryLoader.libraries) { |
| 201 if (library.isInternalLibrary) continue; | 187 if (library.isInternalLibrary) continue; |
| 202 for (ImportElement import in library.imports) { | 188 for (ImportElement import in library.imports) { |
| 203 reporter.withCurrentElement(library, () { | 189 reporter.withCurrentElement(library, () { |
| 204 List<MirrorUsage> usages = | 190 List<MirrorUsage> usages = mirrorsUsedOnLibraryTag(library, import); |
| 205 mirrorsUsedOnLibraryTag(library, import); | |
| 206 if (usages != null) { | 191 if (usages != null) { |
| 207 List<MirrorUsage> existing = result[library]; | 192 List<MirrorUsage> existing = result[library]; |
| 208 if (existing != null) { | 193 if (existing != null) { |
| 209 existing.addAll(usages); | 194 existing.addAll(usages); |
| 210 } else { | 195 } else { |
| 211 result[library] = usages; | 196 result[library] = usages; |
| 212 } | 197 } |
| 213 } | 198 } |
| 214 }); | 199 }); |
| 215 } | 200 } |
| (...skipping 19 matching lines...) Expand all Loading... |
| 235 } | 220 } |
| 236 } else { | 221 } else { |
| 237 for (Element overridden in override) { | 222 for (Element overridden in override) { |
| 238 List<MirrorUsage> overriddenUsages = propagatedOverrides | 223 List<MirrorUsage> overriddenUsages = propagatedOverrides |
| 239 .putIfAbsent(overridden, () => <MirrorUsage>[]); | 224 .putIfAbsent(overridden, () => <MirrorUsage>[]); |
| 240 overriddenUsages.add(usage); | 225 overriddenUsages.add(usage); |
| 241 } | 226 } |
| 242 } | 227 } |
| 243 } | 228 } |
| 244 }); | 229 }); |
| 245 propagatedOverrides.forEach((LibraryElement overridden, | 230 propagatedOverrides.forEach( |
| 246 List<MirrorUsage> overriddenUsages) { | 231 (LibraryElement overridden, List<MirrorUsage> overriddenUsages) { |
| 247 List<MirrorUsage> usages = | 232 List<MirrorUsage> usages = |
| 248 usageMap.putIfAbsent(overridden, () => <MirrorUsage>[]); | 233 usageMap.putIfAbsent(overridden, () => <MirrorUsage>[]); |
| 249 usages.addAll(overriddenUsages); | 234 usages.addAll(overriddenUsages); |
| 250 }); | 235 }); |
| 251 } | 236 } |
| 252 | 237 |
| 253 /// Find @MirrorsUsed annotations on the given import [tag] in [library]. The | 238 /// Find @MirrorsUsed annotations on the given import [tag] in [library]. The |
| 254 /// annotations are represented as [MirrorUsage]. | 239 /// annotations are represented as [MirrorUsage]. |
| 255 List<MirrorUsage> mirrorsUsedOnLibraryTag(LibraryElement library, | 240 List<MirrorUsage> mirrorsUsedOnLibraryTag( |
| 256 ImportElement import) { | 241 LibraryElement library, ImportElement import) { |
| 257 LibraryElement importedLibrary = import.importedLibrary; | 242 LibraryElement importedLibrary = import.importedLibrary; |
| 258 if (importedLibrary != compiler.mirrorsLibrary) { | 243 if (importedLibrary != compiler.mirrorsLibrary) { |
| 259 return null; | 244 return null; |
| 260 } | 245 } |
| 261 List<MirrorUsage> result = <MirrorUsage>[]; | 246 List<MirrorUsage> result = <MirrorUsage>[]; |
| 262 for (MetadataAnnotation metadata in import.metadata) { | 247 for (MetadataAnnotation metadata in import.metadata) { |
| 263 metadata.ensureResolved(compiler.resolution); | 248 metadata.ensureResolved(compiler.resolution); |
| 264 ConstantValue value = | 249 ConstantValue value = |
| 265 compiler.constants.getConstantValue(metadata.constant); | 250 compiler.constants.getConstantValue(metadata.constant); |
| 266 Element element = value.getType(compiler.coreTypes).element; | 251 Element element = value.getType(compiler.coreTypes).element; |
| (...skipping 22 matching lines...) Expand all Loading... |
| 289 } | 274 } |
| 290 } | 275 } |
| 291 | 276 |
| 292 /// Merge [a] with [b]. The resulting [MirrorUsage] simply has the symbols, | 277 /// Merge [a] with [b]. The resulting [MirrorUsage] simply has the symbols, |
| 293 /// targets, and metaTargets of [a] and [b] concatenated. 'override' is | 278 /// targets, and metaTargets of [a] and [b] concatenated. 'override' is |
| 294 /// ignored. | 279 /// ignored. |
| 295 MirrorUsage merge(MirrorUsage a, MirrorUsage b) { | 280 MirrorUsage merge(MirrorUsage a, MirrorUsage b) { |
| 296 // TOOO(ahe): Should be an instance method on MirrorUsage. | 281 // TOOO(ahe): Should be an instance method on MirrorUsage. |
| 297 if (a.symbols == null && a.targets == null && a.metaTargets == null) { | 282 if (a.symbols == null && a.targets == null && a.metaTargets == null) { |
| 298 return b; | 283 return b; |
| 299 } else if ( | 284 } else if (b.symbols == null && |
| 300 b.symbols == null && b.targets == null && b.metaTargets == null) { | 285 b.targets == null && |
| 286 b.metaTargets == null) { |
| 301 return a; | 287 return a; |
| 302 } | 288 } |
| 303 // TODO(ahe): Test the following cases. | 289 // TODO(ahe): Test the following cases. |
| 304 List<String> symbols = a.symbols; | 290 List<String> symbols = a.symbols; |
| 305 if (symbols == null) { | 291 if (symbols == null) { |
| 306 symbols = b.symbols; | 292 symbols = b.symbols; |
| 307 } else if (b.symbols != null) { | 293 } else if (b.symbols != null) { |
| 308 symbols.addAll(b.symbols); | 294 symbols.addAll(b.symbols); |
| 309 } | 295 } |
| 310 List<Element> targets = a.targets; | 296 List<Element> targets = a.targets; |
| 311 if (targets == null) { | 297 if (targets == null) { |
| 312 targets = b.targets; | 298 targets = b.targets; |
| 313 } else if (targets != wildcard && b.targets != null) { | 299 } else if (targets != wildcard && b.targets != null) { |
| 314 targets.addAll(b.targets); | 300 targets.addAll(b.targets); |
| 315 } | 301 } |
| 316 List<Element> metaTargets = a.metaTargets; | 302 List<Element> metaTargets = a.metaTargets; |
| 317 if (metaTargets == null) { | 303 if (metaTargets == null) { |
| 318 metaTargets = b.metaTargets; | 304 metaTargets = b.metaTargets; |
| 319 } else if (metaTargets != wildcard && b.metaTargets != null) { | 305 } else if (metaTargets != wildcard && b.metaTargets != null) { |
| 320 metaTargets.addAll(b.metaTargets); | 306 metaTargets.addAll(b.metaTargets); |
| 321 } | 307 } |
| 322 return new MirrorUsage(symbols, targets, metaTargets, null); | 308 return new MirrorUsage(symbols, targets, metaTargets, null); |
| 323 } | 309 } |
| 324 | 310 |
| 325 /// Convert a [constant] to an instance of [MirrorUsage] using information | 311 /// Convert a [constant] to an instance of [MirrorUsage] using information |
| 326 /// that was resolved during [MirrorUsageAnalyzerTask.validate]. | 312 /// that was resolved during [MirrorUsageAnalyzerTask.validate]. |
| 327 MirrorUsage buildUsage(ConstructedConstantValue constant) { | 313 MirrorUsage buildUsage(ConstructedConstantValue constant) { |
| 328 Map<Element, ConstantValue> fields = constant.fields; | 314 Map<Element, ConstantValue> fields = constant.fields; |
| 329 VariableElement symbolsField = compiler.mirrorsUsedClass.lookupLocalMember( | 315 VariableElement symbolsField = |
| 330 'symbols'); | 316 compiler.mirrorsUsedClass.lookupLocalMember('symbols'); |
| 331 VariableElement targetsField = compiler.mirrorsUsedClass.lookupLocalMember( | 317 VariableElement targetsField = |
| 332 'targets'); | 318 compiler.mirrorsUsedClass.lookupLocalMember('targets'); |
| 333 VariableElement metaTargetsField = | 319 VariableElement metaTargetsField = |
| 334 compiler.mirrorsUsedClass.lookupLocalMember( | 320 compiler.mirrorsUsedClass.lookupLocalMember('metaTargets'); |
| 335 'metaTargets'); | 321 VariableElement overrideField = |
| 336 VariableElement overrideField = compiler.mirrorsUsedClass.lookupLocalMember( | 322 compiler.mirrorsUsedClass.lookupLocalMember('override'); |
| 337 'override'); | |
| 338 | 323 |
| 339 return new MirrorUsage( | 324 return new MirrorUsage( |
| 340 cachedStrings[fields[symbolsField]], | 325 cachedStrings[fields[symbolsField]], |
| 341 cachedElements[fields[targetsField]], | 326 cachedElements[fields[targetsField]], |
| 342 cachedElements[fields[metaTargetsField]], | 327 cachedElements[fields[metaTargetsField]], |
| 343 cachedElements[fields[overrideField]]); | 328 cachedElements[fields[overrideField]]); |
| 344 } | 329 } |
| 345 } | 330 } |
| 346 | 331 |
| 347 /// Used to represent a resolved MirrorsUsed constant. | 332 /// Used to represent a resolved MirrorsUsed constant. |
| 348 class MirrorUsage { | 333 class MirrorUsage { |
| 349 final List<String> symbols; | 334 final List<String> symbols; |
| 350 final List<Element> targets; | 335 final List<Element> targets; |
| 351 final List<Element> metaTargets; | 336 final List<Element> metaTargets; |
| 352 final List<Element> override; | 337 final List<Element> override; |
| 353 | 338 |
| 354 MirrorUsage(this.symbols, this.targets, this.metaTargets, this.override); | 339 MirrorUsage(this.symbols, this.targets, this.metaTargets, this.override); |
| 355 | 340 |
| 356 String toString() { | 341 String toString() { |
| 357 return | 342 return 'MirrorUsage(' |
| 358 'MirrorUsage(' | |
| 359 'symbols = $symbols, ' | 343 'symbols = $symbols, ' |
| 360 'targets = $targets, ' | 344 'targets = $targets, ' |
| 361 'metaTargets = $metaTargets, ' | 345 'metaTargets = $metaTargets, ' |
| 362 'override = $override' | 346 'override = $override' |
| 363 ')'; | 347 ')'; |
| 364 | |
| 365 } | 348 } |
| 366 } | 349 } |
| 367 | 350 |
| 368 class MirrorUsageBuilder { | 351 class MirrorUsageBuilder { |
| 369 final MirrorUsageAnalyzer analyzer; | 352 final MirrorUsageAnalyzer analyzer; |
| 370 final LibraryElement enclosingLibrary; | 353 final LibraryElement enclosingLibrary; |
| 371 final Spannable spannable; | 354 final Spannable spannable; |
| 372 final ConstantValue constant; | 355 final ConstantValue constant; |
| 373 final TreeElements elements; | 356 final TreeElements elements; |
| 374 | 357 |
| 375 MirrorUsageBuilder( | 358 MirrorUsageBuilder(this.analyzer, this.enclosingLibrary, this.spannable, |
| 376 this.analyzer, | 359 this.constant, this.elements); |
| 377 this.enclosingLibrary, | |
| 378 this.spannable, | |
| 379 this.constant, | |
| 380 this.elements); | |
| 381 | 360 |
| 382 Compiler get compiler => analyzer.compiler; | 361 Compiler get compiler => analyzer.compiler; |
| 383 | 362 |
| 384 DiagnosticReporter get reporter => analyzer.reporter; | 363 DiagnosticReporter get reporter => analyzer.reporter; |
| 385 | 364 |
| 386 /// Convert a constant to a list of [String] and [Type] values. If the | 365 /// Convert a constant to a list of [String] and [Type] values. If the |
| 387 /// constant is a single [String], it is assumed to be a comma-separated list | 366 /// constant is a single [String], it is assumed to be a comma-separated list |
| 388 /// of qualified names. If the constant is a [Type] t, the result is [:[t]:]. | 367 /// of qualified names. If the constant is a [Type] t, the result is [:[t]:]. |
| 389 /// Otherwise, the constant is assumed to represent a list of strings (each a | 368 /// Otherwise, the constant is assumed to represent a list of strings (each a |
| 390 /// qualified name) and types, and such a list is constructed. If | 369 /// qualified name) and types, and such a list is constructed. If |
| 391 /// [onlyStrings] is true, the returned list is a [:List<String>:] and any | 370 /// [onlyStrings] is true, the returned list is a [:List<String>:] and any |
| 392 /// [Type] values are treated as an error (meaning that the value is ignored | 371 /// [Type] values are treated as an error (meaning that the value is ignored |
| 393 /// and a hint is emitted). | 372 /// and a hint is emitted). |
| 394 List convertConstantToUsageList( | 373 List convertConstantToUsageList(ConstantValue constant, |
| 395 ConstantValue constant, { bool onlyStrings: false }) { | 374 {bool onlyStrings: false}) { |
| 396 if (constant.isNull) { | 375 if (constant.isNull) { |
| 397 return null; | 376 return null; |
| 398 } else if (constant.isList) { | 377 } else if (constant.isList) { |
| 399 ListConstantValue list = constant; | 378 ListConstantValue list = constant; |
| 400 List result = onlyStrings ? <String> [] : []; | 379 List result = onlyStrings ? <String>[] : []; |
| 401 for (ConstantValue entry in list.entries) { | 380 for (ConstantValue entry in list.entries) { |
| 402 if (entry.isString) { | 381 if (entry.isString) { |
| 403 StringConstantValue string = entry; | 382 StringConstantValue string = entry; |
| 404 result.add(string.primitiveValue.slowToString()); | 383 result.add(string.primitiveValue.slowToString()); |
| 405 } else if (!onlyStrings && entry.isType) { | 384 } else if (!onlyStrings && entry.isType) { |
| 406 TypeConstantValue type = entry; | 385 TypeConstantValue type = entry; |
| 407 result.add(type.representedType); | 386 result.add(type.representedType); |
| 408 } else { | 387 } else { |
| 409 Spannable node = positionOf(entry); | 388 Spannable node = positionOf(entry); |
| 410 MessageKind kind = onlyStrings | 389 MessageKind kind = onlyStrings |
| (...skipping 25 matching lines...) Expand all Loading... |
| 436 | 415 |
| 437 /// Find the first non-implementation interface of constant. | 416 /// Find the first non-implementation interface of constant. |
| 438 DartType apiTypeOf(ConstantValue constant) { | 417 DartType apiTypeOf(ConstantValue constant) { |
| 439 DartType type = constant.getType(compiler.coreTypes); | 418 DartType type = constant.getType(compiler.coreTypes); |
| 440 LibraryElement library = type.element.library; | 419 LibraryElement library = type.element.library; |
| 441 if (type.isInterfaceType && library.isInternalLibrary) { | 420 if (type.isInterfaceType && library.isInternalLibrary) { |
| 442 InterfaceType interface = type; | 421 InterfaceType interface = type; |
| 443 ClassElement cls = type.element; | 422 ClassElement cls = type.element; |
| 444 cls.ensureResolved(compiler.resolution); | 423 cls.ensureResolved(compiler.resolution); |
| 445 for (DartType supertype in cls.allSupertypes) { | 424 for (DartType supertype in cls.allSupertypes) { |
| 446 if (supertype.isInterfaceType | 425 if (supertype.isInterfaceType && |
| 447 && !supertype.element.library.isInternalLibrary) { | 426 !supertype.element.library.isInternalLibrary) { |
| 448 return interface.asInstanceOf(supertype.element); | 427 return interface.asInstanceOf(supertype.element); |
| 449 } | 428 } |
| 450 } | 429 } |
| 451 } | 430 } |
| 452 return type; | 431 return type; |
| 453 } | 432 } |
| 454 | 433 |
| 455 /// Convert a list of strings and types to a list of elements. Types are | 434 /// Convert a list of strings and types to a list of elements. Types are |
| 456 /// converted to their corresponding element, and strings are resolved as | 435 /// converted to their corresponding element, and strings are resolved as |
| 457 /// follows: | 436 /// follows: |
| (...skipping 17 matching lines...) Expand all Loading... |
| 475 String libraryNameCandiate; | 454 String libraryNameCandiate; |
| 476 for (LibraryElement l in compiler.libraryLoader.libraries) { | 455 for (LibraryElement l in compiler.libraryLoader.libraries) { |
| 477 if (l.hasLibraryName) { | 456 if (l.hasLibraryName) { |
| 478 String libraryName = l.libraryOrScriptName; | 457 String libraryName = l.libraryOrScriptName; |
| 479 if (string == libraryName) { | 458 if (string == libraryName) { |
| 480 // Found an exact match. | 459 // Found an exact match. |
| 481 libraryCandiate = l; | 460 libraryCandiate = l; |
| 482 libraryNameCandiate = libraryName; | 461 libraryNameCandiate = libraryName; |
| 483 break; | 462 break; |
| 484 } else if (string.startsWith('$libraryName.')) { | 463 } else if (string.startsWith('$libraryName.')) { |
| 485 if (libraryNameCandiate == null | 464 if (libraryNameCandiate == null || |
| 486 || libraryNameCandiate.length < libraryName.length) { | 465 libraryNameCandiate.length < libraryName.length) { |
| 487 // Found a better candiate | 466 // Found a better candiate |
| 488 libraryCandiate = l; | 467 libraryCandiate = l; |
| 489 libraryNameCandiate = libraryName; | 468 libraryNameCandiate = libraryName; |
| 490 } | 469 } |
| 491 } | 470 } |
| 492 } | 471 } |
| 493 } | 472 } |
| 494 Element e; | 473 Element e; |
| 495 if (libraryNameCandiate == string) { | 474 if (libraryNameCandiate == string) { |
| 496 e = libraryCandiate; | 475 e = libraryCandiate; |
| 497 } else if (libraryNameCandiate != null) { | 476 } else if (libraryNameCandiate != null) { |
| 498 e = resolveLocalExpression( | 477 e = resolveLocalExpression(libraryCandiate, |
| 499 libraryCandiate, | |
| 500 string.substring(libraryNameCandiate.length + 1).split('.')); | 478 string.substring(libraryNameCandiate.length + 1).split('.')); |
| 501 } else { | 479 } else { |
| 502 e = resolveExpression(string); | 480 e = resolveExpression(string); |
| 503 } | 481 } |
| 504 if (e != null) result.add(e); | 482 if (e != null) result.add(e); |
| 505 } | 483 } |
| 506 } | 484 } |
| 507 return result; | 485 return result; |
| 508 } | 486 } |
| 509 | 487 |
| (...skipping 15 matching lines...) Expand all Loading... |
| 525 | 503 |
| 526 /// Resolve [identifiers] in [element]'s local members. | 504 /// Resolve [identifiers] in [element]'s local members. |
| 527 Element resolveLocalExpression(Element element, List<String> identifiers) { | 505 Element resolveLocalExpression(Element element, List<String> identifiers) { |
| 528 Element current = element; | 506 Element current = element; |
| 529 for (String identifier in identifiers) { | 507 for (String identifier in identifiers) { |
| 530 Element e = findLocalMemberIn(current, identifier); | 508 Element e = findLocalMemberIn(current, identifier); |
| 531 if (e == null) { | 509 if (e == null) { |
| 532 if (current.isLibrary) { | 510 if (current.isLibrary) { |
| 533 LibraryElement library = current; | 511 LibraryElement library = current; |
| 534 reporter.reportHintMessage( | 512 reporter.reportHintMessage( |
| 535 spannable, MessageKind.MIRRORS_CANNOT_RESOLVE_IN_LIBRARY, | 513 spannable, |
| 536 {'name': identifiers[0], | 514 MessageKind.MIRRORS_CANNOT_RESOLVE_IN_LIBRARY, |
| 537 'library': library.libraryOrScriptName}); | 515 {'name': identifiers[0], 'library': library.libraryOrScriptName}); |
| 538 } else { | 516 } else { |
| 539 reporter.reportHintMessage( | 517 reporter.reportHintMessage( |
| 540 spannable, MessageKind.MIRRORS_CANNOT_FIND_IN_ELEMENT, | 518 spannable, |
| 519 MessageKind.MIRRORS_CANNOT_FIND_IN_ELEMENT, |
| 541 {'name': identifier, 'element': current.name}); | 520 {'name': identifier, 'element': current.name}); |
| 542 } | 521 } |
| 543 return current; | 522 return current; |
| 544 } | 523 } |
| 545 current = e; | 524 current = e; |
| 546 } | 525 } |
| 547 return current; | 526 return current; |
| 548 } | 527 } |
| 549 | 528 |
| 550 /// Helper method to lookup members in a [ScopeContainerElement]. If | 529 /// Helper method to lookup members in a [ScopeContainerElement]. If |
| (...skipping 34 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 585 // @MirrorsUsed(targets: fisk) | 564 // @MirrorsUsed(targets: fisk) |
| 586 // ^^^^ | 565 // ^^^^ |
| 587 // | 566 // |
| 588 // Instead of saying 'fisk' should pretty print the problematic constant | 567 // Instead of saying 'fisk' should pretty print the problematic constant |
| 589 // value. | 568 // value. |
| 590 return spannable; | 569 return spannable; |
| 591 } | 570 } |
| 592 return node; | 571 return node; |
| 593 } | 572 } |
| 594 } | 573 } |
| OLD | NEW |