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 |