Chromium Code Reviews
chromiumcodereview-hr@appspot.gserviceaccount.com (chromiumcodereview-hr) | Please choose your nickname with Settings | Help | Chromium Project | Gerrit Changes | Sign out
(219)

Side by Side Diff: dart/sdk/lib/_internal/compiler/implementation/mirrors_used.dart

Issue 21242002: Retain elements a finer granularity than library. (Closed) Base URL: https://dart.googlecode.com/svn/branches/bleeding_edge
Patch Set: Variable initialized too early. Created 7 years, 4 months ago
Use n/p to move between diff chunks; N/P to move between comments. Draft comments are only viewable by you.
Jump to:
View unified diff | Download patch | Annotate | Revision Log
OLDNEW
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;
Johnni Winther 2013/08/07 10:39:17 Overall for this file: Document methods.
ahe 2013/08/07 13:40:20 Done.
6 6
7 import 'dart2jslib.dart' show 7 import 'dart2jslib.dart' show
8 Compiler, 8 Compiler,
9 CompilerTask, 9 CompilerTask,
10 Constant, 10 Constant,
11 ConstructedConstant, 11 ConstructedConstant,
12 ListConstant, 12 ListConstant,
13 MessageKind, 13 MessageKind,
14 SourceString, 14 SourceString,
15 StringConstant, 15 StringConstant,
16 TypeConstant; 16 TreeElements,
17 TypeConstant,
18 invariant;
17 19
18 import 'elements/elements.dart' show 20 import 'elements/elements.dart' show
21 ClassElement,
19 Element, 22 Element,
20 LibraryElement, 23 LibraryElement,
21 MetadataAnnotation, 24 MetadataAnnotation,
25 ScopeContainerElement,
22 VariableElement; 26 VariableElement;
23 27
24 import 'util/util.dart' show 28 import 'util/util.dart' show
25 Link; 29 Link,
30 Spannable;
26 31
27 import 'dart_types.dart' show 32 import 'dart_types.dart' show
28 DartType; 33 DartType,
34 InterfaceType,
35 TypeKind;
29 36
30 import 'tree/tree.dart' show 37 import 'tree/tree.dart' show
31 Import, 38 Import,
32 LibraryTag; 39 LibraryTag,
40 NamedArgument,
41 NewExpression,
42 Node;
43
44 import 'resolution/resolution.dart' show
45 ConstantMapper;
33 46
34 /** 47 /**
35 * Compiler task that analyzes MirrorsUsed annotations. 48 * Compiler task that analyzes MirrorsUsed annotations.
36 * 49 *
37 * When importing 'dart:mirrors', it is possible to annotate the import with 50 * When importing 'dart:mirrors', it is possible to annotate the import with
38 * MirrorsUsed annotation. This is a way to declare what elements will be 51 * MirrorsUsed annotation. This is a way to declare what elements will be
39 * reflected on at runtime. Such elements, even they would normally be 52 * reflected on at runtime. Such elements, even they would normally be
40 * discarded by the implicit tree-shaking algorithm must be preserved in the 53 * discarded by the implicit tree-shaking algorithm must be preserved in the
41 * final output. 54 * final output.
42 * 55 *
(...skipping 31 matching lines...) Expand 10 before | Expand all | Expand 10 after
74 * 87 *
75 * On the other hand, if all libraries importing dart:mirrors have a 88 * On the other hand, if all libraries importing dart:mirrors have a
76 * MirrorsUsed annotation, these annotations are merged. 89 * MirrorsUsed annotation, these annotations are merged.
77 * 90 *
78 * MERGING MIRRORSUSED 91 * MERGING MIRRORSUSED
79 * 92 *
80 * TBD. 93 * TBD.
81 */ 94 */
82 class MirrorUsageAnalyzerTask extends CompilerTask { 95 class MirrorUsageAnalyzerTask extends CompilerTask {
83 Set<LibraryElement> librariesWithUsage; 96 Set<LibraryElement> librariesWithUsage;
97 MirrorUsageAnalyzer analyzer;
84 98
85 MirrorUsageAnalyzerTask(Compiler compiler) 99 MirrorUsageAnalyzerTask(Compiler compiler)
86 : super(compiler); 100 : super(compiler) {
101 analyzer = new MirrorUsageAnalyzer(compiler, this);
102 }
87 103
88 void analyzeUsage(LibraryElement mainApp) { 104 void analyzeUsage(LibraryElement mainApp) {
89 if (compiler.mirrorsLibrary == null) return; 105 if (compiler.mirrorsLibrary == null) return;
90 MirrorUsageAnalyzer analyzer = new MirrorUsageAnalyzer(compiler, this);
91 measure(analyzer.run); 106 measure(analyzer.run);
92 List<String> symbols = analyzer.mergedMirrorUsage.symbols; 107 List<String> symbols = analyzer.mergedMirrorUsage.symbols;
93 List<Element> targets = analyzer.mergedMirrorUsage.targets; 108 List<Element> targets = analyzer.mergedMirrorUsage.targets;
94 List<Element> metaTargets = analyzer.mergedMirrorUsage.metaTargets; 109 List<Element> metaTargets = analyzer.mergedMirrorUsage.metaTargets;
95 compiler.backend.registerMirrorUsage( 110 compiler.backend.registerMirrorUsage(
96 symbols == null ? null : new Set<String>.from(symbols), 111 symbols == null ? null : new Set<String>.from(symbols),
97 targets == null ? null : new Set<Element>.from(targets), 112 targets == null ? null : new Set<Element>.from(targets),
98 metaTargets == null ? null : new Set<Element>.from(metaTargets)); 113 metaTargets == null ? null : new Set<Element>.from(metaTargets));
99 librariesWithUsage = analyzer.librariesWithUsage; 114 librariesWithUsage = analyzer.librariesWithUsage;
100 } 115 }
101 116
102 bool hasMirrorUsage(Element element) { 117 bool hasMirrorUsage(Element element) {
103 return librariesWithUsage != null 118 return librariesWithUsage != null
104 && librariesWithUsage.contains(element.getLibrary()); 119 && librariesWithUsage.contains(element.getLibrary());
105 } 120 }
121
122 void validate(NewExpression node, TreeElements mapping) {
123 for (Node argument in node.send.arguments) {
124 NamedArgument named = argument.asNamedArgument();
125 if (named == null) continue;
126 Constant value = compiler.metadataHandler.compileNodeWithDefinitions(
127 named.expression, mapping, isConst: true);
128
129 ConstantMapper mapper =
130 new ConstantMapper(compiler.metadataHandler, mapping, compiler);
131 named.expression.accept(mapper);
132
133 MirrorUsageBuilder builder =
134 new MirrorUsageBuilder(
135 analyzer, mapping.currentElement.getLibrary(), named.expression,
136 value, mapper.constantToNodeMap);
137
138 if (named.name.source == const SourceString('symbols')) {
139 analyzer.cachedValues[value] =
140 builder.convertToListOfStrings(
141 builder.convertConstantToUsageList(value, onlyStrings: true));
142 } else if (named.name.source == const SourceString('targets')) {
143 analyzer.cachedValues[value] =
144 builder.resolveUsageList(builder.convertConstantToUsageList(value));
145 } else if (named.name.source == const SourceString('metaTargets')) {
146 analyzer.cachedValues[value] =
147 builder.resolveUsageList(builder.convertConstantToUsageList(value));
148 } else if (named.name.source == const SourceString('override')) {
149 analyzer.cachedValues[value] =
150 builder.resolveUsageList(builder.convertConstantToUsageList(value));
151 }
152 }
153 }
106 } 154 }
107 155
108 class MirrorUsageAnalyzer { 156 class MirrorUsageAnalyzer {
109 final Compiler compiler; 157 final Compiler compiler;
110 final MirrorUsageAnalyzerTask task; 158 final MirrorUsageAnalyzerTask task;
111 final List<LibraryElement> wildcard; 159 List<LibraryElement> wildcard;
112 final Set<LibraryElement> librariesWithUsage; 160 final Set<LibraryElement> librariesWithUsage;
113 final Set<LibraryElement> librariesWithoutUsage; 161 final Map<Constant, List> cachedValues;
114 MirrorUsage mergedMirrorUsage; 162 MirrorUsage mergedMirrorUsage;
115 163
116 MirrorUsageAnalyzer(Compiler compiler, this.task) 164 MirrorUsageAnalyzer(Compiler compiler, this.task)
117 : compiler = compiler, 165 : compiler = compiler,
118 wildcard = compiler.libraries.values.toList(),
119 librariesWithUsage = new Set<LibraryElement>(), 166 librariesWithUsage = new Set<LibraryElement>(),
120 librariesWithoutUsage = new Set<LibraryElement>(); 167 cachedValues = new Map<Constant, List>();
121 168
122 void run() { 169 void run() {
170 wildcard = compiler.libraries.values.toList();
123 Map<LibraryElement, List<MirrorUsage>> usageMap = 171 Map<LibraryElement, List<MirrorUsage>> usageMap =
124 collectMirrorsUsedAnnotation(); 172 collectMirrorsUsedAnnotation();
125 propagateOverrides(usageMap); 173 propagateOverrides(usageMap);
126 librariesWithoutUsage.removeAll(usageMap.keys); 174 Set<LibraryElement> librariesWithoutUsage = new Set<LibraryElement>();
175 usageMap.forEach((LibraryElement library, List<MirrorUsage> usage) {
176 if (usage.isEmpty) librariesWithoutUsage.add(library);
177 });
127 if (librariesWithoutUsage.isEmpty) { 178 if (librariesWithoutUsage.isEmpty) {
128 mergedMirrorUsage = mergeUsages(usageMap); 179 mergedMirrorUsage = mergeUsages(usageMap);
129 } else { 180 } else {
130 mergedMirrorUsage = new MirrorUsage(null, wildcard, null, null); 181 mergedMirrorUsage = new MirrorUsage(null, wildcard, null, null);
131 } 182 }
132 } 183 }
133 184
134 Map<LibraryElement, List<MirrorUsage>> collectMirrorsUsedAnnotation() { 185 Map<LibraryElement, List<MirrorUsage>> collectMirrorsUsedAnnotation() {
135 Map<LibraryElement, List<MirrorUsage>> result = 186 Map<LibraryElement, List<MirrorUsage>> result =
136 new Map<LibraryElement, List<MirrorUsage>>(); 187 new Map<LibraryElement, List<MirrorUsage>>();
137 for (LibraryElement library in compiler.libraries.values) { 188 for (LibraryElement library in compiler.libraries.values) {
138 if (library.isInternalLibrary) continue; 189 if (library.isInternalLibrary) continue;
139 librariesWithoutUsage.add(library);
140 for (LibraryTag tag in library.tags) { 190 for (LibraryTag tag in library.tags) {
141 Import importTag = tag.asImport(); 191 Import importTag = tag.asImport();
142 if (importTag == null) continue; 192 if (importTag == null) continue;
143 compiler.withCurrentElement(library, () { 193 compiler.withCurrentElement(library, () {
144 List<MirrorUsage> usages = 194 List<MirrorUsage> usages =
145 mirrorsUsedOnLibraryTag(library, importTag); 195 mirrorsUsedOnLibraryTag(library, importTag);
146 if (usages != null) { 196 if (usages != null) {
147 List<MirrorUsage> existing = result[library]; 197 List<MirrorUsage> existing = result[library];
148 if (existing != null) { 198 if (existing != null) {
149 existing.addAll(usages); 199 existing.addAll(usages);
(...skipping 43 matching lines...) Expand 10 before | Expand all | Expand 10 after
193 Import tag) { 243 Import tag) {
194 LibraryElement importedLibrary = library.getLibraryFromTag(tag); 244 LibraryElement importedLibrary = library.getLibraryFromTag(tag);
195 if (importedLibrary != compiler.mirrorsLibrary) { 245 if (importedLibrary != compiler.mirrorsLibrary) {
196 return null; 246 return null;
197 } 247 }
198 List<MirrorUsage> result = <MirrorUsage>[]; 248 List<MirrorUsage> result = <MirrorUsage>[];
199 for (MetadataAnnotation metadata in tag.metadata) { 249 for (MetadataAnnotation metadata in tag.metadata) {
200 metadata.ensureResolved(compiler); 250 metadata.ensureResolved(compiler);
201 Element element = metadata.value.computeType(compiler).element; 251 Element element = metadata.value.computeType(compiler).element;
202 if (element == compiler.mirrorsUsedClass) { 252 if (element == compiler.mirrorsUsedClass) {
203 try { 253 result.add(buildUsage(metadata.value));
204 MirrorUsage usage =
205 new MirrorUsageBuilder(this, library).build(metadata.value);
206 result.add(usage);
207 } on BadMirrorsUsedAnnotation catch (e) {
208 compiler.reportError(
209 metadata, MessageKind.GENERIC, {'text': e.message});
210 }
211 } 254 }
212 } 255 }
213 return result; 256 return result;
214 } 257 }
215 258
216 MirrorUsage mergeUsages(Map<LibraryElement, List<MirrorUsage>> usageMap) { 259 MirrorUsage mergeUsages(Map<LibraryElement, List<MirrorUsage>> usageMap) {
217 Set<MirrorUsage> usagesToMerge = new Set<MirrorUsage>(); 260 Set<MirrorUsage> usagesToMerge = new Set<MirrorUsage>();
218 usageMap.forEach((LibraryElement library, List<MirrorUsage> usages) { 261 usageMap.forEach((LibraryElement library, List<MirrorUsage> usages) {
219 librariesWithUsage.add(library); 262 librariesWithUsage.add(library);
220 usagesToMerge.addAll(usages); 263 usagesToMerge.addAll(usages);
(...skipping 30 matching lines...) Expand all
251 targets.addAll(b.targets); 294 targets.addAll(b.targets);
252 } 295 }
253 List<Element> metaTargets = a.metaTargets; 296 List<Element> metaTargets = a.metaTargets;
254 if (metaTargets == null) { 297 if (metaTargets == null) {
255 metaTargets = b.metaTargets; 298 metaTargets = b.metaTargets;
256 } else if (metaTargets != wildcard && b.metaTargets != null) { 299 } else if (metaTargets != wildcard && b.metaTargets != null) {
257 metaTargets.addAll(b.metaTargets); 300 metaTargets.addAll(b.metaTargets);
258 } 301 }
259 return new MirrorUsage(symbols, targets, metaTargets, null); 302 return new MirrorUsage(symbols, targets, metaTargets, null);
260 } 303 }
304
305 MirrorUsage buildUsage(ConstructedConstant constructedConstant) {
306 Map<Element, Constant> fields = constructedConstant.fieldElements;
307 VariableElement symbolsField = compiler.mirrorsUsedClass.lookupLocalMember(
308 const SourceString('symbols'));
309 VariableElement targetsField = compiler.mirrorsUsedClass.lookupLocalMember(
310 const SourceString('targets'));
311 VariableElement metaTargetsField =
312 compiler.mirrorsUsedClass.lookupLocalMember(
313 const SourceString('metaTargets'));
314 VariableElement overrideField = compiler.mirrorsUsedClass.lookupLocalMember(
315 const SourceString('override'));
316
317 return new MirrorUsage(
318 cachedValues[fields[symbolsField]],
319 cachedValues[fields[targetsField]],
320 cachedValues[fields[metaTargetsField]],
321 cachedValues[fields[overrideField]]);
322 }
261 } 323 }
262 324
263 class MirrorUsage { 325 class MirrorUsage {
264 final List<String> symbols; 326 final List<String> symbols;
265 final List<Element> targets; 327 final List<Element> targets;
266 final List<Element> metaTargets; 328 final List<Element> metaTargets;
267 final List<Element> override; 329 final List<Element> override;
268 330
269 MirrorUsage(this.symbols, this.targets, this.metaTargets, this.override); 331 MirrorUsage(this.symbols, this.targets, this.metaTargets, this.override);
270 332
271 String toString() { 333 String toString() {
272 return 334 return
273 'MirrorUsage(' 335 'MirrorUsage('
274 'symbols = $symbols, ' 336 'symbols = $symbols, '
275 'targets = $targets, ' 337 'targets = $targets, '
276 'metaTargets = $metaTargets, ' 338 'metaTargets = $metaTargets, '
277 'override = $override' 339 'override = $override'
278 ')'; 340 ')';
279 341
280 } 342 }
281 } 343 }
282 344
283 class MirrorUsageBuilder { 345 class MirrorUsageBuilder {
284 MirrorUsageAnalyzer analyzer; 346 final MirrorUsageAnalyzer analyzer;
285 LibraryElement enclosingLibrary; 347 final LibraryElement enclosingLibrary;
348 final Spannable spannable;
349 final Constant constant;
350 final Map<Constant, Node> constantToNodeMap;
286 351
287 MirrorUsageBuilder(this.analyzer, this.enclosingLibrary); 352 MirrorUsageBuilder(
353 this.analyzer,
354 this.enclosingLibrary,
355 this.spannable,
356 this.constant,
357 this.constantToNodeMap);
288 358
289 Compiler get compiler => analyzer.compiler; 359 Compiler get compiler => analyzer.compiler;
290 360
291 MirrorUsage build(ConstructedConstant constant) { 361 List convertConstantToUsageList(
292 Map<Element, Constant> fields = constant.fieldElements; 362 Constant constant, { bool onlyStrings: false }) {
293 VariableElement symbolsField = compiler.mirrorsUsedClass.lookupLocalMember(
294 const SourceString('symbols'));
295 VariableElement targetsField = compiler.mirrorsUsedClass.lookupLocalMember(
296 const SourceString('targets'));
297 VariableElement metaTargetsField =
298 compiler.mirrorsUsedClass.lookupLocalMember(
299 const SourceString('metaTargets'));
300 VariableElement overrideField = compiler.mirrorsUsedClass.lookupLocalMember(
301 const SourceString('override'));
302 List<String> symbols =
303 convertToListOfStrings(
304 convertConstantToUsageList(fields[symbolsField]));
305 List<Element> targets =
306 resolveUsageList(convertConstantToUsageList(fields[targetsField]));
307
308 List<Element> metaTargets =
309 resolveUsageList(convertConstantToUsageList(fields[metaTargetsField]));
310 List<Element> override =
311 resolveUsageList(convertConstantToUsageList(fields[overrideField]));
312 return new MirrorUsage(symbols, targets, metaTargets, override);
313 }
314
315 List convertConstantToUsageList(Constant constant) {
316 if (constant.isNull()) { 363 if (constant.isNull()) {
317 return null; 364 return null;
318 } else if (constant.isList()) { 365 } else if (constant.isList()) {
319 ListConstant list = constant; 366 ListConstant list = constant;
320 List result = []; 367 List result = [];
321 for (Constant entry in list.entries) { 368 for (Constant entry in list.entries) {
322 if (entry.isString()) { 369 if (entry.isString()) {
323 StringConstant string = entry; 370 StringConstant string = entry;
324 result.add(string.value.slowToString()); 371 result.add(string.value.slowToString());
325 } else if (entry.isType()) { 372 } else if (!onlyStrings && entry.isType()) {
326 TypeConstant type = entry; 373 TypeConstant type = entry;
327 result.add(type.representedType); 374 result.add(type.representedType);
328 } else { 375 } else {
329 throw new BadMirrorsUsedAnnotation( 376 Spannable node = positionOf(entry);
330 'Expected a string or type, but got "$entry".'); 377 MessageKind kind = onlyStrings
378 ? MessageKind.MIRRORS_EXPECTED_STRING
379 : MessageKind.MIRRORS_EXPECTED_STRING_OR_TYPE;
380 compiler.reportHint(
381 node,
382 kind, {'name': node, 'type': apiTypeOf(entry)});
331 } 383 }
332 } 384 }
333 return result; 385 return result;
334 } else if (constant.isType()) { 386 } else if (!onlyStrings && constant.isType()) {
335 TypeConstant type = constant; 387 TypeConstant type = constant;
336 return [type.representedType]; 388 return [type.representedType];
337 } else if (constant.isString()) { 389 } else if (constant.isString()) {
338 StringConstant string = constant; 390 StringConstant string = constant;
339 return 391 return
340 string.value.slowToString().split(',').map((e) => e.trim()).toList(); 392 string.value.slowToString().split(',').map((e) => e.trim()).toList();
341 } else { 393 } else {
342 throw new BadMirrorsUsedAnnotation( 394 Spannable node = positionOf(constant);
343 'Expected a string or a list of string, but got "$constant".'); 395 MessageKind kind = onlyStrings
396 ? MessageKind.MIRRORS_EXPECTED_STRING_OR_LIST
397 : MessageKind.MIRRORS_EXPECTED_STRING_TYPE_OR_LIST;
398 compiler.reportHint(
399 node,
400 kind, {'name': node, 'type': apiTypeOf(constant)});
401 return null;
344 } 402 }
345 } 403 }
346 404
405 DartType apiTypeOf(Constant constant) {
406 DartType type = constant.computeType(compiler);
Johnni Winther 2013/08/07 10:39:17 This doesn't work for double constants with zero f
ahe 2013/08/07 13:40:20 That sounds like a bug in our constant system.
407 LibraryElement library = type.element.getLibrary();
408 if (type.kind == TypeKind.INTERFACE && library.isInternalLibrary) {
409 InterfaceType interface = type;
410 ClassElement cls = type.element;
411 for (DartType supertype in cls.ensureResolved(compiler).allSupertypes) {
412 if (supertype.kind == TypeKind.INTERFACE
413 && !supertype.element.getLibrary().isInternalLibrary) {
414 return interface.asInstanceOf(supertype.element);
415 }
416 }
417 }
418 return type;
419 }
420
347 List<String> convertToListOfStrings(List list) { 421 List<String> convertToListOfStrings(List list) {
348 if (list == null) return null; 422 if (list == null) return null;
349 List<String> result = new List<String>(list.length); 423 List<String> result = new List<String>(list.length);
350 int count = 0; 424 int count = 0;
351 for (var entry in list) { 425 for (var entry in list) {
352 if (entry is! String) { 426 assert(invariant(spannable, entry is String));
353 throw new BadMirrorsUsedAnnotation(
354 'Expected a string, but got "$entry"');
355 }
356 result[count++] = entry; 427 result[count++] = entry;
357 } 428 }
358 return result; 429 return result;
359 } 430 }
360 431
361 List<Element> resolveUsageList(List list) { 432 List<Element> resolveUsageList(List list) {
362 if (list == null) return null; 433 if (list == null) return null;
363 if (list.length == 1 && list[0] == '*') { 434 if (list.length == 1 && list[0] == '*') {
364 return analyzer.wildcard; 435 return analyzer.wildcard;
365 } 436 }
366 List<Element> result = <Element>[]; 437 List<Element> result = <Element>[];
367 for (var entry in list) { 438 for (var entry in list) {
368 if (entry is DartType) { 439 if (entry is DartType) {
369 DartType type = entry; 440 DartType type = entry;
370 result.add(type.element); 441 result.add(type.element);
371 } else { 442 } else {
372 String string = entry; 443 String string = entry;
444 LibraryElement libraryCandiate;
445 String libraryNameCandiate;
373 for (LibraryElement l in compiler.libraries.values) { 446 for (LibraryElement l in compiler.libraries.values) {
374 if (l.hasLibraryName()) { 447 if (l.hasLibraryName()) {
375 String libraryName = l.getLibraryOrScriptName(); 448 String libraryName = l.getLibraryOrScriptName();
376 if (string == libraryName || string.startsWith('$libraryName.')) { 449 if (string == libraryName) {
377 result.add(l); 450 // Found an exact match.
451 libraryCandiate = l;
452 libraryNameCandiate = libraryName;
378 break; 453 break;
454 } else if (string.startsWith('$libraryName.')) {
455 if (libraryNameCandiate == null
456 || libraryNameCandiate.length < libraryName.length) {
457 // Found a better candiate
458 libraryCandiate = l;
459 libraryNameCandiate = libraryName;
460 }
379 } 461 }
380 } 462 }
381 } 463 }
464 Element e;
465 if (libraryNameCandiate == string) {
466 e = libraryCandiate;
467 } else if (libraryNameCandiate != null) {
468 e = resolveLocalExpression(
469 libraryCandiate,
470 string.substring(libraryNameCandiate.length + 1).split('.'));
471 } else {
472 e = resolveExpression(string);
473 }
474 if (e != null) result.add(e);
382 } 475 }
383 } 476 }
384 return result; 477 return result;
385 } 478 }
479
480 /// Resolve [expression] in [enclosingLibrary]'s import scope.
481 Element resolveExpression(String expression) {
482 List<String> identifiers = expression.split('.');
483 Element element = enclosingLibrary.find(new SourceString(identifiers[0]));
484 if (element == null) {
485 compiler.reportHint(
486 spannable, MessageKind.MIRRORS_CANNOT_RESOLVE_IN_CURRENT_LIBRARY,
487 {'name': identifiers[0]});
488 return null;
489 } else {
490 if (identifiers.length == 1) return element;
491 return resolveLocalExpression(element, identifiers.sublist(1));
492 }
493 }
494
495 /// Resolve [identifiers] in [element]'s local members.
496 Element resolveLocalExpression(Element element, List<String> identifiers) {
497 Element current = element;
498 for (String identifier in identifiers) {
499 Element e = findLocalMemberIn(current, new SourceString(identifier));
500 if (e == null) {
501 if (current.isLibrary()) {
502 LibraryElement library = current;
503 compiler.reportHint(
504 spannable, MessageKind.MIRRORS_CANNOT_RESOLVE_IN_LIBRARY,
505 {'name': identifiers[0],
506 'library': library.getLibraryOrScriptName()});
507 } else {
508 compiler.reportHint(
509 spannable, MessageKind.MIRRORS_CANNOT_FIND_IN_ELEMENT,
510 {'name': identifier, 'element': current.name});
511 }
512 return current;
513 }
514 current = e;
515 }
516 return current;
517 }
518
519 Element findLocalMemberIn(Element element, SourceString name) {
520 if (element is ScopeContainerElement) {
521 ScopeContainerElement scope = element as dynamic;
522 return scope.localLookup(name);
523 }
524 return null;
525 }
526
527 Spannable positionOf(Constant constant) {
528 Node node = constantToNodeMap[constant];
529 if (node != null) {
530 // TODO(ahe): Returning [node] here leads to confusing error messages.
531 // For example, consider:
532 // @MirrorsUsed(targets: fisk)
533 // import 'dart:mirrors';
534 //
535 // const fisk = const [main];
536 //
537 // main() {}
538 //
539 // The message is:
540 // example.dart:1:23: Hint: Can't use 'fisk' here because ...
541 // Did you forget to add quotes?
542 // @MirrorsUsed(targets: fisk)
543 // ^^^^
544 //
545 // Instead of saying 'fisk' should pretty print the problematic constant
546 // value.
547 return node;
548 }
549 return spannable;
550 }
386 } 551 }
387
388 class BadMirrorsUsedAnnotation {
389 final String message;
390 BadMirrorsUsedAnnotation(this.message);
391 }
OLDNEW

Powered by Google App Engine
This is Rietveld 408576698