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

Side by Side Diff: mojo/public/dart/third_party/analyzer/lib/src/task/dart.dart

Issue 1346773002: Stop running pub get at gclient sync time and fix build bugs (Closed) Base URL: git@github.com:domokit/mojo.git@master
Patch Set: Created 5 years, 3 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
OLDNEW
(Empty)
1 // Copyright (c) 2015, the Dart project authors. Please see the AUTHORS file
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.
4
5 library analyzer.src.task.dart;
6
7 import 'dart:collection';
8
9 import 'package:analyzer/src/context/cache.dart';
10 import 'package:analyzer/src/generated/ast.dart';
11 import 'package:analyzer/src/generated/constant.dart';
12 import 'package:analyzer/src/generated/element.dart';
13 import 'package:analyzer/src/generated/engine.dart'
14 hide AnalysisCache, AnalysisTask;
15 import 'package:analyzer/src/generated/error.dart';
16 import 'package:analyzer/src/generated/error_verifier.dart';
17 import 'package:analyzer/src/generated/incremental_resolver.dart';
18 import 'package:analyzer/src/generated/java_engine.dart';
19 import 'package:analyzer/src/generated/parser.dart';
20 import 'package:analyzer/src/generated/resolver.dart';
21 import 'package:analyzer/src/generated/scanner.dart';
22 import 'package:analyzer/src/generated/sdk.dart';
23 import 'package:analyzer/src/generated/source.dart';
24 import 'package:analyzer/src/task/driver.dart';
25 import 'package:analyzer/src/task/general.dart';
26 import 'package:analyzer/src/task/html.dart';
27 import 'package:analyzer/src/task/inputs.dart';
28 import 'package:analyzer/src/task/model.dart';
29 import 'package:analyzer/src/task/strong_mode.dart';
30 import 'package:analyzer/task/dart.dart';
31 import 'package:analyzer/task/general.dart';
32 import 'package:analyzer/task/model.dart';
33
34 /**
35 * The [ResultCachingPolicy] for ASTs.
36 */
37 const ResultCachingPolicy AST_CACHING_POLICY =
38 const SimpleResultCachingPolicy(8192, 8192);
39
40 /**
41 * The [ResultCachingPolicy] for [Element]s.
42 */
43 const ResultCachingPolicy ELEMENT_CACHING_POLICY =
44 const SimpleResultCachingPolicy(-1, -1);
45
46 /**
47 * The [ResultCachingPolicy] for [TOKEN_STREAM].
48 */
49 const ResultCachingPolicy TOKEN_STREAM_CACHING_POLICY =
50 const SimpleResultCachingPolicy(1, 1);
51
52 /**
53 * The errors produced while resolving a library directives.
54 *
55 * The list will be empty if there were no errors, but will not be `null`.
56 *
57 * The result is only available for [Source]s representing a library.
58 */
59 final ListResultDescriptor<AnalysisError> BUILD_DIRECTIVES_ERRORS =
60 new ListResultDescriptor<AnalysisError>(
61 'BUILD_DIRECTIVES_ERRORS', AnalysisError.NO_ERRORS);
62
63 /**
64 * The errors produced while building a library element.
65 *
66 * The list will be empty if there were no errors, but will not be `null`.
67 *
68 * The result is only available for [Source]s representing a library.
69 */
70 final ListResultDescriptor<AnalysisError> BUILD_LIBRARY_ERRORS =
71 new ListResultDescriptor<AnalysisError>(
72 'BUILD_LIBRARY_ERRORS', AnalysisError.NO_ERRORS);
73
74 /**
75 * A list of the [ClassElement]s representing the classes defined in a
76 * compilation unit.
77 *
78 * The result is only available for [LibrarySpecificUnit]s, and only when strong
79 * mode is enabled.
80 */
81 final ListResultDescriptor<ClassElement> CLASSES_IN_UNIT =
82 new ListResultDescriptor<ClassElement>('CLASSES_IN_UNIT', null);
83
84 /**
85 * A list of the [ConstantEvaluationTarget]s defined in a unit. This includes
86 * constants defined at top level, statically inside classes, and local to
87 * functions, as well as constant constructors, annotations, and default values
88 * of parameters to constant constructors.
89 */
90 final ListResultDescriptor<
91 ConstantEvaluationTarget> COMPILATION_UNIT_CONSTANTS =
92 new ListResultDescriptor<ConstantEvaluationTarget>(
93 'COMPILATION_UNIT_CONSTANTS', null,
94 cachingPolicy: ELEMENT_CACHING_POLICY);
95
96 /**
97 * The element model associated with a single compilation unit.
98 *
99 * The result is only available for [LibrarySpecificUnit]s.
100 */
101 final ResultDescriptor<CompilationUnitElement> COMPILATION_UNIT_ELEMENT =
102 new ResultDescriptor<CompilationUnitElement>(
103 'COMPILATION_UNIT_ELEMENT', null,
104 cachingPolicy: ELEMENT_CACHING_POLICY);
105
106 /**
107 * The list of [ConstantEvaluationTarget]s on which the target constant element
108 * depends.
109 *
110 * The result is only available for targets representing a
111 * [ConstantEvaluationTarget] (i.e. a constant variable declaration, a constant
112 * constructor, or a parameter element with a default value).
113 */
114 final ListResultDescriptor<ConstantEvaluationTarget> CONSTANT_DEPENDENCIES =
115 new ListResultDescriptor<ConstantEvaluationTarget>(
116 'CONSTANT_DEPENDENCIES', const <ConstantEvaluationTarget>[]);
117
118 /**
119 * A [ConstantEvaluationTarget] that has been successfully constant-evaluated.
120 *
121 * TODO(paulberry): is ELEMENT_CACHING_POLICY the correct caching policy?
122 */
123 final ResultDescriptor<ConstantEvaluationTarget> CONSTANT_VALUE =
124 new ResultDescriptor<ConstantEvaluationTarget>('CONSTANT_VALUE', null,
125 cachingPolicy: ELEMENT_CACHING_POLICY);
126
127 /**
128 * The sources representing the libraries that include a given source as a part.
129 *
130 * The result is only available for [Source]s representing a compilation unit.
131 */
132 final ListResultDescriptor<Source> CONTAINING_LIBRARIES =
133 new ListResultDescriptor<Source>('CONTAINING_LIBRARIES', Source.EMPTY_LIST);
134
135 /**
136 * The sources representing the export closure of a library.
137 * The [Source]s include only library sources, not their units.
138 *
139 * The result is only available for [Source]s representing a library.
140 */
141 final ListResultDescriptor<Source> EXPORT_SOURCE_CLOSURE =
142 new ListResultDescriptor<Source>('EXPORT_SOURCE_CLOSURE', null);
143
144 /**
145 * The errors produced while generating hints a compilation unit.
146 *
147 * The list will be empty if there were no errors, but will not be `null`.
148 *
149 * The result is only available for [LibrarySpecificUnit]s.
150 */
151 final ListResultDescriptor<AnalysisError> HINTS =
152 new ListResultDescriptor<AnalysisError>(
153 'HINT_ERRORS', AnalysisError.NO_ERRORS);
154
155 /**
156 * The sources representing the combined import/export closure of a library.
157 * The [Source]s include only library sources, not their units.
158 *
159 * The result is only available for [Source]s representing a library.
160 */
161 final ListResultDescriptor<Source> IMPORT_EXPORT_SOURCE_CLOSURE =
162 new ListResultDescriptor<Source>('IMPORT_EXPORT_SOURCE_CLOSURE', null);
163
164 /**
165 * A list of the [VariableElement]s whose type should be inferred that another
166 * inferable static variable (the target) depends on.
167 *
168 * The result is only available for [VariableElement]s, and only when strong
169 * mode is enabled.
170 */
171 final ListResultDescriptor<
172 VariableElement> INFERABLE_STATIC_VARIABLE_DEPENDENCIES =
173 new ListResultDescriptor<VariableElement>(
174 'INFERABLE_STATIC_VARIABLE_DEPENDENCIES', null);
175
176 /**
177 * A list of the [VariableElement]s defined in a unit whose type should be
178 * inferred. This includes variables defined at the library level as well as
179 * static members inside classes.
180 *
181 * The result is only available for [LibrarySpecificUnit]s, and only when strong
182 * mode is enabled.
183 */
184 final ListResultDescriptor<VariableElement> INFERABLE_STATIC_VARIABLES_IN_UNIT =
185 new ListResultDescriptor<VariableElement>(
186 'INFERABLE_STATIC_VARIABLES_IN_UNIT', null);
187
188 /**
189 * An inferrable static variable ([VariableElement]) whose type has been
190 * inferred.
191 */
192 final ResultDescriptor<VariableElement> INFERRED_STATIC_VARIABLE =
193 new ResultDescriptor<VariableElement>('INFERRED_STATIC_VARIABLE', null,
194 cachingPolicy: ELEMENT_CACHING_POLICY);
195
196 /**
197 * The partial [LibraryElement] associated with a library.
198 *
199 * The [LibraryElement] and its [CompilationUnitElement]s are attached to each
200 * other. Directives 'library', 'part' and 'part of' are resolved.
201 *
202 * The result is only available for [Source]s representing a library.
203 */
204 final ResultDescriptor<LibraryElement> LIBRARY_ELEMENT1 =
205 new ResultDescriptor<LibraryElement>('LIBRARY_ELEMENT1', null,
206 cachingPolicy: ELEMENT_CACHING_POLICY);
207
208 /**
209 * The partial [LibraryElement] associated with a library.
210 *
211 * In addition to [LIBRARY_ELEMENT1] [LibraryElement.imports] and
212 * [LibraryElement.exports] are set.
213 *
214 * The result is only available for [Source]s representing a library.
215 */
216 final ResultDescriptor<LibraryElement> LIBRARY_ELEMENT2 =
217 new ResultDescriptor<LibraryElement>('LIBRARY_ELEMENT2', null,
218 cachingPolicy: ELEMENT_CACHING_POLICY);
219
220 /**
221 * The partial [LibraryElement] associated with a library.
222 *
223 * In addition to [LIBRARY_ELEMENT2] the [LibraryElement.publicNamespace] is set .
224 *
225 * The result is only available for [Source]s representing a library.
226 */
227 final ResultDescriptor<LibraryElement> LIBRARY_ELEMENT3 =
228 new ResultDescriptor<LibraryElement>('LIBRARY_ELEMENT3', null,
229 cachingPolicy: ELEMENT_CACHING_POLICY);
230
231 /**
232 * The partial [LibraryElement] associated with a library.
233 *
234 * In addition to [LIBRARY_ELEMENT3] the [LibraryElement.entryPoint] is set,
235 * if the library does not declare one already and one of the exported
236 * libraries exports one.
237 *
238 * Also [LibraryElement.exportNamespace] is set.
239 *
240 * The result is only available for [Source]s representing a library.
241 */
242 final ResultDescriptor<LibraryElement> LIBRARY_ELEMENT4 =
243 new ResultDescriptor<LibraryElement>('LIBRARY_ELEMENT4', null,
244 cachingPolicy: ELEMENT_CACHING_POLICY);
245
246 /**
247 * The partial [LibraryElement] associated with a library.
248 *
249 * [LIBRARY_ELEMENT4] plus resolved types for every element.
250 *
251 * The result is only available for [Source]s representing a library.
252 */
253 final ResultDescriptor<LibraryElement> LIBRARY_ELEMENT5 =
254 new ResultDescriptor<LibraryElement>('LIBRARY_ELEMENT5', null,
255 cachingPolicy: ELEMENT_CACHING_POLICY);
256
257 /**
258 * The flag specifying whether all analysis errors are computed in a specific
259 * library.
260 *
261 * The result is only available for [Source]s representing a library.
262 */
263 final ResultDescriptor<bool> LIBRARY_ERRORS_READY =
264 new ResultDescriptor<bool>('LIBRARY_ERRORS_READY', false);
265
266 /**
267 * The analysis errors associated with a compilation unit in a specific library.
268 *
269 * The result is only available for [LibrarySpecificUnit]s.
270 */
271 final ListResultDescriptor<AnalysisError> LIBRARY_UNIT_ERRORS =
272 new ListResultDescriptor<AnalysisError>(
273 'LIBRARY_UNIT_ERRORS', AnalysisError.NO_ERRORS);
274
275 /**
276 * The errors produced while parsing a compilation unit.
277 *
278 * The list will be empty if there were no errors, but will not be `null`.
279 *
280 * The result is only available for [Source]s representing a compilation unit.
281 */
282 final ListResultDescriptor<AnalysisError> PARSE_ERRORS =
283 new ListResultDescriptor<AnalysisError>(
284 'PARSE_ERRORS', AnalysisError.NO_ERRORS);
285
286 /**
287 * The errors produced while resolving references outside of function bodies.
288 *
289 * The list will be empty if there were no errors, but will not be `null`.
290 *
291 * The result is only available for [LibrarySpecificUnit]s.
292 */
293 final ListResultDescriptor<AnalysisError> PARTIALLY_RESOLVE_REFERENCES_ERRORS =
294 new ListResultDescriptor<AnalysisError>(
295 'PARTIALLY_RESOLVE_REFERENCES_ERRORS', AnalysisError.NO_ERRORS);
296
297 /**
298 * The names (resolved and not) referenced by a unit.
299 *
300 * The result is only available for [Source]s representing a compilation unit.
301 */
302 final ResultDescriptor<ReferencedNames> REFERENCED_NAMES =
303 new ResultDescriptor<ReferencedNames>('REFERENCED_NAMES', null);
304
305 /**
306 * The errors produced while resolving references.
307 *
308 * The list will be empty if there were no errors, but will not be `null`.
309 *
310 * The result is only available for [LibrarySpecificUnit]s.
311 */
312 final ListResultDescriptor<AnalysisError> RESOLVE_REFERENCES_ERRORS =
313 new ListResultDescriptor<AnalysisError>(
314 'RESOLVE_REFERENCES_ERRORS', AnalysisError.NO_ERRORS);
315
316 /**
317 * The errors produced while resolving type names.
318 *
319 * The list will be empty if there were no errors, but will not be `null`.
320 *
321 * The result is only available for [LibrarySpecificUnit]s.
322 */
323 final ListResultDescriptor<AnalysisError> RESOLVE_TYPE_NAMES_ERRORS =
324 new ListResultDescriptor<AnalysisError>(
325 'RESOLVE_TYPE_NAMES_ERRORS', AnalysisError.NO_ERRORS);
326
327 /**
328 * The partially resolved [CompilationUnit] associated with a unit.
329 *
330 * All declarations bound to the element defined by the declaration.
331 *
332 * The result is only available for [LibrarySpecificUnit]s.
333 */
334 final ResultDescriptor<CompilationUnit> RESOLVED_UNIT1 =
335 new ResultDescriptor<CompilationUnit>('RESOLVED_UNIT1', null,
336 cachingPolicy: AST_CACHING_POLICY);
337
338 /**
339 * The partially resolved [CompilationUnit] associated with a unit.
340 *
341 * All the enum member elements are built.
342 *
343 * The result is only available for [LibrarySpecificUnit]s.
344 */
345 final ResultDescriptor<CompilationUnit> RESOLVED_UNIT2 =
346 new ResultDescriptor<CompilationUnit>('RESOLVED_UNIT2', null,
347 cachingPolicy: AST_CACHING_POLICY);
348
349 /**
350 * The partially resolved [CompilationUnit] associated with a unit.
351 *
352 * [RESOLVED_UNIT2] with resolved type names.
353 *
354 * The result is only available for [LibrarySpecificUnit]s.
355 */
356 final ResultDescriptor<CompilationUnit> RESOLVED_UNIT3 =
357 new ResultDescriptor<CompilationUnit>('RESOLVED_UNIT3', null,
358 cachingPolicy: AST_CACHING_POLICY);
359
360 /**
361 * The partially resolved [CompilationUnit] associated with a unit.
362 *
363 * [RESOLVED_UNIT3] plus resolved local variables and formal parameters.
364 *
365 * The result is only available for [LibrarySpecificUnit]s.
366 */
367 final ResultDescriptor<CompilationUnit> RESOLVED_UNIT4 =
368 new ResultDescriptor<CompilationUnit>('RESOLVED_UNIT4', null,
369 cachingPolicy: AST_CACHING_POLICY);
370
371 /**
372 * The resolved [CompilationUnit] associated with a compilation unit in which
373 * elements and types have been initially resolved outside of method bodies in
374 * addition to everything that is true of a [RESOLVED_UNIT4].
375 *
376 * The result is only available for [LibrarySpecificUnit]s.
377 */
378 final ResultDescriptor<CompilationUnit> RESOLVED_UNIT5 =
379 new ResultDescriptor<CompilationUnit>('RESOLVED_UNIT5', null,
380 cachingPolicy: AST_CACHING_POLICY);
381
382 /**
383 * The resolved [CompilationUnit] associated with a compilation unit in which
384 * the types of static variables have been inferred in addition to everything
385 * that is true of a [RESOLVED_UNIT5].
386 *
387 * The result is only available for [LibrarySpecificUnit]s.
388 */
389 final ResultDescriptor<CompilationUnit> RESOLVED_UNIT6 =
390 new ResultDescriptor<CompilationUnit>('RESOLVED_UNIT6', null,
391 cachingPolicy: AST_CACHING_POLICY);
392
393 /**
394 * The resolved [CompilationUnit] associated with a compilation unit in which
395 * the types of class members have been inferred in addition to everything that
396 * is true of a [RESOLVED_UNIT7].
397 *
398 * The result is only available for [LibrarySpecificUnit]s.
399 */
400 final ResultDescriptor<CompilationUnit> RESOLVED_UNIT7 =
401 new ResultDescriptor<CompilationUnit>('RESOLVED_UNIT7', null,
402 cachingPolicy: AST_CACHING_POLICY);
403
404 /**
405 * The resolved [CompilationUnit] associated with a compilation unit, with
406 * constants not yet resolved.
407 *
408 * The result is only available for [LibrarySpecificUnit]s.
409 */
410 final ResultDescriptor<CompilationUnit> RESOLVED_UNIT8 =
411 new ResultDescriptor<CompilationUnit>('RESOLVED_UNIT8', null,
412 cachingPolicy: AST_CACHING_POLICY);
413
414 /**
415 * The errors produced while scanning a compilation unit.
416 *
417 * The list will be empty if there were no errors, but will not be `null`.
418 *
419 * The result is only available for [Source]s representing a compilation unit.
420 */
421 final ListResultDescriptor<AnalysisError> SCAN_ERRORS =
422 new ListResultDescriptor<AnalysisError>(
423 'SCAN_ERRORS', AnalysisError.NO_ERRORS);
424
425 /**
426 * The [TypeProvider] of the [AnalysisContext].
427 */
428 final ResultDescriptor<TypeProvider> TYPE_PROVIDER =
429 new ResultDescriptor<TypeProvider>('TYPE_PROVIDER', null);
430
431 /**
432 * The [UsedImportedElements] of a [LibrarySpecificUnit].
433 */
434 final ResultDescriptor<UsedImportedElements> USED_IMPORTED_ELEMENTS =
435 new ResultDescriptor<UsedImportedElements>('USED_IMPORTED_ELEMENTS', null,
436 cachingPolicy: ELEMENT_CACHING_POLICY);
437
438 /**
439 * The [UsedLocalElements] of a [LibrarySpecificUnit].
440 */
441 final ResultDescriptor<UsedLocalElements> USED_LOCAL_ELEMENTS =
442 new ResultDescriptor<UsedLocalElements>('USED_LOCAL_ELEMENTS', null,
443 cachingPolicy: ELEMENT_CACHING_POLICY);
444
445 /**
446 * The errors produced while resolving variable references in a compilation unit .
447 *
448 * The list will be empty if there were no errors, but will not be `null`.
449 *
450 * The result is only available for [LibrarySpecificUnit]s.
451 */
452 final ListResultDescriptor<AnalysisError> VARIABLE_REFERENCE_ERRORS =
453 new ListResultDescriptor<AnalysisError>(
454 'VARIABLE_REFERENCE_ERRORS', AnalysisError.NO_ERRORS);
455
456 /**
457 * The errors produced while verifying a compilation unit.
458 *
459 * The list will be empty if there were no errors, but will not be `null`.
460 *
461 * The result is only available for [LibrarySpecificUnit]s.
462 */
463 final ListResultDescriptor<AnalysisError> VERIFY_ERRORS =
464 new ListResultDescriptor<AnalysisError>(
465 'VERIFY_ERRORS', AnalysisError.NO_ERRORS);
466
467 /**
468 * Return a list of errors containing the errors from the given [errors] list
469 * but with duplications removed.
470 */
471 List<AnalysisError> removeDuplicateErrors(List<AnalysisError> errors) {
472 if (errors.isEmpty) {
473 return errors;
474 }
475 return errors.toSet().toList();
476 }
477
478 /**
479 * A task that builds a compilation unit element for a single compilation unit.
480 */
481 class BuildCompilationUnitElementTask extends SourceBasedAnalysisTask {
482 /**
483 * The name of the input whose value is the AST for the compilation unit.
484 */
485 static const String PARSED_UNIT_INPUT_NAME = 'PARSED_UNIT_INPUT_NAME';
486
487 /**
488 * The task descriptor describing this kind of task.
489 */
490 static final TaskDescriptor DESCRIPTOR = new TaskDescriptor(
491 'BuildCompilationUnitElementTask',
492 createTask,
493 buildInputs, <ResultDescriptor>[
494 COMPILATION_UNIT_CONSTANTS,
495 COMPILATION_UNIT_ELEMENT,
496 RESOLVED_UNIT1
497 ]);
498
499 /**
500 * Initialize a newly created task to build a compilation unit element for
501 * the given [target] in the given [context].
502 */
503 BuildCompilationUnitElementTask(
504 InternalAnalysisContext context, AnalysisTarget target)
505 : super(context, target);
506
507 @override
508 TaskDescriptor get descriptor => DESCRIPTOR;
509
510 @override
511 void internalPerform() {
512 //
513 // Prepare inputs.
514 //
515 LibrarySpecificUnit librarySpecificUnit = target;
516 Source source = getRequiredSource();
517 CompilationUnit unit = getRequiredInput(PARSED_UNIT_INPUT_NAME);
518 //
519 // Build or reuse CompilationUnitElement.
520 //
521 unit = AstCloner.clone(unit);
522 AnalysisCache analysisCache =
523 (context as InternalAnalysisContext).analysisCache;
524 CompilationUnitElement element =
525 analysisCache.getValue(target, COMPILATION_UNIT_ELEMENT);
526 if (element == null) {
527 CompilationUnitBuilder builder = new CompilationUnitBuilder();
528 element = builder.buildCompilationUnit(
529 source, unit, librarySpecificUnit.library);
530 } else {
531 new DeclarationResolver().resolve(unit, element);
532 }
533 //
534 // Prepare constants.
535 //
536 ConstantFinder constantFinder =
537 new ConstantFinder(context, source, librarySpecificUnit.library);
538 unit.accept(constantFinder);
539 List<ConstantEvaluationTarget> constants = new List<
540 ConstantEvaluationTarget>.from(constantFinder.constantsToCompute);
541 //
542 // Record outputs.
543 //
544 outputs[COMPILATION_UNIT_CONSTANTS] = constants;
545 outputs[COMPILATION_UNIT_ELEMENT] = element;
546 outputs[RESOLVED_UNIT1] = unit;
547 }
548
549 /**
550 * Return a map from the names of the inputs of this kind of task to the task
551 * input descriptors describing those inputs for a task with the given
552 * [target].
553 */
554 static Map<String, TaskInput> buildInputs(AnalysisTarget target) {
555 LibrarySpecificUnit unit = target;
556 return <String, TaskInput>{
557 PARSED_UNIT_INPUT_NAME: PARSED_UNIT.of(unit.unit)
558 };
559 }
560
561 /**
562 * Create a [BuildCompilationUnitElementTask] based on the given [target] in
563 * the given [context].
564 */
565 static BuildCompilationUnitElementTask createTask(
566 AnalysisContext context, AnalysisTarget target) {
567 return new BuildCompilationUnitElementTask(context, target);
568 }
569 }
570
571 /**
572 * A task that builds imports and export directive elements for a library.
573 */
574 class BuildDirectiveElementsTask extends SourceBasedAnalysisTask {
575 /**
576 * The name of the input whose value is the defining [LIBRARY_ELEMENT1].
577 */
578 static const String LIBRARY_INPUT = 'LIBRARY_INPUT';
579
580 /**
581 * The name of the input for [RESOLVED_UNIT1] of a library unit.
582 */
583 static const String UNIT_INPUT_NAME = 'UNIT_INPUT_NAME';
584
585 /**
586 * The input with a list of [LIBRARY_ELEMENT3]s of imported libraries.
587 */
588 static const String IMPORTS_LIBRARY_ELEMENT_INPUT_NAME =
589 'IMPORTS_LIBRARY_ELEMENT1_INPUT_NAME';
590
591 /**
592 * The input with a list of [LIBRARY_ELEMENT3]s of exported libraries.
593 */
594 static const String EXPORTS_LIBRARY_ELEMENT_INPUT_NAME =
595 'EXPORTS_LIBRARY_ELEMENT_INPUT_NAME';
596
597 /**
598 * The input with a list of [SOURCE_KIND]s of imported libraries.
599 */
600 static const String IMPORTS_SOURCE_KIND_INPUT_NAME =
601 'IMPORTS_SOURCE_KIND_INPUT_NAME';
602
603 /**
604 * The input with a list of [SOURCE_KIND]s of exported libraries.
605 */
606 static const String EXPORTS_SOURCE_KIND_INPUT_NAME =
607 'EXPORTS_SOURCE_KIND_INPUT_NAME';
608
609 /**
610 * The task descriptor describing this kind of task.
611 */
612 static final TaskDescriptor DESCRIPTOR = new TaskDescriptor(
613 'BuildDirectiveElementsTask',
614 createTask,
615 buildInputs,
616 <ResultDescriptor>[LIBRARY_ELEMENT2, BUILD_DIRECTIVES_ERRORS]);
617
618 BuildDirectiveElementsTask(
619 InternalAnalysisContext context, AnalysisTarget target)
620 : super(context, target);
621
622 @override
623 TaskDescriptor get descriptor => DESCRIPTOR;
624
625 @override
626 void internalPerform() {
627 List<AnalysisError> errors = <AnalysisError>[];
628 //
629 // Prepare inputs.
630 //
631 LibraryElementImpl libraryElement = getRequiredInput(LIBRARY_INPUT);
632 CompilationUnit libraryUnit = getRequiredInput(UNIT_INPUT_NAME);
633 Map<Source, LibraryElement> importLibraryMap =
634 getRequiredInput(IMPORTS_LIBRARY_ELEMENT_INPUT_NAME);
635 Map<Source, LibraryElement> exportLibraryMap =
636 getRequiredInput(EXPORTS_LIBRARY_ELEMENT_INPUT_NAME);
637 Map<Source, SourceKind> importSourceKindMap =
638 getRequiredInput(IMPORTS_SOURCE_KIND_INPUT_NAME);
639 Map<Source, SourceKind> exportSourceKindMap =
640 getRequiredInput(EXPORTS_SOURCE_KIND_INPUT_NAME);
641 Source librarySource = libraryElement.source;
642 //
643 // Resolve directives.
644 //
645 HashMap<String, PrefixElementImpl> nameToPrefixMap =
646 new HashMap<String, PrefixElementImpl>();
647 List<ImportElement> imports = <ImportElement>[];
648 List<ExportElement> exports = <ExportElement>[];
649 bool explicitlyImportsCore = false;
650 for (Directive directive in libraryUnit.directives) {
651 if (directive is ImportDirective) {
652 ImportDirective importDirective = directive;
653 String uriContent = importDirective.uriContent;
654 if (DartUriResolver.isDartExtUri(uriContent)) {
655 libraryElement.hasExtUri = true;
656 }
657 Source importedSource = importDirective.source;
658 if (importedSource != null && context.exists(importedSource)) {
659 // The imported source will be null if the URI in the import
660 // directive was invalid.
661 LibraryElement importedLibrary = importLibraryMap[importedSource];
662 if (importedLibrary != null) {
663 if (importedLibrary.isDartCore) {
664 explicitlyImportsCore = true;
665 }
666 ImportElementImpl importElement =
667 new ImportElementImpl(directive.offset);
668 StringLiteral uriLiteral = importDirective.uri;
669 if (uriLiteral != null) {
670 importElement.uriOffset = uriLiteral.offset;
671 importElement.uriEnd = uriLiteral.end;
672 }
673 importElement.uri = uriContent;
674 importElement.deferred = importDirective.deferredKeyword != null;
675 importElement.combinators = _buildCombinators(importDirective);
676 importElement.importedLibrary = importedLibrary;
677 SimpleIdentifier prefixNode = directive.prefix;
678 if (prefixNode != null) {
679 importElement.prefixOffset = prefixNode.offset;
680 String prefixName = prefixNode.name;
681 PrefixElementImpl prefix = nameToPrefixMap[prefixName];
682 if (prefix == null) {
683 prefix = new PrefixElementImpl.forNode(prefixNode);
684 nameToPrefixMap[prefixName] = prefix;
685 }
686 importElement.prefix = prefix;
687 prefixNode.staticElement = prefix;
688 }
689 directive.element = importElement;
690 imports.add(importElement);
691 if (importSourceKindMap[importedSource] != SourceKind.LIBRARY) {
692 ErrorCode errorCode = (importElement.isDeferred
693 ? StaticWarningCode.IMPORT_OF_NON_LIBRARY
694 : CompileTimeErrorCode.IMPORT_OF_NON_LIBRARY);
695 errors.add(new AnalysisError(importedSource, uriLiteral.offset,
696 uriLiteral.length, errorCode, [uriLiteral.toSource()]));
697 }
698 }
699 }
700 } else if (directive is ExportDirective) {
701 ExportDirective exportDirective = directive;
702 Source exportedSource = exportDirective.source;
703 if (exportedSource != null && context.exists(exportedSource)) {
704 // The exported source will be null if the URI in the export
705 // directive was invalid.
706 LibraryElement exportedLibrary = exportLibraryMap[exportedSource];
707 if (exportedLibrary != null) {
708 ExportElementImpl exportElement =
709 new ExportElementImpl(directive.offset);
710 StringLiteral uriLiteral = exportDirective.uri;
711 if (uriLiteral != null) {
712 exportElement.uriOffset = uriLiteral.offset;
713 exportElement.uriEnd = uriLiteral.end;
714 }
715 exportElement.uri = exportDirective.uriContent;
716 exportElement.combinators = _buildCombinators(exportDirective);
717 exportElement.exportedLibrary = exportedLibrary;
718 directive.element = exportElement;
719 exports.add(exportElement);
720 if (exportSourceKindMap[exportedSource] != SourceKind.LIBRARY) {
721 errors.add(new AnalysisError(
722 exportedSource,
723 uriLiteral.offset,
724 uriLiteral.length,
725 CompileTimeErrorCode.EXPORT_OF_NON_LIBRARY,
726 [uriLiteral.toSource()]));
727 }
728 }
729 }
730 }
731 }
732 //
733 // Ensure "dart:core" import.
734 //
735 Source coreLibrarySource = context.sourceFactory.forUri(DartSdk.DART_CORE);
736 if (!explicitlyImportsCore && coreLibrarySource != librarySource) {
737 ImportElementImpl importElement = new ImportElementImpl(-1);
738 importElement.importedLibrary = importLibraryMap[coreLibrarySource];
739 importElement.synthetic = true;
740 imports.add(importElement);
741 }
742 //
743 // Populate the library element.
744 //
745 libraryElement.imports = imports;
746 libraryElement.exports = exports;
747 //
748 // Record outputs.
749 //
750 outputs[LIBRARY_ELEMENT2] = libraryElement;
751 outputs[BUILD_DIRECTIVES_ERRORS] = errors;
752 }
753
754 /**
755 * Return a map from the names of the inputs of this kind of task to the task
756 * input descriptors describing those inputs for a task with the
757 * given library [libSource].
758 */
759 static Map<String, TaskInput> buildInputs(AnalysisTarget target) {
760 Source source = target;
761 return <String, TaskInput>{
762 LIBRARY_INPUT: LIBRARY_ELEMENT1.of(source),
763 UNIT_INPUT_NAME:
764 RESOLVED_UNIT1.of(new LibrarySpecificUnit(source, source)),
765 IMPORTS_LIBRARY_ELEMENT_INPUT_NAME:
766 IMPORTED_LIBRARIES.of(source).toMapOf(LIBRARY_ELEMENT1),
767 EXPORTS_LIBRARY_ELEMENT_INPUT_NAME:
768 EXPORTED_LIBRARIES.of(source).toMapOf(LIBRARY_ELEMENT1),
769 IMPORTS_SOURCE_KIND_INPUT_NAME:
770 IMPORTED_LIBRARIES.of(source).toMapOf(SOURCE_KIND),
771 EXPORTS_SOURCE_KIND_INPUT_NAME:
772 EXPORTED_LIBRARIES.of(source).toMapOf(SOURCE_KIND)
773 };
774 }
775
776 /**
777 * Create a [BuildDirectiveElementsTask] based on the given [target] in
778 * the given [context].
779 */
780 static BuildDirectiveElementsTask createTask(
781 AnalysisContext context, AnalysisTarget target) {
782 return new BuildDirectiveElementsTask(context, target);
783 }
784
785 /**
786 * Build the element model representing the combinators declared by
787 * the given [directive].
788 */
789 static List<NamespaceCombinator> _buildCombinators(
790 NamespaceDirective directive) {
791 List<NamespaceCombinator> combinators = <NamespaceCombinator>[];
792 for (Combinator combinator in directive.combinators) {
793 if (combinator is ShowCombinator) {
794 ShowElementCombinatorImpl show = new ShowElementCombinatorImpl();
795 show.offset = combinator.offset;
796 show.end = combinator.end;
797 show.shownNames = _getIdentifiers(combinator.shownNames);
798 combinators.add(show);
799 } else if (combinator is HideCombinator) {
800 HideElementCombinatorImpl hide = new HideElementCombinatorImpl();
801 hide.hiddenNames = _getIdentifiers(combinator.hiddenNames);
802 combinators.add(hide);
803 }
804 }
805 return combinators;
806 }
807
808 /**
809 * Return the lexical identifiers associated with the given [identifiers].
810 */
811 static List<String> _getIdentifiers(NodeList<SimpleIdentifier> identifiers) {
812 return identifiers.map((identifier) => identifier.name).toList();
813 }
814 }
815
816 /**
817 * A task that builds the elements representing the members of enum
818 * declarations.
819 */
820 class BuildEnumMemberElementsTask extends SourceBasedAnalysisTask {
821 /**
822 * The name of the [TYPE_PROVIDER] input.
823 */
824 static const String TYPE_PROVIDER_INPUT = 'TYPE_PROVIDER_INPUT';
825
826 /**
827 * The name of the [RESOLVED_UNIT1] input.
828 */
829 static const String UNIT_INPUT = 'UNIT_INPUT';
830
831 /**
832 * The task descriptor describing this kind of task.
833 */
834 static final TaskDescriptor DESCRIPTOR = new TaskDescriptor(
835 'BuildEnumMemberElementsTask',
836 createTask,
837 buildInputs,
838 <ResultDescriptor>[RESOLVED_UNIT2]);
839
840 BuildEnumMemberElementsTask(
841 InternalAnalysisContext context, AnalysisTarget target)
842 : super(context, target);
843
844 @override
845 TaskDescriptor get descriptor => DESCRIPTOR;
846
847 @override
848 void internalPerform() {
849 //
850 // Prepare inputs.
851 //
852 TypeProvider typeProvider = getRequiredInput(TYPE_PROVIDER_INPUT);
853 CompilationUnit unit = getRequiredInput(UNIT_INPUT);
854 //
855 // Record outputs.
856 //
857 EnumMemberBuilder builder = new EnumMemberBuilder(typeProvider);
858 unit.accept(builder);
859 outputs[RESOLVED_UNIT2] = unit;
860 }
861
862 /**
863 * Return a map from the names of the inputs of this kind of task to the task
864 * input descriptors describing those inputs for a task with the
865 * given [target].
866 */
867 static Map<String, TaskInput> buildInputs(AnalysisTarget target) {
868 LibrarySpecificUnit unit = target;
869 return <String, TaskInput>{
870 TYPE_PROVIDER_INPUT: TYPE_PROVIDER.of(AnalysisContextTarget.request),
871 UNIT_INPUT: RESOLVED_UNIT1.of(unit)
872 };
873 }
874
875 /**
876 * Create a [BuildEnumMemberElementsTask] based on the given [target] in
877 * the given [context].
878 */
879 static BuildEnumMemberElementsTask createTask(
880 AnalysisContext context, AnalysisTarget target) {
881 return new BuildEnumMemberElementsTask(context, target);
882 }
883 }
884
885 /**
886 * A task that builds [EXPORT_NAMESPACE] and [LIBRARY_ELEMENT4] for a library.
887 */
888 class BuildExportNamespaceTask extends SourceBasedAnalysisTask {
889 /**
890 * The name of the input for [LIBRARY_ELEMENT3] of a library.
891 */
892 static const String LIBRARY_INPUT = 'LIBRARY_INPUT';
893
894 /**
895 * The task descriptor describing this kind of task.
896 */
897 static final TaskDescriptor DESCRIPTOR = new TaskDescriptor(
898 'BuildExportNamespaceTask',
899 createTask,
900 buildInputs,
901 <ResultDescriptor>[LIBRARY_ELEMENT4]);
902
903 BuildExportNamespaceTask(
904 InternalAnalysisContext context, AnalysisTarget target)
905 : super(context, target);
906
907 @override
908 TaskDescriptor get descriptor => DESCRIPTOR;
909
910 @override
911 void internalPerform() {
912 LibraryElementImpl library = getRequiredInput(LIBRARY_INPUT);
913 //
914 // Compute export namespace.
915 //
916 ExportNamespaceBuilder builder = new ExportNamespaceBuilder();
917 Namespace namespace = builder.build(library);
918 library.exportNamespace = namespace;
919 //
920 // Update entry point.
921 //
922 if (library.entryPoint == null) {
923 Iterable<Element> exportedElements = namespace.definedNames.values;
924 library.entryPoint = exportedElements.firstWhere(
925 (element) => element is FunctionElement && element.isEntryPoint,
926 orElse: () => null);
927 }
928 //
929 // Record outputs.
930 //
931 outputs[LIBRARY_ELEMENT4] = library;
932 }
933
934 /**
935 * Return a map from the names of the inputs of this kind of task to the task
936 * input descriptors describing those inputs for a task with the
937 * given library [libSource].
938 */
939 static Map<String, TaskInput> buildInputs(AnalysisTarget target) {
940 Source source = target;
941 return <String, TaskInput>{
942 LIBRARY_INPUT: LIBRARY_ELEMENT3.of(source),
943 'exportsLibraryPublicNamespace':
944 EXPORT_SOURCE_CLOSURE.of(source).toMapOf(LIBRARY_ELEMENT3)
945 };
946 }
947
948 /**
949 * Create a [BuildExportNamespaceTask] based on the given [target] in
950 * the given [context].
951 */
952 static BuildExportNamespaceTask createTask(
953 AnalysisContext context, AnalysisTarget target) {
954 return new BuildExportNamespaceTask(context, target);
955 }
956 }
957
958 /**
959 * A task that builds a library element for a Dart library.
960 */
961 class BuildLibraryElementTask extends SourceBasedAnalysisTask {
962 /**
963 * The name of the input whose value is the defining [RESOLVED_UNIT1].
964 */
965 static const String DEFINING_UNIT_INPUT = 'DEFINING_UNIT_INPUT';
966
967 /**
968 * The name of the input whose value is a list of built [RESOLVED_UNIT1]s
969 * of the parts sourced by a library.
970 */
971 static const String PARTS_UNIT_INPUT = 'PARTS_UNIT_INPUT';
972
973 /**
974 * The task descriptor describing this kind of task.
975 */
976 static final TaskDescriptor DESCRIPTOR = new TaskDescriptor(
977 'BuildLibraryElementTask', createTask, buildInputs, <ResultDescriptor>[
978 BUILD_LIBRARY_ERRORS,
979 LIBRARY_ELEMENT1,
980 IS_LAUNCHABLE
981 ]);
982
983 /**
984 * The constant used as an unknown common library name in parts.
985 */
986 static const String _UNKNOWN_LIBRARY_NAME = 'unknown-library-name';
987
988 /**
989 * Initialize a newly created task to build a library element for the given
990 * [target] in the given [context].
991 */
992 BuildLibraryElementTask(
993 InternalAnalysisContext context, AnalysisTarget target)
994 : super(context, target);
995
996 @override
997 TaskDescriptor get descriptor => DESCRIPTOR;
998
999 @override
1000 void internalPerform() {
1001 List<AnalysisError> errors = <AnalysisError>[];
1002 //
1003 // Prepare inputs.
1004 //
1005 Source librarySource = getRequiredSource();
1006 CompilationUnit definingCompilationUnit =
1007 getRequiredInput(DEFINING_UNIT_INPUT);
1008 List<CompilationUnit> partUnits = getRequiredInput(PARTS_UNIT_INPUT);
1009 //
1010 // Process inputs.
1011 //
1012 CompilationUnitElementImpl definingCompilationUnitElement =
1013 definingCompilationUnit.element;
1014 Map<Source, CompilationUnit> partUnitMap =
1015 new HashMap<Source, CompilationUnit>();
1016 for (CompilationUnit partUnit in partUnits) {
1017 Source partSource = partUnit.element.source;
1018 partUnitMap[partSource] = partUnit;
1019 }
1020 //
1021 // Update "part" directives.
1022 //
1023 LibraryIdentifier libraryNameNode = null;
1024 String partsLibraryName = _UNKNOWN_LIBRARY_NAME;
1025 bool hasPartDirective = false;
1026 FunctionElement entryPoint =
1027 _findEntryPoint(definingCompilationUnitElement);
1028 List<Directive> directivesToResolve = <Directive>[];
1029 List<CompilationUnitElementImpl> sourcedCompilationUnits =
1030 <CompilationUnitElementImpl>[];
1031 for (Directive directive in definingCompilationUnit.directives) {
1032 if (directive is LibraryDirective) {
1033 if (libraryNameNode == null) {
1034 libraryNameNode = directive.name;
1035 directivesToResolve.add(directive);
1036 }
1037 } else if (directive is PartDirective) {
1038 PartDirective partDirective = directive;
1039 StringLiteral partUri = partDirective.uri;
1040 Source partSource = partDirective.source;
1041 hasPartDirective = true;
1042 CompilationUnit partUnit = partUnitMap[partSource];
1043 if (partUnit != null) {
1044 CompilationUnitElementImpl partElement = partUnit.element;
1045 partElement.uriOffset = partUri.offset;
1046 partElement.uriEnd = partUri.end;
1047 partElement.uri = partDirective.uriContent;
1048 //
1049 // Validate that the part contains a part-of directive with the same
1050 // name as the library.
1051 //
1052 if (context.exists(partSource)) {
1053 String partLibraryName =
1054 _getPartLibraryName(partSource, partUnit, directivesToResolve);
1055 if (partLibraryName == null) {
1056 errors.add(new AnalysisError(
1057 librarySource,
1058 partUri.offset,
1059 partUri.length,
1060 CompileTimeErrorCode.PART_OF_NON_PART,
1061 [partUri.toSource()]));
1062 } else if (libraryNameNode == null) {
1063 if (partsLibraryName == _UNKNOWN_LIBRARY_NAME) {
1064 partsLibraryName = partLibraryName;
1065 } else if (partsLibraryName != partLibraryName) {
1066 partsLibraryName = null;
1067 }
1068 } else if (libraryNameNode.name != partLibraryName) {
1069 errors.add(new AnalysisError(
1070 librarySource,
1071 partUri.offset,
1072 partUri.length,
1073 StaticWarningCode.PART_OF_DIFFERENT_LIBRARY,
1074 [libraryNameNode.name, partLibraryName]));
1075 }
1076 }
1077 if (entryPoint == null) {
1078 entryPoint = _findEntryPoint(partElement);
1079 }
1080 directive.element = partElement;
1081 sourcedCompilationUnits.add(partElement);
1082 }
1083 }
1084 }
1085 if (hasPartDirective && libraryNameNode == null) {
1086 AnalysisError error;
1087 if (partsLibraryName != _UNKNOWN_LIBRARY_NAME &&
1088 partsLibraryName != null) {
1089 error = new AnalysisErrorWithProperties(librarySource, 0, 0,
1090 ResolverErrorCode.MISSING_LIBRARY_DIRECTIVE_WITH_PART)
1091 ..setProperty(ErrorProperty.PARTS_LIBRARY_NAME, partsLibraryName);
1092 } else {
1093 error = new AnalysisError(librarySource, 0, 0,
1094 ResolverErrorCode.MISSING_LIBRARY_DIRECTIVE_WITH_PART);
1095 }
1096 errors.add(error);
1097 }
1098 //
1099 // Create and populate the library element.
1100 //
1101 AnalysisContext owningContext = context;
1102 if (context is InternalAnalysisContext) {
1103 InternalAnalysisContext internalContext = context;
1104 owningContext = internalContext.getContextFor(librarySource);
1105 }
1106 LibraryElementImpl libraryElement =
1107 new LibraryElementImpl.forNode(owningContext, libraryNameNode);
1108 libraryElement.definingCompilationUnit = definingCompilationUnitElement;
1109 libraryElement.entryPoint = entryPoint;
1110 libraryElement.parts = sourcedCompilationUnits;
1111 for (Directive directive in directivesToResolve) {
1112 directive.element = libraryElement;
1113 }
1114 if (sourcedCompilationUnits.isNotEmpty) {
1115 _patchTopLevelAccessors(libraryElement);
1116 }
1117 //
1118 // Record outputs.
1119 //
1120 outputs[BUILD_LIBRARY_ERRORS] = errors;
1121 outputs[LIBRARY_ELEMENT1] = libraryElement;
1122 outputs[IS_LAUNCHABLE] = entryPoint != null;
1123 }
1124
1125 /**
1126 * Add all of the non-synthetic [getters] and [setters] defined in the given
1127 * [unit] that have no corresponding accessor to one of the given collections.
1128 */
1129 void _collectAccessors(Map<String, PropertyAccessorElement> getters,
1130 List<PropertyAccessorElement> setters, CompilationUnitElement unit) {
1131 for (PropertyAccessorElement accessor in unit.accessors) {
1132 if (accessor.isGetter) {
1133 if (!accessor.isSynthetic && accessor.correspondingSetter == null) {
1134 getters[accessor.displayName] = accessor;
1135 }
1136 } else {
1137 if (!accessor.isSynthetic && accessor.correspondingGetter == null) {
1138 setters.add(accessor);
1139 }
1140 }
1141 }
1142 }
1143
1144 /**
1145 * Return the top-level [FunctionElement] entry point, or `null` if the given
1146 * [element] does not define an entry point.
1147 */
1148 FunctionElement _findEntryPoint(CompilationUnitElementImpl element) {
1149 for (FunctionElement function in element.functions) {
1150 if (function.isEntryPoint) {
1151 return function;
1152 }
1153 }
1154 return null;
1155 }
1156
1157 /**
1158 * Return the name of the library that the given part is declared to be a
1159 * part of, or `null` if the part does not contain a part-of directive.
1160 */
1161 String _getPartLibraryName(Source partSource, CompilationUnit partUnit,
1162 List<Directive> directivesToResolve) {
1163 for (Directive directive in partUnit.directives) {
1164 if (directive is PartOfDirective) {
1165 directivesToResolve.add(directive);
1166 LibraryIdentifier libraryName = directive.libraryName;
1167 if (libraryName != null) {
1168 return libraryName.name;
1169 }
1170 }
1171 }
1172 return null;
1173 }
1174
1175 /**
1176 * Look through all of the compilation units defined for the given [library],
1177 * looking for getters and setters that are defined in different compilation
1178 * units but that have the same names. If any are found, make sure that they
1179 * have the same variable element.
1180 */
1181 void _patchTopLevelAccessors(LibraryElementImpl library) {
1182 HashMap<String, PropertyAccessorElement> getters =
1183 new HashMap<String, PropertyAccessorElement>();
1184 List<PropertyAccessorElement> setters = <PropertyAccessorElement>[];
1185 _collectAccessors(getters, setters, library.definingCompilationUnit);
1186 for (CompilationUnitElement unit in library.parts) {
1187 _collectAccessors(getters, setters, unit);
1188 }
1189 for (PropertyAccessorElement setter in setters) {
1190 PropertyAccessorElement getter = getters[setter.displayName];
1191 if (getter != null) {
1192 TopLevelVariableElementImpl variable = getter.variable;
1193 TopLevelVariableElementImpl setterVariable = setter.variable;
1194 CompilationUnitElementImpl setterUnit = setterVariable.enclosingElement;
1195 setterUnit.replaceTopLevelVariable(setterVariable, variable);
1196 variable.setter = setter;
1197 (setter as PropertyAccessorElementImpl).variable = variable;
1198 }
1199 }
1200 }
1201
1202 /**
1203 * Return a map from the names of the inputs of this kind of task to the task
1204 * input descriptors describing those inputs for a task with the given
1205 * [libSource].
1206 */
1207 static Map<String, TaskInput> buildInputs(AnalysisTarget target) {
1208 Source source = target;
1209 return <String, TaskInput>{
1210 DEFINING_UNIT_INPUT:
1211 RESOLVED_UNIT1.of(new LibrarySpecificUnit(source, source)),
1212 PARTS_UNIT_INPUT: INCLUDED_PARTS.of(source).toList((Source unit) {
1213 return RESOLVED_UNIT1.of(new LibrarySpecificUnit(source, unit));
1214 })
1215 };
1216 }
1217
1218 /**
1219 * Create a [BuildLibraryElementTask] based on the given [target] in the
1220 * given [context].
1221 */
1222 static BuildLibraryElementTask createTask(
1223 AnalysisContext context, AnalysisTarget target) {
1224 return new BuildLibraryElementTask(context, target);
1225 }
1226 }
1227
1228 /**
1229 * A task that builds [PUBLIC_NAMESPACE] for a library.
1230 */
1231 class BuildPublicNamespaceTask extends SourceBasedAnalysisTask {
1232 /**
1233 * The name of the input for [LIBRARY_ELEMENT2] of a library.
1234 */
1235 static const String LIBRARY_INPUT = 'LIBRARY_INPUT';
1236
1237 /**
1238 * The task descriptor describing this kind of task.
1239 */
1240 static final TaskDescriptor DESCRIPTOR = new TaskDescriptor(
1241 'BuildPublicNamespaceTask',
1242 createTask,
1243 buildInputs,
1244 <ResultDescriptor>[LIBRARY_ELEMENT3]);
1245
1246 BuildPublicNamespaceTask(
1247 InternalAnalysisContext context, AnalysisTarget target)
1248 : super(context, target);
1249
1250 @override
1251 TaskDescriptor get descriptor => DESCRIPTOR;
1252
1253 @override
1254 void internalPerform() {
1255 LibraryElementImpl library = getRequiredInput(LIBRARY_INPUT);
1256 library.publicNamespace = new PublicNamespaceBuilder().build(library);
1257 outputs[LIBRARY_ELEMENT3] = library;
1258 }
1259
1260 /**
1261 * Return a map from the names of the inputs of this kind of task to the task
1262 * input descriptors describing those inputs for a task with the
1263 * given library [libSource].
1264 */
1265 static Map<String, TaskInput> buildInputs(AnalysisTarget target) {
1266 Source source = target;
1267 return <String, TaskInput>{LIBRARY_INPUT: LIBRARY_ELEMENT2.of(source)};
1268 }
1269
1270 /**
1271 * Create a [BuildPublicNamespaceTask] based on the given [target] in
1272 * the given [context].
1273 */
1274 static BuildPublicNamespaceTask createTask(
1275 AnalysisContext context, AnalysisTarget target) {
1276 return new BuildPublicNamespaceTask(context, target);
1277 }
1278 }
1279
1280 /**
1281 * A task that builds [EXPORT_SOURCE_CLOSURE] of a library.
1282 */
1283 class BuildSourceExportClosureTask extends SourceBasedAnalysisTask {
1284 /**
1285 * The name of the export closure.
1286 */
1287 static const String EXPORT_INPUT = 'EXPORT_INPUT';
1288
1289 /**
1290 * The task descriptor describing this kind of task.
1291 */
1292 static final TaskDescriptor DESCRIPTOR = new TaskDescriptor(
1293 'BuildSourceExportClosureTask',
1294 createTask,
1295 buildInputs,
1296 <ResultDescriptor>[EXPORT_SOURCE_CLOSURE]);
1297
1298 BuildSourceExportClosureTask(
1299 InternalAnalysisContext context, AnalysisTarget target)
1300 : super(context, target);
1301
1302 @override
1303 TaskDescriptor get descriptor => DESCRIPTOR;
1304
1305 @override
1306 void internalPerform() {
1307 List<Source> exportClosure = getRequiredInput(EXPORT_INPUT);
1308 //
1309 // Record output.
1310 //
1311 outputs[EXPORT_SOURCE_CLOSURE] = exportClosure;
1312 }
1313
1314 /**
1315 * Return a map from the names of the inputs of this kind of task to the task
1316 * input descriptors describing those inputs for a task with the
1317 * given library [libSource].
1318 */
1319 static Map<String, TaskInput> buildInputs(AnalysisTarget target) {
1320 Source source = target;
1321 return <String, TaskInput>{
1322 EXPORT_INPUT: new _ExportSourceClosureTaskInput(source, LIBRARY_ELEMENT2)
1323 };
1324 }
1325
1326 /**
1327 * Create a [BuildSourceExportClosureTask] based on the given [target] in
1328 * the given [context].
1329 */
1330 static BuildSourceExportClosureTask createTask(
1331 AnalysisContext context, AnalysisTarget target) {
1332 return new BuildSourceExportClosureTask(context, target);
1333 }
1334 }
1335
1336 /**
1337 * A task that builds [IMPORT_EXPORT_SOURCE_CLOSURE] of a library, and also
1338 * sets [IS_CLIENT].
1339 */
1340 class BuildSourceImportExportClosureTask extends SourceBasedAnalysisTask {
1341 /**
1342 * The name of the import/export closure.
1343 */
1344 static const String IMPORT_EXPORT_INPUT = 'IMPORT_EXPORT_INPUT';
1345
1346 /**
1347 * The task descriptor describing this kind of task.
1348 */
1349 static final TaskDescriptor DESCRIPTOR = new TaskDescriptor(
1350 'BuildSourceImportExportClosureTask',
1351 createTask,
1352 buildInputs,
1353 <ResultDescriptor>[IMPORT_EXPORT_SOURCE_CLOSURE, IS_CLIENT]);
1354
1355 BuildSourceImportExportClosureTask(
1356 InternalAnalysisContext context, AnalysisTarget target)
1357 : super(context, target);
1358
1359 @override
1360 TaskDescriptor get descriptor => DESCRIPTOR;
1361
1362 @override
1363 void internalPerform() {
1364 List<Source> importExportClosure = getRequiredInput(IMPORT_EXPORT_INPUT);
1365 Source htmlSource = context.sourceFactory.forUri(DartSdk.DART_HTML);
1366 //
1367 // Record outputs.
1368 //
1369 outputs[IMPORT_EXPORT_SOURCE_CLOSURE] = importExportClosure;
1370 outputs[IS_CLIENT] = importExportClosure.contains(htmlSource);
1371 }
1372
1373 /**
1374 * Return a map from the names of the inputs of this kind of task to the task
1375 * input descriptors describing those inputs for a task with the
1376 * given library [libSource].
1377 */
1378 static Map<String, TaskInput> buildInputs(AnalysisTarget target) {
1379 Source source = target;
1380 return <String, TaskInput>{
1381 IMPORT_EXPORT_INPUT:
1382 new _ImportExportSourceClosureTaskInput(source, LIBRARY_ELEMENT2)
1383 };
1384 }
1385
1386 /**
1387 * Create a [BuildSourceImportExportClosureTask] based on the given [target]
1388 * in the given [context].
1389 */
1390 static BuildSourceImportExportClosureTask createTask(
1391 AnalysisContext context, AnalysisTarget target) {
1392 return new BuildSourceImportExportClosureTask(context, target);
1393 }
1394 }
1395
1396 /**
1397 * A task that builds [TYPE_PROVIDER] for a context.
1398 */
1399 class BuildTypeProviderTask extends SourceBasedAnalysisTask {
1400 /**
1401 * The [PUBLIC_NAMESPACE] input of the `dart:core` library.
1402 */
1403 static const String CORE_INPUT = 'CORE_INPUT';
1404
1405 /**
1406 * The [PUBLIC_NAMESPACE] input of the `dart:async` library.
1407 */
1408 static const String ASYNC_INPUT = 'ASYNC_INPUT';
1409
1410 /**
1411 * The task descriptor describing this kind of task.
1412 */
1413 static final TaskDescriptor DESCRIPTOR = new TaskDescriptor(
1414 'BuildTypeProviderTask',
1415 createTask,
1416 buildInputs,
1417 <ResultDescriptor>[TYPE_PROVIDER]);
1418
1419 BuildTypeProviderTask(
1420 InternalAnalysisContext context, AnalysisContextTarget target)
1421 : super(context, target);
1422
1423 @override
1424 TaskDescriptor get descriptor => DESCRIPTOR;
1425
1426 @override
1427 void internalPerform() {
1428 LibraryElement coreLibrary = getRequiredInput(CORE_INPUT);
1429 LibraryElement asyncLibrary = getRequiredInput(ASYNC_INPUT);
1430 Namespace coreNamespace = coreLibrary.publicNamespace;
1431 Namespace asyncNamespace = asyncLibrary.publicNamespace;
1432 //
1433 // Record outputs.
1434 //
1435 TypeProvider typeProvider =
1436 new TypeProviderImpl.forNamespaces(coreNamespace, asyncNamespace);
1437 (context as InternalAnalysisContext).typeProvider = typeProvider;
1438 outputs[TYPE_PROVIDER] = typeProvider;
1439 }
1440
1441 static Map<String, TaskInput> buildInputs(AnalysisTarget target) {
1442 AnalysisContextTarget contextTarget = target;
1443 SourceFactory sourceFactory = contextTarget.context.sourceFactory;
1444 Source coreSource = sourceFactory.forUri(DartSdk.DART_CORE);
1445 Source asyncSource = sourceFactory.forUri(DartSdk.DART_ASYNC);
1446 return <String, TaskInput>{
1447 CORE_INPUT: LIBRARY_ELEMENT3.of(coreSource),
1448 ASYNC_INPUT: LIBRARY_ELEMENT3.of(asyncSource)
1449 };
1450 }
1451
1452 /**
1453 * Create a [BuildTypeProviderTask] based on the given [context].
1454 */
1455 static BuildTypeProviderTask createTask(
1456 AnalysisContext context, AnalysisTarget target) {
1457 return new BuildTypeProviderTask(context, target);
1458 }
1459 }
1460
1461 /**
1462 * A task that computes [CONSTANT_DEPENDENCIES] for a constant.
1463 */
1464 class ComputeConstantDependenciesTask extends ConstantEvaluationAnalysisTask {
1465 /**
1466 * The name of the [RESOLVED_UNIT8] input.
1467 */
1468 static const String UNIT_INPUT = 'UNIT_INPUT';
1469
1470 /**
1471 * The name of the [TYPE_PROVIDER] input.
1472 */
1473 static const String TYPE_PROVIDER_INPUT = 'TYPE_PROVIDER_INPUT';
1474
1475 static final TaskDescriptor DESCRIPTOR = new TaskDescriptor(
1476 'ComputeConstantDependenciesTask',
1477 createTask,
1478 buildInputs,
1479 <ResultDescriptor>[CONSTANT_DEPENDENCIES]);
1480
1481 ComputeConstantDependenciesTask(
1482 InternalAnalysisContext context, ConstantEvaluationTarget constant)
1483 : super(context, constant);
1484
1485 @override
1486 TaskDescriptor get descriptor => DESCRIPTOR;
1487
1488 @override
1489 void internalPerform() {
1490 //
1491 // Prepare inputs.
1492 //
1493 // Note: UNIT_INPUT is not needed. It is merely a bookkeeping dependency
1494 // to ensure that resolution has occurred before we attempt to determine
1495 // constant dependencies.
1496 //
1497 ConstantEvaluationTarget constant = target;
1498 TypeProvider typeProvider = getRequiredInput(TYPE_PROVIDER_INPUT);
1499 //
1500 // Compute dependencies.
1501 //
1502 List<ConstantEvaluationTarget> dependencies = <ConstantEvaluationTarget>[];
1503 new ConstantEvaluationEngine(typeProvider, context.declaredVariables)
1504 .computeDependencies(constant, dependencies.add);
1505 //
1506 // Record outputs.
1507 //
1508 outputs[CONSTANT_DEPENDENCIES] = dependencies;
1509 }
1510
1511 /**
1512 * Return a map from the names of the inputs of this kind of task to the task
1513 * input descriptors describing those inputs for a task with the
1514 * given [target].
1515 */
1516 static Map<String, TaskInput> buildInputs(AnalysisTarget target) {
1517 if (target is Element) {
1518 CompilationUnitElementImpl unit = target
1519 .getAncestor((Element element) => element is CompilationUnitElement);
1520 return <String, TaskInput>{
1521 UNIT_INPUT: RESOLVED_UNIT8
1522 .of(new LibrarySpecificUnit(unit.librarySource, target.source)),
1523 TYPE_PROVIDER_INPUT: TYPE_PROVIDER.of(AnalysisContextTarget.request)
1524 };
1525 } else if (target is ConstantEvaluationTarget_Annotation) {
1526 return <String, TaskInput>{
1527 UNIT_INPUT: RESOLVED_UNIT8
1528 .of(new LibrarySpecificUnit(target.librarySource, target.source)),
1529 TYPE_PROVIDER_INPUT: TYPE_PROVIDER.of(AnalysisContextTarget.request)
1530 };
1531 }
1532 throw new AnalysisException(
1533 'Cannot build inputs for a ${target.runtimeType}');
1534 }
1535
1536 /**
1537 * Create a [ComputeConstantDependenciesTask] based on the given [target] in
1538 * the given [context].
1539 */
1540 static ComputeConstantDependenciesTask createTask(
1541 AnalysisContext context, AnalysisTarget target) {
1542 return new ComputeConstantDependenciesTask(context, target);
1543 }
1544 }
1545
1546 /**
1547 * A task that computes the value of a constant ([CONSTANT_VALUE]) and
1548 * stores it in the element model.
1549 */
1550 class ComputeConstantValueTask extends ConstantEvaluationAnalysisTask {
1551 /**
1552 * The name of the input which ensures that dependent constants are evaluated
1553 * before the target.
1554 */
1555 static const String DEPENDENCIES_INPUT = 'DEPENDENCIES_INPUT';
1556
1557 /**
1558 * The name of the [TYPE_PROVIDER] input.
1559 */
1560 static const String TYPE_PROVIDER_INPUT = 'TYPE_PROVIDER_INPUT';
1561
1562 static final TaskDescriptor DESCRIPTOR = new TaskDescriptor(
1563 'ComputeConstantValueTask',
1564 createTask,
1565 buildInputs,
1566 <ResultDescriptor>[CONSTANT_VALUE]);
1567
1568 ComputeConstantValueTask(
1569 InternalAnalysisContext context, ConstantEvaluationTarget constant)
1570 : super(context, constant);
1571
1572 @override
1573 TaskDescriptor get descriptor => DESCRIPTOR;
1574
1575 @override
1576 bool get handlesDependencyCycles => true;
1577
1578 @override
1579 void internalPerform() {
1580 //
1581 // Prepare inputs.
1582 //
1583 // Note: DEPENDENCIES_INPUT is not needed. It is merely a bookkeeping
1584 // dependency to ensure that the constants that this constant depends on
1585 // are computed first.
1586 ConstantEvaluationTarget constant = target;
1587 AnalysisContext context = constant.context;
1588 TypeProvider typeProvider = getRequiredInput(TYPE_PROVIDER_INPUT);
1589 //
1590 // Compute the value of the constant, or report an error if there was a
1591 // cycle.
1592 //
1593 ConstantEvaluationEngine constantEvaluationEngine =
1594 new ConstantEvaluationEngine(typeProvider, context.declaredVariables);
1595 if (dependencyCycle == null) {
1596 constantEvaluationEngine.computeConstantValue(constant);
1597 } else {
1598 List<ConstantEvaluationTarget> constantsInCycle =
1599 <ConstantEvaluationTarget>[];
1600 for (WorkItem workItem in dependencyCycle) {
1601 if (workItem.descriptor == DESCRIPTOR) {
1602 constantsInCycle.add(workItem.target);
1603 }
1604 }
1605 assert(constantsInCycle.isNotEmpty);
1606 constantEvaluationEngine.generateCycleError(constantsInCycle, constant);
1607 }
1608 //
1609 // Record outputs.
1610 //
1611 outputs[CONSTANT_VALUE] = constant;
1612 }
1613
1614 /**
1615 * Return a map from the names of the inputs of this kind of task to the task
1616 * input descriptors describing those inputs for a task with the given
1617 * [target].
1618 */
1619 static Map<String, TaskInput> buildInputs(AnalysisTarget target) {
1620 ConstantEvaluationTarget evaluationTarget = target;
1621 return <String, TaskInput>{
1622 DEPENDENCIES_INPUT:
1623 CONSTANT_DEPENDENCIES.of(evaluationTarget).toListOf(CONSTANT_VALUE),
1624 TYPE_PROVIDER_INPUT: TYPE_PROVIDER.of(AnalysisContextTarget.request)
1625 };
1626 }
1627
1628 /**
1629 * Create a [ComputeConstantValueTask] based on the given [target] in the
1630 * given [context].
1631 */
1632 static ComputeConstantValueTask createTask(
1633 AnalysisContext context, AnalysisTarget target) {
1634 return new ComputeConstantValueTask(context, target);
1635 }
1636 }
1637
1638 /**
1639 * A task that computes the [INFERABLE_STATIC_VARIABLE_DEPENDENCIES] for a
1640 * static variable whose type should be inferred.
1641 */
1642 class ComputeInferableStaticVariableDependenciesTask
1643 extends ConstantEvaluationAnalysisTask {
1644 /**
1645 * The name of the [RESOLVED_UNIT5] input.
1646 */
1647 static const String UNIT_INPUT = 'UNIT_INPUT';
1648
1649 static final TaskDescriptor DESCRIPTOR = new TaskDescriptor(
1650 'ComputeInferableStaticVariableDependenciesTask',
1651 createTask,
1652 buildInputs,
1653 <ResultDescriptor>[INFERABLE_STATIC_VARIABLE_DEPENDENCIES]);
1654
1655 ComputeInferableStaticVariableDependenciesTask(
1656 InternalAnalysisContext context, VariableElement variable)
1657 : super(context, variable);
1658
1659 @override
1660 TaskDescriptor get descriptor => DESCRIPTOR;
1661
1662 @override
1663 void internalPerform() {
1664 //
1665 // Prepare inputs.
1666 //
1667 VariableElement variable = target;
1668 CompilationUnit unit = getRequiredInput(UNIT_INPUT);
1669 //
1670 // Compute dependencies.
1671 //
1672 NodeLocator locator = new NodeLocator(variable.nameOffset);
1673 AstNode node = locator.searchWithin(unit);
1674 VariableDeclaration declaration =
1675 node.getAncestor((AstNode ancestor) => ancestor is VariableDeclaration);
1676 if (declaration == null || declaration.name != node) {
1677 throw new AnalysisException(
1678 "NodeLocator failed to find a variable's declaration");
1679 }
1680 VariableGatherer gatherer = new VariableGatherer(_isInferableStatic);
1681 declaration.initializer.accept(gatherer);
1682 //
1683 // Record outputs.
1684 //
1685 outputs[INFERABLE_STATIC_VARIABLE_DEPENDENCIES] = gatherer.results.toList();
1686 }
1687
1688 /**
1689 * Return `true` if the given [variable] is a static variable whose type
1690 * should be inferred.
1691 */
1692 bool _isInferableStatic(VariableElement variable) => variable.isStatic &&
1693 variable.hasImplicitType &&
1694 variable.initializer != null;
1695
1696 /**
1697 * Return a map from the names of the inputs of this kind of task to the task
1698 * input descriptors describing those inputs for a task with the
1699 * given [target].
1700 */
1701 static Map<String, TaskInput> buildInputs(AnalysisTarget target) {
1702 if (target is VariableElement) {
1703 CompilationUnitElementImpl unit = target
1704 .getAncestor((Element element) => element is CompilationUnitElement);
1705 return <String, TaskInput>{
1706 UNIT_INPUT: RESOLVED_UNIT5
1707 .of(new LibrarySpecificUnit(unit.librarySource, unit.source))
1708 };
1709 }
1710 throw new AnalysisException(
1711 'Cannot build inputs for a ${target.runtimeType}');
1712 }
1713
1714 /**
1715 * Create a [ComputeInferableStaticVariableDependenciesTask] based on the
1716 * given [target] in the given [context].
1717 */
1718 static ComputeInferableStaticVariableDependenciesTask createTask(
1719 AnalysisContext context, AnalysisTarget target) {
1720 return new ComputeInferableStaticVariableDependenciesTask(context, target);
1721 }
1722 }
1723
1724 /**
1725 * A base class for analysis tasks whose target is expected to be a
1726 * [ConstantEvaluationTarget].
1727 */
1728 abstract class ConstantEvaluationAnalysisTask extends AnalysisTask {
1729 /**
1730 * Initialize a newly created task to perform analysis within the given
1731 * [context] in order to produce results for the given [constant].
1732 */
1733 ConstantEvaluationAnalysisTask(
1734 AnalysisContext context, ConstantEvaluationTarget constant)
1735 : super(context, constant);
1736
1737 @override
1738 String get description {
1739 Source source = target.source;
1740 String sourceName = source == null ? '<unknown source>' : source.fullName;
1741 return '${descriptor.name} for element $target in source $sourceName';
1742 }
1743 }
1744
1745 /**
1746 * Interface for [AnalysisTarget]s for which constant evaluation can be
1747 * performed.
1748 */
1749 abstract class ConstantEvaluationTarget extends AnalysisTarget {
1750 /**
1751 * Return the [AnalysisContext] which should be used to evaluate this
1752 * constant.
1753 */
1754 AnalysisContext get context;
1755 }
1756
1757 /**
1758 * A task that computes a list of the libraries containing the target source.
1759 */
1760 class ContainingLibrariesTask extends SourceBasedAnalysisTask {
1761 /**
1762 * The task descriptor describing this kind of task.
1763 */
1764 static final TaskDescriptor DESCRIPTOR = new TaskDescriptor(
1765 'ContainingLibrariesTask',
1766 createTask,
1767 buildInputs,
1768 <ResultDescriptor>[CONTAINING_LIBRARIES]);
1769
1770 ContainingLibrariesTask(
1771 InternalAnalysisContext context, AnalysisTarget target)
1772 : super(context, target);
1773
1774 @override
1775 TaskDescriptor get descriptor => DESCRIPTOR;
1776
1777 @override
1778 void internalPerform() {
1779 // TODO(brianwilkerson) This value can change as new libraries are analyzed
1780 // so we need some way of making sure that this result is removed from the
1781 // cache appropriately.
1782 Source source = getRequiredSource();
1783 outputs[CONTAINING_LIBRARIES] = context.getLibrariesContaining(source);
1784 }
1785
1786 /**
1787 * Return a map from the names of the inputs of this kind of task to the task
1788 * input descriptors describing those inputs for a task with the
1789 * given [target].
1790 */
1791 static Map<String, TaskInput> buildInputs(AnalysisTarget target) {
1792 return <String, TaskInput>{};
1793 }
1794
1795 /**
1796 * Create a [ContainingLibrariesTask] based on the given [target] in the given
1797 * [context].
1798 */
1799 static ContainingLibrariesTask createTask(
1800 AnalysisContext context, AnalysisTarget target) {
1801 return new ContainingLibrariesTask(context, target);
1802 }
1803 }
1804
1805 /**
1806 * The description for a change in a Dart source.
1807 */
1808 class DartDelta extends Delta {
1809 bool hasDirectiveChange = false;
1810
1811 final Set<String> addedNames = new Set<String>();
1812 final Set<String> changedNames = new Set<String>();
1813 final Set<String> removedNames = new Set<String>();
1814
1815 final Set<Source> invalidatedSources = new Set<Source>();
1816
1817 DartDelta(Source source) : super(source) {
1818 invalidatedSources.add(source);
1819 }
1820
1821 void elementAdded(Element element) {
1822 addedNames.add(element.name);
1823 }
1824
1825 void elementChanged(Element element) {
1826 changedNames.add(element.name);
1827 }
1828
1829 void elementRemoved(Element element) {
1830 removedNames.add(element.name);
1831 }
1832
1833 bool isNameAffected(String name) {
1834 return addedNames.contains(name) ||
1835 changedNames.contains(name) ||
1836 removedNames.contains(name);
1837 }
1838
1839 bool nameChanged(String name) {
1840 return changedNames.add(name);
1841 }
1842
1843 @override
1844 DeltaResult validate(InternalAnalysisContext context, AnalysisTarget target,
1845 ResultDescriptor descriptor) {
1846 if (hasDirectiveChange) {
1847 return DeltaResult.INVALIDATE;
1848 }
1849 // Prepare target source.
1850 Source targetSource = null;
1851 if (target is Source) {
1852 targetSource = target;
1853 }
1854 if (target is LibrarySpecificUnit) {
1855 targetSource = target.library;
1856 }
1857 if (target is Element) {
1858 targetSource = target.source;
1859 }
1860 // Keep results that are updated incrementally.
1861 // If we want to analyze only some references to the source being changed,
1862 // we need to keep the same instances of CompilationUnitElement and
1863 // LibraryElement.
1864 if (targetSource == source) {
1865 if (ParseDartTask.DESCRIPTOR.results.contains(descriptor)) {
1866 return DeltaResult.KEEP_CONTINUE;
1867 }
1868 if (BuildCompilationUnitElementTask.DESCRIPTOR.results
1869 .contains(descriptor)) {
1870 return DeltaResult.KEEP_CONTINUE;
1871 }
1872 if (BuildLibraryElementTask.DESCRIPTOR.results.contains(descriptor)) {
1873 return DeltaResult.KEEP_CONTINUE;
1874 }
1875 return DeltaResult.INVALIDATE;
1876 }
1877 // Use the target library dependency information to decide whether
1878 // the delta affects the library.
1879 if (targetSource != null) {
1880 List<Source> librarySources =
1881 context.getLibrariesContaining(targetSource);
1882 for (Source librarySource in librarySources) {
1883 AnalysisCache cache = context.analysisCache;
1884 ReferencedNames referencedNames =
1885 cache.getValue(librarySource, REFERENCED_NAMES);
1886 if (referencedNames == null) {
1887 return DeltaResult.INVALIDATE;
1888 }
1889 referencedNames.addChangedElements(this);
1890 if (referencedNames.isAffectedBy(this)) {
1891 return DeltaResult.INVALIDATE;
1892 }
1893 }
1894 return DeltaResult.STOP;
1895 }
1896 // We don't know what to do with the given target, invalidate it.
1897 return DeltaResult.INVALIDATE;
1898 }
1899 }
1900
1901 /**
1902 * A task that merges all of the errors for a single source into a single list
1903 * of errors.
1904 */
1905 class DartErrorsTask extends SourceBasedAnalysisTask {
1906 /**
1907 * The name of the [BUILD_DIRECTIVES_ERRORS] input.
1908 */
1909 static const String BUILD_DIRECTIVES_ERRORS_INPUT = 'BUILD_DIRECTIVES_ERRORS';
1910
1911 /**
1912 * The name of the [BUILD_LIBRARY_ERRORS] input.
1913 */
1914 static const String BUILD_LIBRARY_ERRORS_INPUT = 'BUILD_LIBRARY_ERRORS';
1915
1916 /**
1917 * The name of the [LIBRARY_UNIT_ERRORS] input.
1918 */
1919 static const String LIBRARY_UNIT_ERRORS_INPUT = 'LIBRARY_UNIT_ERRORS';
1920
1921 /**
1922 * The name of the [PARSE_ERRORS] input.
1923 */
1924 static const String PARSE_ERRORS_INPUT = 'PARSE_ERRORS';
1925
1926 /**
1927 * The name of the [SCAN_ERRORS] input.
1928 */
1929 static const String SCAN_ERRORS_INPUT = 'SCAN_ERRORS';
1930
1931 /**
1932 * The task descriptor describing this kind of task.
1933 */
1934 static final TaskDescriptor DESCRIPTOR = new TaskDescriptor('DartErrorsTask',
1935 createTask, buildInputs, <ResultDescriptor>[DART_ERRORS]);
1936
1937 DartErrorsTask(InternalAnalysisContext context, AnalysisTarget target)
1938 : super(context, target);
1939
1940 @override
1941 TaskDescriptor get descriptor => DESCRIPTOR;
1942
1943 @override
1944 void internalPerform() {
1945 //
1946 // Prepare inputs.
1947 //
1948 List<List<AnalysisError>> errorLists = <List<AnalysisError>>[];
1949 errorLists.add(getRequiredInput(BUILD_DIRECTIVES_ERRORS_INPUT));
1950 errorLists.add(getRequiredInput(BUILD_LIBRARY_ERRORS_INPUT));
1951 errorLists.add(getRequiredInput(PARSE_ERRORS_INPUT));
1952 errorLists.add(getRequiredInput(SCAN_ERRORS_INPUT));
1953 Map<Source, List<AnalysisError>> unitErrors =
1954 getRequiredInput(LIBRARY_UNIT_ERRORS_INPUT);
1955 for (List<AnalysisError> errors in unitErrors.values) {
1956 errorLists.add(errors);
1957 }
1958 //
1959 // Record outputs.
1960 //
1961 outputs[DART_ERRORS] = AnalysisError.mergeLists(errorLists);
1962 }
1963
1964 /**
1965 * Return a map from the names of the inputs of this kind of task to the task
1966 * input descriptors describing those inputs for a task with the
1967 * given [target].
1968 */
1969 static Map<String, TaskInput> buildInputs(AnalysisTarget target) {
1970 Source source = target;
1971 return <String, TaskInput>{
1972 BUILD_DIRECTIVES_ERRORS_INPUT: BUILD_DIRECTIVES_ERRORS.of(source),
1973 BUILD_LIBRARY_ERRORS_INPUT: BUILD_LIBRARY_ERRORS.of(source),
1974 PARSE_ERRORS_INPUT: PARSE_ERRORS.of(source),
1975 SCAN_ERRORS_INPUT: SCAN_ERRORS.of(source),
1976 LIBRARY_UNIT_ERRORS_INPUT:
1977 CONTAINING_LIBRARIES.of(source).toMap((Source library) {
1978 LibrarySpecificUnit unit = new LibrarySpecificUnit(library, source);
1979 return LIBRARY_UNIT_ERRORS.of(unit);
1980 })
1981 };
1982 }
1983
1984 /**
1985 * Create a [DartErrorsTask] based on the given [target] in the given
1986 * [context].
1987 */
1988 static DartErrorsTask createTask(
1989 AnalysisContext context, AnalysisTarget target) {
1990 return new DartErrorsTask(context, target);
1991 }
1992 }
1993
1994 /**
1995 * A task that builds [RESOLVED_UNIT] for a unit.
1996 */
1997 class EvaluateUnitConstantsTask extends SourceBasedAnalysisTask {
1998 /**
1999 * The name of the [RESOLVED_UNIT8] input.
2000 */
2001 static const String UNIT_INPUT = 'UNIT_INPUT';
2002
2003 /**
2004 * The name of the [CONSTANT_VALUE] input.
2005 */
2006 static const String CONSTANT_VALUES = 'CONSTANT_VALUES';
2007
2008 /**
2009 * The task descriptor describing this kind of task.
2010 */
2011 static final TaskDescriptor DESCRIPTOR = new TaskDescriptor(
2012 'EvaluateUnitConstantsTask',
2013 createTask,
2014 buildInputs,
2015 <ResultDescriptor>[RESOLVED_UNIT]);
2016
2017 EvaluateUnitConstantsTask(AnalysisContext context, LibrarySpecificUnit target)
2018 : super(context, target);
2019
2020 @override
2021 TaskDescriptor get descriptor => DESCRIPTOR;
2022
2023 @override
2024 void internalPerform() {
2025 // No actual work needs to be performed; the task manager will ensure that
2026 // all constants are evaluated before this method is called.
2027 CompilationUnit unit = getRequiredInput(UNIT_INPUT);
2028 outputs[RESOLVED_UNIT] = unit;
2029 }
2030
2031 /**
2032 * Return a map from the names of the inputs of this kind of task to the task
2033 * input descriptors describing those inputs for a task with the
2034 * given [target].
2035 */
2036 static Map<String, TaskInput> buildInputs(AnalysisTarget target) {
2037 LibrarySpecificUnit unit = target;
2038 return <String, TaskInput>{
2039 'libraryElement': LIBRARY_ELEMENT.of(unit.library),
2040 UNIT_INPUT: RESOLVED_UNIT8.of(unit),
2041 CONSTANT_VALUES:
2042 COMPILATION_UNIT_CONSTANTS.of(unit).toListOf(CONSTANT_VALUE)
2043 };
2044 }
2045
2046 /**
2047 * Create an [EvaluateUnitConstantsTask] based on the given [target] in
2048 * the given [context].
2049 */
2050 static EvaluateUnitConstantsTask createTask(
2051 AnalysisContext context, AnalysisTarget target) {
2052 return new EvaluateUnitConstantsTask(context, target);
2053 }
2054 }
2055
2056 /**
2057 * The helper for building the export [Namespace] of a [LibraryElement].
2058 */
2059 class ExportNamespaceBuilder {
2060 /**
2061 * Build the export [Namespace] of the given [LibraryElement].
2062 */
2063 Namespace build(LibraryElement library) {
2064 return new Namespace(
2065 _createExportMapping(library, new HashSet<LibraryElement>()));
2066 }
2067
2068 /**
2069 * Create a mapping table representing the export namespace of the given
2070 * [library].
2071 *
2072 * The given [visitedElements] a set of libraries that do not need to be
2073 * visited when processing the export directives of the given library because
2074 * all of the names defined by them will be added by another library.
2075 */
2076 HashMap<String, Element> _createExportMapping(
2077 LibraryElement library, HashSet<LibraryElement> visitedElements) {
2078 visitedElements.add(library);
2079 try {
2080 HashMap<String, Element> definedNames = new HashMap<String, Element>();
2081 // Add names of the export directives.
2082 for (ExportElement element in library.exports) {
2083 LibraryElement exportedLibrary = element.exportedLibrary;
2084 if (exportedLibrary != null &&
2085 !visitedElements.contains(exportedLibrary)) {
2086 //
2087 // The exported library will be null if the URI does not reference a
2088 // valid library.
2089 //
2090 HashMap<String, Element> exportedNames =
2091 _createExportMapping(exportedLibrary, visitedElements);
2092 exportedNames = _applyCombinators(exportedNames, element.combinators);
2093 definedNames.addAll(exportedNames);
2094 }
2095 }
2096 // Add names of the public namespace.
2097 {
2098 Namespace publicNamespace = library.publicNamespace;
2099 if (publicNamespace != null) {
2100 definedNames.addAll(publicNamespace.definedNames);
2101 }
2102 }
2103 return definedNames;
2104 } finally {
2105 visitedElements.remove(library);
2106 }
2107 }
2108
2109 /**
2110 * Apply the given [combinators] to all of the names in [definedNames].
2111 */
2112 static HashMap<String, Element> _applyCombinators(
2113 HashMap<String, Element> definedNames,
2114 List<NamespaceCombinator> combinators) {
2115 for (NamespaceCombinator combinator in combinators) {
2116 if (combinator is HideElementCombinator) {
2117 _hide(definedNames, combinator.hiddenNames);
2118 } else if (combinator is ShowElementCombinator) {
2119 definedNames = _show(definedNames, combinator.shownNames);
2120 }
2121 }
2122 return definedNames;
2123 }
2124
2125 /**
2126 * Hide all of the [hiddenNames] by removing them from the given
2127 * [definedNames].
2128 */
2129 static void _hide(
2130 HashMap<String, Element> definedNames, List<String> hiddenNames) {
2131 for (String name in hiddenNames) {
2132 definedNames.remove(name);
2133 definedNames.remove('$name=');
2134 }
2135 }
2136
2137 /**
2138 * Show only the given [shownNames] by removing all other names from the given
2139 * [definedNames].
2140 */
2141 static HashMap<String, Element> _show(
2142 HashMap<String, Element> definedNames, List<String> shownNames) {
2143 HashMap<String, Element> newNames = new HashMap<String, Element>();
2144 for (String name in shownNames) {
2145 Element element = definedNames[name];
2146 if (element != null) {
2147 newNames[name] = element;
2148 }
2149 String setterName = '$name=';
2150 element = definedNames[setterName];
2151 if (element != null) {
2152 newNames[setterName] = element;
2153 }
2154 }
2155 return newNames;
2156 }
2157 }
2158
2159 /**
2160 * A task that builds [USED_IMPORTED_ELEMENTS] for a unit.
2161 */
2162 class GatherUsedImportedElementsTask extends SourceBasedAnalysisTask {
2163 /**
2164 * The name of the [RESOLVED_UNIT8] input.
2165 */
2166 static const String UNIT_INPUT = 'UNIT_INPUT';
2167
2168 /**
2169 * The task descriptor describing this kind of task.
2170 */
2171 static final TaskDescriptor DESCRIPTOR = new TaskDescriptor(
2172 'GatherUsedImportedElementsTask',
2173 createTask,
2174 buildInputs,
2175 <ResultDescriptor>[USED_IMPORTED_ELEMENTS]);
2176
2177 GatherUsedImportedElementsTask(
2178 InternalAnalysisContext context, AnalysisTarget target)
2179 : super(context, target);
2180
2181 @override
2182 TaskDescriptor get descriptor => DESCRIPTOR;
2183
2184 @override
2185 void internalPerform() {
2186 CompilationUnit unit = getRequiredInput(UNIT_INPUT);
2187 CompilationUnitElement unitElement = unit.element;
2188 LibraryElement libraryElement = unitElement.library;
2189 //
2190 // Prepare used imported elements.
2191 //
2192 GatherUsedImportedElementsVisitor visitor =
2193 new GatherUsedImportedElementsVisitor(libraryElement);
2194 unit.accept(visitor);
2195 //
2196 // Record outputs.
2197 //
2198 outputs[USED_IMPORTED_ELEMENTS] = visitor.usedElements;
2199 }
2200
2201 /**
2202 * Return a map from the names of the inputs of this kind of task to the task
2203 * input descriptors describing those inputs for a task with the
2204 * given [target].
2205 */
2206 static Map<String, TaskInput> buildInputs(AnalysisTarget target) {
2207 LibrarySpecificUnit unit = target;
2208 return <String, TaskInput>{UNIT_INPUT: RESOLVED_UNIT8.of(unit)};
2209 }
2210
2211 /**
2212 * Create a [GatherUsedImportedElementsTask] based on the given [target] in
2213 * the given [context].
2214 */
2215 static GatherUsedImportedElementsTask createTask(
2216 AnalysisContext context, AnalysisTarget target) {
2217 return new GatherUsedImportedElementsTask(context, target);
2218 }
2219 }
2220
2221 /**
2222 * A task that builds [USED_LOCAL_ELEMENTS] for a unit.
2223 */
2224 class GatherUsedLocalElementsTask extends SourceBasedAnalysisTask {
2225 /**
2226 * The name of the [RESOLVED_UNIT8] input.
2227 */
2228 static const String UNIT_INPUT = 'UNIT_INPUT';
2229
2230 /**
2231 * The task descriptor describing this kind of task.
2232 */
2233 static final TaskDescriptor DESCRIPTOR = new TaskDescriptor(
2234 'GatherUsedLocalElementsTask',
2235 createTask,
2236 buildInputs,
2237 <ResultDescriptor>[USED_LOCAL_ELEMENTS]);
2238
2239 GatherUsedLocalElementsTask(
2240 InternalAnalysisContext context, AnalysisTarget target)
2241 : super(context, target);
2242
2243 @override
2244 TaskDescriptor get descriptor => DESCRIPTOR;
2245
2246 @override
2247 void internalPerform() {
2248 CompilationUnit unit = getRequiredInput(UNIT_INPUT);
2249 CompilationUnitElement unitElement = unit.element;
2250 LibraryElement libraryElement = unitElement.library;
2251 //
2252 // Prepare used local elements.
2253 //
2254 GatherUsedLocalElementsVisitor visitor =
2255 new GatherUsedLocalElementsVisitor(libraryElement);
2256 unit.accept(visitor);
2257 //
2258 // Record outputs.
2259 //
2260 outputs[USED_LOCAL_ELEMENTS] = visitor.usedElements;
2261 }
2262
2263 /**
2264 * Return a map from the names of the inputs of this kind of task to the task
2265 * input descriptors describing those inputs for a task with the
2266 * given [target].
2267 */
2268 static Map<String, TaskInput> buildInputs(AnalysisTarget target) {
2269 LibrarySpecificUnit unit = target;
2270 return <String, TaskInput>{UNIT_INPUT: RESOLVED_UNIT8.of(unit)};
2271 }
2272
2273 /**
2274 * Create a [GatherUsedLocalElementsTask] based on the given [target] in
2275 * the given [context].
2276 */
2277 static GatherUsedLocalElementsTask createTask(
2278 AnalysisContext context, AnalysisTarget target) {
2279 return new GatherUsedLocalElementsTask(context, target);
2280 }
2281 }
2282
2283 /**
2284 * A task that generates [HINTS] for a unit.
2285 */
2286 class GenerateHintsTask extends SourceBasedAnalysisTask {
2287 /**
2288 * The name of the [RESOLVED_UNIT8] input.
2289 */
2290 static const String RESOLVED_UNIT_INPUT = 'RESOLVED_UNIT';
2291
2292 /**
2293 * The name of a list of [USED_LOCAL_ELEMENTS] for each library unit input.
2294 */
2295 static const String USED_LOCAL_ELEMENTS_INPUT = 'USED_LOCAL_ELEMENTS';
2296
2297 /**
2298 * The name of a list of [USED_IMPORTED_ELEMENTS] for each library unit input.
2299 */
2300 static const String USED_IMPORTED_ELEMENTS_INPUT = 'USED_IMPORTED_ELEMENTS';
2301
2302 /**
2303 * The name of the [TYPE_PROVIDER] input.
2304 */
2305 static const String TYPE_PROVIDER_INPUT = 'TYPE_PROVIDER_INPUT';
2306
2307 /**
2308 * The task descriptor describing this kind of task.
2309 */
2310 static final TaskDescriptor DESCRIPTOR = new TaskDescriptor(
2311 'GenerateHintsTask', createTask, buildInputs, <ResultDescriptor>[HINTS]);
2312
2313 GenerateHintsTask(InternalAnalysisContext context, AnalysisTarget target)
2314 : super(context, target);
2315
2316 @override
2317 TaskDescriptor get descriptor => DESCRIPTOR;
2318
2319 @override
2320 void internalPerform() {
2321 AnalysisOptions analysisOptions = context.analysisOptions;
2322 if (!analysisOptions.hint) {
2323 outputs[HINTS] = AnalysisError.NO_ERRORS;
2324 return;
2325 }
2326 //
2327 // Prepare collectors.
2328 //
2329 RecordingErrorListener errorListener = new RecordingErrorListener();
2330 Source source = getRequiredSource();
2331 ErrorReporter errorReporter = new ErrorReporter(errorListener, source);
2332 //
2333 // Prepare inputs.
2334 //
2335 CompilationUnit unit = getRequiredInput(RESOLVED_UNIT_INPUT);
2336 List<UsedImportedElements> usedImportedElementsList =
2337 getRequiredInput(USED_IMPORTED_ELEMENTS_INPUT);
2338 List<UsedLocalElements> usedLocalElementsList =
2339 getRequiredInput(USED_LOCAL_ELEMENTS_INPUT);
2340 CompilationUnitElement unitElement = unit.element;
2341 LibraryElement libraryElement = unitElement.library;
2342 //
2343 // Generate errors.
2344 //
2345 unit.accept(new DeadCodeVerifier(errorReporter));
2346 // Verify imports.
2347 {
2348 ImportsVerifier verifier = new ImportsVerifier();
2349 verifier.addImports(unit);
2350 usedImportedElementsList.forEach(verifier.removeUsedElements);
2351 verifier.generateDuplicateImportHints(errorReporter);
2352 verifier.generateUnusedImportHints(errorReporter);
2353 }
2354 // Unused local elements.
2355 {
2356 UsedLocalElements usedElements =
2357 new UsedLocalElements.merge(usedLocalElementsList);
2358 UnusedLocalElementsVerifier visitor =
2359 new UnusedLocalElementsVerifier(errorListener, usedElements);
2360 unitElement.accept(visitor);
2361 }
2362 // Dart2js analysis.
2363 if (analysisOptions.dart2jsHint) {
2364 unit.accept(new Dart2JSVerifier(errorReporter));
2365 }
2366 // Dart best practices.
2367 InheritanceManager inheritanceManager =
2368 new InheritanceManager(libraryElement);
2369 TypeProvider typeProvider = getRequiredInput(TYPE_PROVIDER_INPUT);
2370 unit.accept(new BestPracticesVerifier(errorReporter, typeProvider));
2371 unit.accept(new OverrideVerifier(errorReporter, inheritanceManager));
2372 // Find to-do comments.
2373 new ToDoFinder(errorReporter).findIn(unit);
2374 //
2375 // Record outputs.
2376 //
2377 outputs[HINTS] = errorListener.errors;
2378 }
2379
2380 /**
2381 * Return a map from the names of the inputs of this kind of task to the task
2382 * input descriptors describing those inputs for a task with the
2383 * given [target].
2384 */
2385 static Map<String, TaskInput> buildInputs(AnalysisTarget target) {
2386 LibrarySpecificUnit unit = target;
2387 Source libSource = unit.library;
2388 return <String, TaskInput>{
2389 RESOLVED_UNIT_INPUT: RESOLVED_UNIT.of(unit),
2390 USED_LOCAL_ELEMENTS_INPUT: UNITS.of(libSource).toList((unit) {
2391 LibrarySpecificUnit target = new LibrarySpecificUnit(libSource, unit);
2392 return USED_LOCAL_ELEMENTS.of(target);
2393 }),
2394 USED_IMPORTED_ELEMENTS_INPUT: UNITS.of(libSource).toList((unit) {
2395 LibrarySpecificUnit target = new LibrarySpecificUnit(libSource, unit);
2396 return USED_IMPORTED_ELEMENTS.of(target);
2397 }),
2398 TYPE_PROVIDER_INPUT: TYPE_PROVIDER.of(AnalysisContextTarget.request)
2399 };
2400 }
2401
2402 /**
2403 * Create a [GenerateHintsTask] based on the given [target] in
2404 * the given [context].
2405 */
2406 static GenerateHintsTask createTask(
2407 AnalysisContext context, AnalysisTarget target) {
2408 return new GenerateHintsTask(context, target);
2409 }
2410 }
2411
2412 /**
2413 * An abstract class that defines utility methods that are useful for tasks
2414 * operating on static variables.
2415 */
2416 abstract class InferStaticVariableTask extends ConstantEvaluationAnalysisTask {
2417 InferStaticVariableTask(
2418 InternalAnalysisContext context, VariableElement variable)
2419 : super(context, variable);
2420
2421 /**
2422 * Return the declaration of the target within the given compilation [unit].
2423 * Throw an exception if the declaration cannot be found.
2424 */
2425 VariableDeclaration getDeclaration(CompilationUnit unit) {
2426 VariableElement variable = target;
2427 NodeLocator locator = new NodeLocator(variable.nameOffset);
2428 AstNode node = locator.searchWithin(unit);
2429 VariableDeclaration declaration =
2430 node.getAncestor((AstNode ancestor) => ancestor is VariableDeclaration);
2431 if (declaration == null || declaration.name != node) {
2432 throw new AnalysisException(
2433 "Failed to find the declaration of the variable ${variable.displayName } in ${variable.source}");
2434 }
2435 return declaration;
2436 }
2437 }
2438
2439 /**
2440 * A task that ensures that all of the inferrable static variables in a
2441 * compilation unit have had their type inferred.
2442 */
2443 class InferStaticVariableTypesInUnitTask extends SourceBasedAnalysisTask {
2444 /**
2445 * The name of the input whose value is the [RESOLVED_UNIT5] for the
2446 * compilation unit.
2447 */
2448 static const String UNIT_INPUT = 'UNIT_INPUT';
2449
2450 /**
2451 * The name of the input whose value is a list of the inferrable static
2452 * variables whose types have been computed.
2453 */
2454 static const String INFERRED_VARIABLES_INPUT = 'INFERRED_VARIABLES_INPUT';
2455
2456 /**
2457 * The task descriptor describing this kind of task.
2458 */
2459 static final TaskDescriptor DESCRIPTOR = new TaskDescriptor(
2460 'InferStaticVariableTypesInUnitTask',
2461 createTask,
2462 buildInputs,
2463 <ResultDescriptor>[RESOLVED_UNIT6]);
2464
2465 /**
2466 * Initialize a newly created task to build a library element for the given
2467 * [unit] in the given [context].
2468 */
2469 InferStaticVariableTypesInUnitTask(
2470 InternalAnalysisContext context, LibrarySpecificUnit unit)
2471 : super(context, unit);
2472
2473 @override
2474 TaskDescriptor get descriptor => DESCRIPTOR;
2475
2476 @override
2477 void internalPerform() {
2478 //
2479 // Prepare inputs.
2480 //
2481 CompilationUnit unit = getRequiredInput(UNIT_INPUT);
2482 //
2483 // Record outputs. There is no additional work to be done at this time
2484 // because the work has implicitly been done by virtue of the task model
2485 // preparing all of the inputs.
2486 //
2487 outputs[RESOLVED_UNIT6] = unit;
2488 }
2489
2490 /**
2491 * Return a map from the names of the inputs of this kind of task to the task
2492 * input descriptors describing those inputs for a task with the given
2493 * [libSource].
2494 */
2495 static Map<String, TaskInput> buildInputs(AnalysisTarget target) {
2496 LibrarySpecificUnit unit = target;
2497 return <String, TaskInput>{
2498 INFERRED_VARIABLES_INPUT: INFERABLE_STATIC_VARIABLES_IN_UNIT
2499 .of(unit)
2500 .toListOf(INFERRED_STATIC_VARIABLE),
2501 UNIT_INPUT: RESOLVED_UNIT5.of(unit)
2502 };
2503 }
2504
2505 /**
2506 * Create a [InferStaticVariableTypesInUnitTask] based on the given [target] i n the
2507 * given [context].
2508 */
2509 static InferStaticVariableTypesInUnitTask createTask(
2510 AnalysisContext context, AnalysisTarget target) {
2511 return new InferStaticVariableTypesInUnitTask(context, target);
2512 }
2513 }
2514
2515 /**
2516 * A task that computes the type of an inferrable static variable and
2517 * stores it in the element model.
2518 */
2519 class InferStaticVariableTypeTask extends InferStaticVariableTask {
2520 /**
2521 * The name of the input which ensures that dependent values have their type
2522 * inferred before the target.
2523 */
2524 static const String DEPENDENCIES_INPUT = 'DEPENDENCIES_INPUT';
2525
2526 /**
2527 * The name of the [TYPE_PROVIDER] input.
2528 */
2529 static const String TYPE_PROVIDER_INPUT = 'TYPE_PROVIDER_INPUT';
2530
2531 /**
2532 * The name of the [RESOLVED_UNIT5] input.
2533 */
2534 static const String UNIT_INPUT = 'UNIT_INPUT';
2535
2536 static final TaskDescriptor DESCRIPTOR = new TaskDescriptor(
2537 'InferStaticVariableTypeTask',
2538 createTask,
2539 buildInputs,
2540 <ResultDescriptor>[INFERRED_STATIC_VARIABLE]);
2541
2542 InferStaticVariableTypeTask(
2543 InternalAnalysisContext context, VariableElement variable)
2544 : super(context, variable);
2545
2546 @override
2547 TaskDescriptor get descriptor => DESCRIPTOR;
2548
2549 @override
2550 bool get handlesDependencyCycles => true;
2551
2552 @override
2553 void internalPerform() {
2554 //
2555 // Prepare inputs.
2556 //
2557 // Note: DEPENDENCIES_INPUT is not needed. It is merely a bookkeeping
2558 // dependency to ensure that the variables that this variable references
2559 // have types inferred before inferring the type of this variable.
2560 //
2561 VariableElementImpl variable = target;
2562 CompilationUnit unit = getRequiredInput(UNIT_INPUT);
2563 TypeProvider typeProvider = getRequiredInput(TYPE_PROVIDER_INPUT);
2564 //
2565 // Re-resolve the variable's initializer so that the inferred types of other
2566 // variables will be propagated.
2567 //
2568 NodeLocator locator = new NodeLocator(variable.nameOffset);
2569 AstNode node = locator.searchWithin(unit);
2570 VariableDeclaration declaration =
2571 node.getAncestor((AstNode ancestor) => ancestor is VariableDeclaration);
2572 if (declaration == null || declaration.name != node) {
2573 throw new AnalysisException(
2574 "NodeLocator failed to find a variable's declaration");
2575 }
2576 RecordingErrorListener errorListener = new RecordingErrorListener();
2577 Expression initializer = declaration.initializer;
2578 ResolutionContext resolutionContext =
2579 ResolutionContextBuilder.contextFor(initializer, errorListener);
2580 ResolverVisitor visitor = new ResolverVisitor(
2581 variable.library, variable.source, typeProvider, errorListener,
2582 nameScope: resolutionContext.scope);
2583 if (resolutionContext.enclosingClassDeclaration != null) {
2584 visitor.prepareToResolveMembersInClass(
2585 resolutionContext.enclosingClassDeclaration);
2586 }
2587 visitor.initForIncrementalResolution();
2588 initializer.accept(visitor);
2589 //
2590 // Record the type of the variable.
2591 //
2592 DartType newType = initializer.staticType;
2593 variable.type = newType;
2594 (variable.initializer as ExecutableElementImpl).returnType = newType;
2595 if (variable is PropertyInducingElementImpl) {
2596 setReturnType(variable.getter, newType);
2597 setParameterType(variable.setter, newType);
2598 }
2599 //
2600 // Record outputs.
2601 //
2602 outputs[INFERRED_STATIC_VARIABLE] = variable;
2603 }
2604
2605 /**
2606 * Return a map from the names of the inputs of this kind of task to the task
2607 * input descriptors describing those inputs for a task with the given
2608 * [target].
2609 */
2610 static Map<String, TaskInput> buildInputs(AnalysisTarget target) {
2611 VariableElement variable = target;
2612 LibrarySpecificUnit unit =
2613 new LibrarySpecificUnit(variable.library.source, variable.source);
2614 return <String, TaskInput>{
2615 DEPENDENCIES_INPUT: INFERABLE_STATIC_VARIABLE_DEPENDENCIES
2616 .of(variable)
2617 .toListOf(INFERRED_STATIC_VARIABLE),
2618 TYPE_PROVIDER_INPUT: TYPE_PROVIDER.of(AnalysisContextTarget.request),
2619 UNIT_INPUT: RESOLVED_UNIT5.of(unit)
2620 };
2621 }
2622
2623 /**
2624 * Create a [InferStaticVariableTypeTask] based on the given [target] in the
2625 * given [context].
2626 */
2627 static InferStaticVariableTypeTask createTask(
2628 AnalysisContext context, AnalysisTarget target) {
2629 return new InferStaticVariableTypeTask(context, target);
2630 }
2631 }
2632
2633 /**
2634 * A task computes all of the errors of all of the units for a single
2635 * library source and sets the [LIBRARY_ERRORS_READY] flag.
2636 */
2637 class LibraryErrorsReadyTask extends SourceBasedAnalysisTask {
2638 /**
2639 * The task descriptor describing this kind of task.
2640 */
2641 static final TaskDescriptor DESCRIPTOR = new TaskDescriptor(
2642 'LibraryErrorsReadyTask',
2643 createTask,
2644 buildInputs,
2645 <ResultDescriptor>[LIBRARY_ERRORS_READY]);
2646
2647 LibraryErrorsReadyTask(InternalAnalysisContext context, AnalysisTarget target)
2648 : super(context, target);
2649
2650 @override
2651 TaskDescriptor get descriptor => DESCRIPTOR;
2652
2653 @override
2654 void internalPerform() {
2655 outputs[LIBRARY_ERRORS_READY] = true;
2656 }
2657
2658 /**
2659 * Return a map from the names of the inputs of this kind of task to the task
2660 * input descriptors describing those inputs for a task with the
2661 * given [library].
2662 */
2663 static Map<String, TaskInput> buildInputs(AnalysisTarget target) {
2664 Source source = target;
2665 return <String, TaskInput>{
2666 'allErrors': UNITS.of(source).toListOf(DART_ERRORS)
2667 };
2668 }
2669
2670 /**
2671 * Create a [LibraryErrorsReadyTask] based on the given [target] in the given
2672 * [context].
2673 */
2674 static LibraryErrorsReadyTask createTask(
2675 AnalysisContext context, AnalysisTarget target) {
2676 return new LibraryErrorsReadyTask(context, target);
2677 }
2678 }
2679
2680 /**
2681 * A task that merges all of the errors for a single source into a single list
2682 * of errors.
2683 */
2684 class LibraryUnitErrorsTask extends SourceBasedAnalysisTask {
2685 /**
2686 * The name of the [HINTS] input.
2687 */
2688 static const String HINTS_INPUT = 'HINTS';
2689
2690 /**
2691 * The name of the [RESOLVE_REFERENCES_ERRORS] input.
2692 */
2693 static const String RESOLVE_REFERENCES_ERRORS_INPUT =
2694 'RESOLVE_REFERENCES_ERRORS';
2695
2696 /**
2697 * The name of the [RESOLVE_TYPE_NAMES_ERRORS] input.
2698 */
2699 static const String RESOLVE_TYPE_NAMES_ERRORS_INPUT =
2700 'RESOLVE_TYPE_NAMES_ERRORS';
2701
2702 /**
2703 * The name of the [VARIABLE_REFERENCE_ERRORS] input.
2704 */
2705 static const String VARIABLE_REFERENCE_ERRORS_INPUT =
2706 'VARIABLE_REFERENCE_ERRORS';
2707
2708 /**
2709 * The name of the [VERIFY_ERRORS] input.
2710 */
2711 static const String VERIFY_ERRORS_INPUT = 'VERIFY_ERRORS';
2712
2713 /**
2714 * The task descriptor describing this kind of task.
2715 */
2716 static final TaskDescriptor DESCRIPTOR = new TaskDescriptor(
2717 'LibraryUnitErrorsTask',
2718 createTask,
2719 buildInputs,
2720 <ResultDescriptor>[LIBRARY_UNIT_ERRORS]);
2721
2722 LibraryUnitErrorsTask(InternalAnalysisContext context, AnalysisTarget target)
2723 : super(context, target);
2724
2725 @override
2726 TaskDescriptor get descriptor => DESCRIPTOR;
2727
2728 @override
2729 void internalPerform() {
2730 //
2731 // Prepare inputs.
2732 //
2733 List<List<AnalysisError>> errorLists = <List<AnalysisError>>[];
2734 errorLists.add(getRequiredInput(HINTS_INPUT));
2735 errorLists.add(getRequiredInput(RESOLVE_REFERENCES_ERRORS_INPUT));
2736 errorLists.add(getRequiredInput(RESOLVE_TYPE_NAMES_ERRORS_INPUT));
2737 errorLists.add(getRequiredInput(VARIABLE_REFERENCE_ERRORS_INPUT));
2738 errorLists.add(getRequiredInput(VERIFY_ERRORS_INPUT));
2739 //
2740 // Record outputs.
2741 //
2742 outputs[LIBRARY_UNIT_ERRORS] = AnalysisError.mergeLists(errorLists);
2743 }
2744
2745 /**
2746 * Return a map from the names of the inputs of this kind of task to the task
2747 * input descriptors describing those inputs for a task with the
2748 * given [unit].
2749 */
2750 static Map<String, TaskInput> buildInputs(AnalysisTarget target) {
2751 LibrarySpecificUnit unit = target;
2752 return <String, TaskInput>{
2753 HINTS_INPUT: HINTS.of(unit),
2754 RESOLVE_REFERENCES_ERRORS_INPUT: RESOLVE_REFERENCES_ERRORS.of(unit),
2755 RESOLVE_TYPE_NAMES_ERRORS_INPUT: RESOLVE_TYPE_NAMES_ERRORS.of(unit),
2756 VARIABLE_REFERENCE_ERRORS_INPUT: VARIABLE_REFERENCE_ERRORS.of(unit),
2757 VERIFY_ERRORS_INPUT: VERIFY_ERRORS.of(unit)
2758 };
2759 }
2760
2761 /**
2762 * Create a [LibraryUnitErrorsTask] based on the given [target] in the given
2763 * [context].
2764 */
2765 static LibraryUnitErrorsTask createTask(
2766 AnalysisContext context, AnalysisTarget target) {
2767 return new LibraryUnitErrorsTask(context, target);
2768 }
2769 }
2770
2771 /**
2772 * A task that parses the content of a Dart file, producing an AST structure.
2773 */
2774 class ParseDartTask extends SourceBasedAnalysisTask {
2775 /**
2776 * The name of the input whose value is the line information produced for the
2777 * file.
2778 */
2779 static const String LINE_INFO_INPUT_NAME = 'LINE_INFO_INPUT_NAME';
2780
2781 /**
2782 * The name of the input whose value is the modification time of the file.
2783 */
2784 static const String MODIFICATION_TIME_INPUT_NAME =
2785 'MODIFICATION_TIME_INPUT_NAME';
2786
2787 /**
2788 * The name of the input whose value is the token stream produced for the file .
2789 */
2790 static const String TOKEN_STREAM_INPUT_NAME = 'TOKEN_STREAM_INPUT_NAME';
2791
2792 /**
2793 * The task descriptor describing this kind of task.
2794 */
2795 static final TaskDescriptor DESCRIPTOR = new TaskDescriptor(
2796 'ParseDartTask', createTask, buildInputs, <ResultDescriptor>[
2797 EXPLICITLY_IMPORTED_LIBRARIES,
2798 EXPORTED_LIBRARIES,
2799 IMPORTED_LIBRARIES,
2800 INCLUDED_PARTS,
2801 PARSE_ERRORS,
2802 PARSED_UNIT,
2803 SOURCE_KIND,
2804 UNITS
2805 ]);
2806
2807 /**
2808 * Initialize a newly created task to parse the content of the Dart file
2809 * associated with the given [target] in the given [context].
2810 */
2811 ParseDartTask(InternalAnalysisContext context, AnalysisTarget target)
2812 : super(context, target);
2813
2814 @override
2815 TaskDescriptor get descriptor => DESCRIPTOR;
2816
2817 @override
2818 void internalPerform() {
2819 Source source = getRequiredSource();
2820 LineInfo lineInfo = getRequiredInput(LINE_INFO_INPUT_NAME);
2821 int modificationTime = getRequiredInput(MODIFICATION_TIME_INPUT_NAME);
2822 Token tokenStream = getRequiredInput(TOKEN_STREAM_INPUT_NAME);
2823
2824 RecordingErrorListener errorListener = new RecordingErrorListener();
2825 Parser parser = new Parser(source, errorListener);
2826 AnalysisOptions options = context.analysisOptions;
2827 parser.parseFunctionBodies = options.analyzeFunctionBodiesPredicate(source);
2828 parser.parseGenericMethods = options.enableGenericMethods;
2829 CompilationUnit unit = parser.parseCompilationUnit(tokenStream);
2830 unit.lineInfo = lineInfo;
2831
2832 bool hasNonPartOfDirective = false;
2833 bool hasPartOfDirective = false;
2834 HashSet<Source> explicitlyImportedSourceSet = new HashSet<Source>();
2835 HashSet<Source> exportedSourceSet = new HashSet<Source>();
2836 HashSet<Source> includedSourceSet = new HashSet<Source>();
2837 for (Directive directive in unit.directives) {
2838 if (directive is PartOfDirective) {
2839 hasPartOfDirective = true;
2840 } else {
2841 hasNonPartOfDirective = true;
2842 if (directive is UriBasedDirective) {
2843 Source referencedSource =
2844 resolveDirective(context, source, directive, errorListener);
2845 if (referencedSource != null) {
2846 if (directive is ExportDirective) {
2847 exportedSourceSet.add(referencedSource);
2848 } else if (directive is ImportDirective) {
2849 explicitlyImportedSourceSet.add(referencedSource);
2850 } else if (directive is PartDirective) {
2851 includedSourceSet.add(referencedSource);
2852 } else {
2853 throw new AnalysisException(
2854 '$runtimeType failed to handle a ${directive.runtimeType}');
2855 }
2856 }
2857 }
2858 }
2859 }
2860 //
2861 // Always include "dart:core" source.
2862 //
2863 HashSet<Source> importedSourceSet =
2864 new HashSet.from(explicitlyImportedSourceSet);
2865 Source coreLibrarySource = context.sourceFactory.forUri(DartSdk.DART_CORE);
2866 importedSourceSet.add(coreLibrarySource);
2867 //
2868 // Compute kind.
2869 //
2870 SourceKind sourceKind = SourceKind.LIBRARY;
2871 if (modificationTime == -1) {
2872 sourceKind = SourceKind.UNKNOWN;
2873 } else if (hasPartOfDirective && !hasNonPartOfDirective) {
2874 sourceKind = SourceKind.PART;
2875 }
2876 //
2877 // Record outputs.
2878 //
2879 List<Source> explicitlyImportedSources =
2880 explicitlyImportedSourceSet.toList();
2881 List<Source> exportedSources = exportedSourceSet.toList();
2882 List<Source> importedSources = importedSourceSet.toList();
2883 List<Source> includedSources = includedSourceSet.toList();
2884 List<AnalysisError> parseErrors =
2885 removeDuplicateErrors(errorListener.errors);
2886 List<Source> unitSources = <Source>[source]..addAll(includedSourceSet);
2887 outputs[EXPLICITLY_IMPORTED_LIBRARIES] = explicitlyImportedSources;
2888 outputs[EXPORTED_LIBRARIES] = exportedSources;
2889 outputs[IMPORTED_LIBRARIES] = importedSources;
2890 outputs[INCLUDED_PARTS] = includedSources;
2891 outputs[PARSE_ERRORS] = parseErrors;
2892 outputs[PARSED_UNIT] = unit;
2893 outputs[SOURCE_KIND] = sourceKind;
2894 outputs[UNITS] = unitSources;
2895 }
2896
2897 /**
2898 * Return a map from the names of the inputs of this kind of task to the task
2899 * input descriptors describing those inputs for a task with the given
2900 * [source].
2901 */
2902 static Map<String, TaskInput> buildInputs(AnalysisTarget target) {
2903 return <String, TaskInput>{
2904 LINE_INFO_INPUT_NAME: LINE_INFO.of(target),
2905 MODIFICATION_TIME_INPUT_NAME: MODIFICATION_TIME.of(target),
2906 TOKEN_STREAM_INPUT_NAME: TOKEN_STREAM.of(target)
2907 };
2908 }
2909
2910 /**
2911 * Create a [ParseDartTask] based on the given [target] in the given
2912 * [context].
2913 */
2914 static ParseDartTask createTask(
2915 AnalysisContext context, AnalysisTarget target) {
2916 return new ParseDartTask(context, target);
2917 }
2918
2919 /**
2920 * Return the result of resolving the URI of the given URI-based [directive]
2921 * against the URI of the given library, or `null` if the URI is not valid.
2922 *
2923 * Resolution is to be performed in the given [context]. Errors should be
2924 * reported to the [errorListener].
2925 */
2926 static Source resolveDirective(AnalysisContext context, Source librarySource,
2927 UriBasedDirective directive, AnalysisErrorListener errorListener) {
2928 StringLiteral uriLiteral = directive.uri;
2929 String uriContent = uriLiteral.stringValue;
2930 if (uriContent != null) {
2931 uriContent = uriContent.trim();
2932 directive.uriContent = uriContent;
2933 }
2934 UriValidationCode code = directive.validate();
2935 if (code == null) {
2936 String encodedUriContent = Uri.encodeFull(uriContent);
2937 Source source =
2938 context.sourceFactory.resolveUri(librarySource, encodedUriContent);
2939 directive.source = source;
2940 return source;
2941 }
2942 if (code == UriValidationCode.URI_WITH_DART_EXT_SCHEME) {
2943 return null;
2944 }
2945 if (code == UriValidationCode.URI_WITH_INTERPOLATION) {
2946 errorListener.onError(new AnalysisError(librarySource, uriLiteral.offset,
2947 uriLiteral.length, CompileTimeErrorCode.URI_WITH_INTERPOLATION));
2948 return null;
2949 }
2950 if (code == UriValidationCode.INVALID_URI) {
2951 errorListener.onError(new AnalysisError(librarySource, uriLiteral.offset,
2952 uriLiteral.length, CompileTimeErrorCode.INVALID_URI, [uriContent]));
2953 return null;
2954 }
2955 throw new AnalysisException('Failed to handle validation code: $code');
2956 }
2957 }
2958
2959 /**
2960 * A task that builds [RESOLVED_UNIT5] for a unit.
2961 */
2962 class PartiallyResolveUnitReferencesTask extends SourceBasedAnalysisTask {
2963 /**
2964 * The name of the [LIBRARY_ELEMENT5] input.
2965 */
2966 static const String LIBRARY_INPUT = 'LIBRARY_INPUT';
2967
2968 /**
2969 * The name of the [RESOLVED_UNIT4] input.
2970 */
2971 static const String UNIT_INPUT = 'UNIT_INPUT';
2972
2973 /**
2974 * The name of the [TYPE_PROVIDER] input.
2975 */
2976 static const String TYPE_PROVIDER_INPUT = 'TYPE_PROVIDER_INPUT';
2977
2978 /**
2979 * The task descriptor describing this kind of task.
2980 */
2981 static final TaskDescriptor DESCRIPTOR = new TaskDescriptor(
2982 'PartiallyResolveUnitReferencesTask',
2983 createTask,
2984 buildInputs, <ResultDescriptor>[
2985 CLASSES_IN_UNIT,
2986 INFERABLE_STATIC_VARIABLES_IN_UNIT,
2987 PARTIALLY_RESOLVE_REFERENCES_ERRORS,
2988 RESOLVED_UNIT5
2989 ]);
2990
2991 PartiallyResolveUnitReferencesTask(
2992 InternalAnalysisContext context, AnalysisTarget target)
2993 : super(context, target);
2994
2995 @override
2996 TaskDescriptor get descriptor => DESCRIPTOR;
2997
2998 @override
2999 void internalPerform() {
3000 RecordingErrorListener errorListener = new RecordingErrorListener();
3001 //
3002 // Prepare inputs.
3003 //
3004 LibraryElement libraryElement = getRequiredInput(LIBRARY_INPUT);
3005 CompilationUnit unit = getRequiredInput(UNIT_INPUT);
3006 CompilationUnitElement unitElement = unit.element;
3007 TypeProvider typeProvider = getRequiredInput(TYPE_PROVIDER_INPUT);
3008 //
3009 // Resolve references.
3010 //
3011 InheritanceManager inheritanceManager =
3012 new InheritanceManager(libraryElement);
3013 // TODO(brianwilkerson) Improve performance by not resolving anything inside
3014 // function bodies. Function bodies will be resolved later so this is wasted
3015 // effort.
3016 AstVisitor visitor = new ResolverVisitor(
3017 libraryElement, unitElement.source, typeProvider, errorListener,
3018 inheritanceManager: inheritanceManager);
3019 unit.accept(visitor);
3020 //
3021 // Prepare targets for inference.
3022 //
3023 List<VariableElement> staticVariables = <VariableElement>[];
3024 List<ClassElement> classes = <ClassElement>[];
3025 if (context.analysisOptions.strongMode) {
3026 InferrenceFinder inferrenceFinder = new InferrenceFinder();
3027 unit.accept(inferrenceFinder);
3028 staticVariables = inferrenceFinder.staticVariables;
3029 classes = inferrenceFinder.classes;
3030 }
3031 //
3032 // Record outputs.
3033 //
3034 outputs[CLASSES_IN_UNIT] = classes;
3035 outputs[INFERABLE_STATIC_VARIABLES_IN_UNIT] = staticVariables;
3036 outputs[PARTIALLY_RESOLVE_REFERENCES_ERRORS] =
3037 removeDuplicateErrors(errorListener.errors);
3038 outputs[RESOLVED_UNIT5] = unit;
3039 }
3040
3041 /**
3042 * Return a map from the names of the inputs of this kind of task to the task
3043 * input descriptors describing those inputs for a task with the
3044 * given [target].
3045 */
3046 static Map<String, TaskInput> buildInputs(AnalysisTarget target) {
3047 LibrarySpecificUnit unit = target;
3048 return <String, TaskInput>{
3049 'fullyBuiltLibraryElements': IMPORT_EXPORT_SOURCE_CLOSURE
3050 .of(unit.library)
3051 .toListOf(LIBRARY_ELEMENT5),
3052 LIBRARY_INPUT: LIBRARY_ELEMENT5.of(unit.library),
3053 UNIT_INPUT: RESOLVED_UNIT4.of(unit),
3054 TYPE_PROVIDER_INPUT: TYPE_PROVIDER.of(AnalysisContextTarget.request)
3055 };
3056 }
3057
3058 /**
3059 * Create a [PartiallyResolveUnitReferencesTask] based on the given [target]
3060 * in the given [context].
3061 */
3062 static PartiallyResolveUnitReferencesTask createTask(
3063 AnalysisContext context, AnalysisTarget target) {
3064 return new PartiallyResolveUnitReferencesTask(context, target);
3065 }
3066 }
3067
3068 /**
3069 * The helper for building the public [Namespace] of a [LibraryElement].
3070 */
3071 class PublicNamespaceBuilder {
3072 final HashMap<String, Element> definedNames = new HashMap<String, Element>();
3073
3074 /**
3075 * Build a public [Namespace] of the given [library].
3076 */
3077 Namespace build(LibraryElement library) {
3078 definedNames.clear();
3079 _addPublicNames(library.definingCompilationUnit);
3080 library.parts.forEach(_addPublicNames);
3081 return new Namespace(definedNames);
3082 }
3083
3084 /**
3085 * Add the given [element] if it has a publicly visible name.
3086 */
3087 void _addIfPublic(Element element) {
3088 String name = element.name;
3089 if (name != null && !Scope.isPrivateName(name)) {
3090 definedNames[name] = element;
3091 }
3092 }
3093
3094 /**
3095 * Add all of the public top-level names that are defined in the given
3096 * [compilationUnit].
3097 */
3098 void _addPublicNames(CompilationUnitElement compilationUnit) {
3099 compilationUnit.accessors.forEach(_addIfPublic);
3100 compilationUnit.enums.forEach(_addIfPublic);
3101 compilationUnit.functions.forEach(_addIfPublic);
3102 compilationUnit.functionTypeAliases.forEach(_addIfPublic);
3103 compilationUnit.types.forEach(_addIfPublic);
3104 }
3105 }
3106
3107 /**
3108 * Information about a library - which names it uses, which names it defines
3109 * with their externally visible dependencies.
3110 */
3111 class ReferencedNames {
3112 final Set<String> names = new Set<String>();
3113 final Map<String, Set<String>> userToDependsOn = <String, Set<String>>{};
3114
3115 /**
3116 * Updates [delta] by adding names that are changed in this library.
3117 */
3118 void addChangedElements(DartDelta delta) {
3119 bool hasProgress = true;
3120 while (hasProgress) {
3121 hasProgress = false;
3122 userToDependsOn.forEach((user, dependencies) {
3123 for (String dependency in dependencies) {
3124 if (delta.isNameAffected(dependency)) {
3125 if (delta.nameChanged(user)) {
3126 hasProgress = true;
3127 }
3128 }
3129 }
3130 });
3131 }
3132 }
3133
3134 /**
3135 * Returns `true` if the library described by this object is affected by
3136 * the given [delta].
3137 */
3138 bool isAffectedBy(DartDelta delta) {
3139 for (String name in names) {
3140 if (delta.isNameAffected(name)) {
3141 return true;
3142 }
3143 }
3144 return false;
3145 }
3146 }
3147
3148 /**
3149 * A builder for creating [ReferencedNames].
3150 *
3151 * TODO(scheglov) Record dependencies for all other top-level declarations.
3152 */
3153 class ReferencedNamesBuilder extends RecursiveAstVisitor {
3154 final ReferencedNames names;
3155 int bodyLevel = 0;
3156 Set<String> dependsOn;
3157
3158 ReferencedNamesBuilder(this.names);
3159
3160 ReferencedNames build(CompilationUnit unit) {
3161 unit.accept(this);
3162 return names;
3163 }
3164
3165 @override
3166 visitBlockFunctionBody(BlockFunctionBody node) {
3167 try {
3168 bodyLevel++;
3169 super.visitBlockFunctionBody(node);
3170 } finally {
3171 bodyLevel--;
3172 }
3173 }
3174
3175 @override
3176 visitClassDeclaration(ClassDeclaration node) {
3177 dependsOn = new Set<String>();
3178 super.visitClassDeclaration(node);
3179 names.userToDependsOn[node.name.name] = dependsOn;
3180 dependsOn = null;
3181 }
3182
3183 @override
3184 visitExpressionFunctionBody(ExpressionFunctionBody node) {
3185 try {
3186 bodyLevel++;
3187 super.visitExpressionFunctionBody(node);
3188 } finally {
3189 bodyLevel--;
3190 }
3191 }
3192
3193 @override
3194 visitSimpleIdentifier(SimpleIdentifier node) {
3195 if (!node.inDeclarationContext()) {
3196 String name = node.name;
3197 names.names.add(name);
3198 if (dependsOn != null && bodyLevel == 0) {
3199 dependsOn.add(name);
3200 }
3201 }
3202 }
3203 }
3204
3205 /**
3206 * A task that finishes resolution by requesting [RESOLVED_UNIT_NO_CONSTANTS] fo r every
3207 * unit in the libraries closure and produces [LIBRARY_ELEMENT].
3208 */
3209 class ResolveLibraryReferencesTask extends SourceBasedAnalysisTask {
3210 /**
3211 * The name of the [LIBRARY_ELEMENT5] input.
3212 */
3213 static const String LIBRARY_INPUT = 'LIBRARY_INPUT';
3214
3215 /**
3216 * The name of the list of [RESOLVED_UNIT8] input.
3217 */
3218 static const String UNITS_INPUT = 'UNITS_INPUT';
3219
3220 /**
3221 * The task descriptor describing this kind of task.
3222 */
3223 static final TaskDescriptor DESCRIPTOR = new TaskDescriptor(
3224 'ResolveLibraryReferencesTask',
3225 createTask,
3226 buildInputs,
3227 <ResultDescriptor>[LIBRARY_ELEMENT, REFERENCED_NAMES]);
3228
3229 ResolveLibraryReferencesTask(
3230 InternalAnalysisContext context, AnalysisTarget target)
3231 : super(context, target);
3232
3233 @override
3234 TaskDescriptor get descriptor => DESCRIPTOR;
3235
3236 @override
3237 void internalPerform() {
3238 //
3239 // Prepare inputs.
3240 //
3241 LibraryElement library = getRequiredInput(LIBRARY_INPUT);
3242 List<CompilationUnit> units = getRequiredInput(UNITS_INPUT);
3243 // Compute referenced names.
3244 ReferencedNames referencedNames = new ReferencedNames();
3245 for (CompilationUnit unit in units) {
3246 new ReferencedNamesBuilder(referencedNames).build(unit);
3247 }
3248 //
3249 // Record outputs.
3250 //
3251 outputs[LIBRARY_ELEMENT] = library;
3252 outputs[REFERENCED_NAMES] = referencedNames;
3253 }
3254
3255 /**
3256 * Return a map from the names of the inputs of this kind of task to the task
3257 * input descriptors describing those inputs for a task with the
3258 * given [target].
3259 */
3260 static Map<String, TaskInput> buildInputs(AnalysisTarget target) {
3261 Source source = target;
3262 return <String, TaskInput>{
3263 LIBRARY_INPUT: LIBRARY_ELEMENT5.of(source),
3264 UNITS_INPUT: UNITS.of(source).toList((Source unit) =>
3265 RESOLVED_UNIT8.of(new LibrarySpecificUnit(source, unit))),
3266 'resolvedUnits': IMPORT_EXPORT_SOURCE_CLOSURE
3267 .of(source)
3268 .toMapOf(UNITS)
3269 .toFlattenList((Source library, Source unit) =>
3270 RESOLVED_UNIT8.of(new LibrarySpecificUnit(library, unit))),
3271 };
3272 }
3273
3274 /**
3275 * Create a [ResolveLibraryReferencesTask] based on the given [target] in
3276 * the given [context].
3277 */
3278 static ResolveLibraryReferencesTask createTask(
3279 AnalysisContext context, AnalysisTarget target) {
3280 return new ResolveLibraryReferencesTask(context, target);
3281 }
3282 }
3283
3284 /**
3285 * An artifitial task that does nothing except to force type names resolution
3286 * for the defining and part units of a library.
3287 */
3288 class ResolveLibraryTypeNamesTask extends SourceBasedAnalysisTask {
3289 /**
3290 * The name of the [LIBRARY_ELEMENT4] input.
3291 */
3292 static const String LIBRARY_INPUT = 'LIBRARY_INPUT';
3293
3294 /**
3295 * The task descriptor describing this kind of task.
3296 */
3297 static final TaskDescriptor DESCRIPTOR = new TaskDescriptor(
3298 'ResolveLibraryTypeNamesTask',
3299 createTask,
3300 buildInputs,
3301 <ResultDescriptor>[LIBRARY_ELEMENT5]);
3302
3303 ResolveLibraryTypeNamesTask(
3304 InternalAnalysisContext context, AnalysisTarget target)
3305 : super(context, target);
3306
3307 @override
3308 TaskDescriptor get descriptor => DESCRIPTOR;
3309
3310 @override
3311 void internalPerform() {
3312 LibraryElement library = getRequiredInput(LIBRARY_INPUT);
3313 outputs[LIBRARY_ELEMENT5] = library;
3314 }
3315
3316 /**
3317 * Return a map from the names of the inputs of this kind of task to the task
3318 * input descriptors describing those inputs for a task with the
3319 * given [target].
3320 */
3321 static Map<String, TaskInput> buildInputs(AnalysisTarget target) {
3322 Source source = target;
3323 return <String, TaskInput>{
3324 'resolvedUnit': UNITS.of(source).toList((Source unit) =>
3325 RESOLVED_UNIT3.of(new LibrarySpecificUnit(source, unit))),
3326 LIBRARY_INPUT: LIBRARY_ELEMENT4.of(source)
3327 };
3328 }
3329
3330 /**
3331 * Create a [ResolveLibraryTypeNamesTask] based on the given [target] in
3332 * the given [context].
3333 */
3334 static ResolveLibraryTypeNamesTask createTask(
3335 AnalysisContext context, AnalysisTarget target) {
3336 return new ResolveLibraryTypeNamesTask(context, target);
3337 }
3338 }
3339
3340 /**
3341 * A task that builds [RESOLVED_UNIT8] for a unit.
3342 */
3343 class ResolveUnitReferencesTask extends SourceBasedAnalysisTask {
3344 /**
3345 * The name of the [LIBRARY_ELEMENT5] input.
3346 */
3347 static const String LIBRARY_INPUT = 'LIBRARY_INPUT';
3348
3349 /**
3350 * The name of the [RESOLVED_UNIT4] input.
3351 */
3352 static const String UNIT_INPUT = 'UNIT_INPUT';
3353
3354 /**
3355 * The name of the [TYPE_PROVIDER] input.
3356 */
3357 static const String TYPE_PROVIDER_INPUT = 'TYPE_PROVIDER_INPUT';
3358
3359 /**
3360 * The task descriptor describing this kind of task.
3361 */
3362 static final TaskDescriptor DESCRIPTOR = new TaskDescriptor(
3363 'ResolveUnitReferencesTask',
3364 createTask,
3365 buildInputs,
3366 <ResultDescriptor>[RESOLVE_REFERENCES_ERRORS, RESOLVED_UNIT8]);
3367
3368 ResolveUnitReferencesTask(
3369 InternalAnalysisContext context, AnalysisTarget target)
3370 : super(context, target);
3371
3372 @override
3373 TaskDescriptor get descriptor => DESCRIPTOR;
3374
3375 @override
3376 void internalPerform() {
3377 RecordingErrorListener errorListener = new RecordingErrorListener();
3378 //
3379 // Prepare inputs.
3380 //
3381 LibraryElement libraryElement = getRequiredInput(LIBRARY_INPUT);
3382 CompilationUnit unit = getRequiredInput(UNIT_INPUT);
3383 CompilationUnitElement unitElement = unit.element;
3384 TypeProvider typeProvider = getRequiredInput(TYPE_PROVIDER_INPUT);
3385 //
3386 // Resolve references.
3387 //
3388 InheritanceManager inheritanceManager =
3389 new InheritanceManager(libraryElement);
3390 AstVisitor visitor = new ResolverVisitor(
3391 libraryElement, unitElement.source, typeProvider, errorListener,
3392 inheritanceManager: inheritanceManager);
3393 unit.accept(visitor);
3394 //
3395 // Record outputs.
3396 //
3397 outputs[RESOLVE_REFERENCES_ERRORS] =
3398 removeDuplicateErrors(errorListener.errors);
3399 outputs[RESOLVED_UNIT8] = unit;
3400 }
3401
3402 /**
3403 * Return a map from the names of the inputs of this kind of task to the task
3404 * input descriptors describing those inputs for a task with the
3405 * given [target].
3406 */
3407 static Map<String, TaskInput> buildInputs(AnalysisTarget target) {
3408 LibrarySpecificUnit unit = target;
3409 return <String, TaskInput>{
3410 'fullyBuiltLibraryElements': IMPORT_EXPORT_SOURCE_CLOSURE
3411 .of(unit.library)
3412 .toListOf(LIBRARY_ELEMENT5),
3413 LIBRARY_INPUT: LIBRARY_ELEMENT5.of(unit.library),
3414 UNIT_INPUT: RESOLVED_UNIT4.of(unit),
3415 TYPE_PROVIDER_INPUT: TYPE_PROVIDER.of(AnalysisContextTarget.request)
3416 };
3417 }
3418
3419 /**
3420 * Create a [ResolveUnitReferencesTask] based on the given [target] in
3421 * the given [context].
3422 */
3423 static ResolveUnitReferencesTask createTask(
3424 AnalysisContext context, AnalysisTarget target) {
3425 return new ResolveUnitReferencesTask(context, target);
3426 }
3427 }
3428
3429 /**
3430 * A task that builds [RESOLVED_UNIT3] for a unit.
3431 */
3432 class ResolveUnitTypeNamesTask extends SourceBasedAnalysisTask {
3433 /**
3434 * The name of the input whose value is the defining [LIBRARY_ELEMENT4].
3435 */
3436 static const String LIBRARY_INPUT = 'LIBRARY_INPUT';
3437
3438 /**
3439 * The name of the [RESOLVED_UNIT2] input.
3440 */
3441 static const String UNIT_INPUT = 'UNIT_INPUT';
3442
3443 /**
3444 * The name of the [TYPE_PROVIDER] input.
3445 */
3446 static const String TYPE_PROVIDER_INPUT = 'TYPE_PROVIDER_INPUT';
3447
3448 /**
3449 * The task descriptor describing this kind of task.
3450 */
3451 static final TaskDescriptor DESCRIPTOR = new TaskDescriptor(
3452 'ResolveUnitTypeNamesTask',
3453 createTask,
3454 buildInputs,
3455 <ResultDescriptor>[RESOLVE_TYPE_NAMES_ERRORS, RESOLVED_UNIT3]);
3456
3457 ResolveUnitTypeNamesTask(
3458 InternalAnalysisContext context, AnalysisTarget target)
3459 : super(context, target);
3460
3461 @override
3462 TaskDescriptor get descriptor => DESCRIPTOR;
3463
3464 @override
3465 void internalPerform() {
3466 RecordingErrorListener errorListener = new RecordingErrorListener();
3467 //
3468 // Prepare inputs.
3469 //
3470 LibraryElement library = getRequiredInput(LIBRARY_INPUT);
3471 CompilationUnit unit = getRequiredInput(UNIT_INPUT);
3472 CompilationUnitElement unitElement = unit.element;
3473 TypeProvider typeProvider = getRequiredInput(TYPE_PROVIDER_INPUT);
3474 //
3475 // Resolve TypeName nodes.
3476 //
3477 TypeResolverVisitor visitor = new TypeResolverVisitor(
3478 library, unitElement.source, typeProvider, errorListener);
3479 unit.accept(visitor);
3480 //
3481 // Record outputs.
3482 //
3483 outputs[RESOLVE_TYPE_NAMES_ERRORS] =
3484 removeDuplicateErrors(errorListener.errors);
3485 outputs[RESOLVED_UNIT3] = unit;
3486 }
3487
3488 /**
3489 * Return a map from the names of the inputs of this kind of task to the task
3490 * input descriptors describing those inputs for a task with the
3491 * given [target].
3492 */
3493 static Map<String, TaskInput> buildInputs(AnalysisTarget target) {
3494 LibrarySpecificUnit unit = target;
3495 return <String, TaskInput>{
3496 'importsExportNamespace':
3497 IMPORTED_LIBRARIES.of(unit.library).toMapOf(LIBRARY_ELEMENT4),
3498 LIBRARY_INPUT: LIBRARY_ELEMENT4.of(unit.library),
3499 UNIT_INPUT: RESOLVED_UNIT2.of(unit),
3500 TYPE_PROVIDER_INPUT: TYPE_PROVIDER.of(AnalysisContextTarget.request)
3501 };
3502 }
3503
3504 /**
3505 * Create a [ResolveUnitTypeNamesTask] based on the given [target] in
3506 * the given [context].
3507 */
3508 static ResolveUnitTypeNamesTask createTask(
3509 AnalysisContext context, AnalysisTarget target) {
3510 return new ResolveUnitTypeNamesTask(context, target);
3511 }
3512 }
3513
3514 /**
3515 * A task that builds [RESOLVED_UNIT4] for a unit.
3516 */
3517 class ResolveVariableReferencesTask extends SourceBasedAnalysisTask {
3518 /**
3519 * The name of the [LIBRARY_ELEMENT1] input.
3520 */
3521 static const String LIBRARY_INPUT = 'LIBRARY_INPUT';
3522
3523 /**
3524 * The name of the [RESOLVED_UNIT3] input.
3525 */
3526 static const String UNIT_INPUT = 'UNIT_INPUT';
3527
3528 /**
3529 * The name of the [TYPE_PROVIDER] input.
3530 */
3531 static const String TYPE_PROVIDER_INPUT = 'TYPE_PROVIDER_INPUT';
3532
3533 /**
3534 * The task descriptor describing this kind of task.
3535 */
3536 static final TaskDescriptor DESCRIPTOR = new TaskDescriptor(
3537 'ResolveVariableReferencesTask',
3538 createTask,
3539 buildInputs,
3540 <ResultDescriptor>[RESOLVED_UNIT4, VARIABLE_REFERENCE_ERRORS]);
3541
3542 ResolveVariableReferencesTask(
3543 InternalAnalysisContext context, AnalysisTarget target)
3544 : super(context, target);
3545
3546 @override
3547 TaskDescriptor get descriptor => DESCRIPTOR;
3548
3549 @override
3550 void internalPerform() {
3551 RecordingErrorListener errorListener = new RecordingErrorListener();
3552 //
3553 // Prepare inputs.
3554 //
3555 LibraryElement libraryElement = getRequiredInput(LIBRARY_INPUT);
3556 CompilationUnit unit = getRequiredInput(UNIT_INPUT);
3557 CompilationUnitElement unitElement = unit.element;
3558 //
3559 // Resolve local variables.
3560 //
3561 TypeProvider typeProvider = getRequiredInput(TYPE_PROVIDER_INPUT);
3562 Scope nameScope = new LibraryScope(libraryElement, errorListener);
3563 AstVisitor visitor = new VariableResolverVisitor(
3564 libraryElement, unitElement.source, typeProvider, errorListener,
3565 nameScope: nameScope);
3566 unit.accept(visitor);
3567 //
3568 // Record outputs.
3569 //
3570 outputs[RESOLVED_UNIT4] = unit;
3571 outputs[VARIABLE_REFERENCE_ERRORS] =
3572 removeDuplicateErrors(errorListener.errors);
3573 }
3574
3575 /**
3576 * Return a map from the names of the inputs of this kind of task to the task
3577 * input descriptors describing those inputs for a task with the
3578 * given [target].
3579 */
3580 static Map<String, TaskInput> buildInputs(AnalysisTarget target) {
3581 LibrarySpecificUnit unit = target;
3582 return <String, TaskInput>{
3583 LIBRARY_INPUT: LIBRARY_ELEMENT1.of(unit.library),
3584 UNIT_INPUT: RESOLVED_UNIT1.of(unit),
3585 TYPE_PROVIDER_INPUT: TYPE_PROVIDER.of(AnalysisContextTarget.request)
3586 };
3587 }
3588
3589 /**
3590 * Create a [ResolveVariableReferencesTask] based on the given [target] in
3591 * the given [context].
3592 */
3593 static ResolveVariableReferencesTask createTask(
3594 AnalysisContext context, AnalysisTarget target) {
3595 return new ResolveVariableReferencesTask(context, target);
3596 }
3597 }
3598
3599 /**
3600 * A task that scans the content of a file, producing a set of Dart tokens.
3601 */
3602 class ScanDartTask extends SourceBasedAnalysisTask {
3603 /**
3604 * The name of the input whose value is the content of the file.
3605 */
3606 static const String CONTENT_INPUT_NAME = 'CONTENT_INPUT_NAME';
3607
3608 /**
3609 * The task descriptor describing this kind of task.
3610 */
3611 static final TaskDescriptor DESCRIPTOR = new TaskDescriptor(
3612 'ScanDartTask',
3613 createTask,
3614 buildInputs,
3615 <ResultDescriptor>[LINE_INFO, SCAN_ERRORS, TOKEN_STREAM]);
3616
3617 /**
3618 * Initialize a newly created task to access the content of the source
3619 * associated with the given [target] in the given [context].
3620 */
3621 ScanDartTask(InternalAnalysisContext context, AnalysisTarget target)
3622 : super(context, target);
3623
3624 @override
3625 TaskDescriptor get descriptor => DESCRIPTOR;
3626
3627 @override
3628 void internalPerform() {
3629 Source source = getRequiredSource();
3630
3631 RecordingErrorListener errorListener = new RecordingErrorListener();
3632 if (context.getModificationStamp(target.source) < 0) {
3633 String message = 'Content could not be read';
3634 if (context is InternalAnalysisContext) {
3635 CacheEntry entry =
3636 (context as InternalAnalysisContext).getCacheEntry(target);
3637 CaughtException exception = entry.exception;
3638 if (exception != null) {
3639 message = exception.toString();
3640 }
3641 }
3642 errorListener.onError(new AnalysisError(
3643 source, 0, 0, ScannerErrorCode.UNABLE_GET_CONTENT, [message]));
3644 }
3645 if (target is DartScript) {
3646 DartScript script = target;
3647 List<ScriptFragment> fragments = script.fragments;
3648 if (fragments.length < 1) {
3649 throw new AnalysisException('Cannot scan scripts with no fragments');
3650 } else if (fragments.length > 1) {
3651 throw new AnalysisException(
3652 'Cannot scan scripts with multiple fragments');
3653 }
3654 ScriptFragment fragment = fragments[0];
3655
3656 Scanner scanner = new Scanner(
3657 source,
3658 new SubSequenceReader(fragment.content, fragment.offset),
3659 errorListener);
3660 scanner.setSourceStart(fragment.line, fragment.column);
3661 scanner.preserveComments = context.analysisOptions.preserveComments;
3662
3663 outputs[TOKEN_STREAM] = scanner.tokenize();
3664 outputs[LINE_INFO] = new LineInfo(scanner.lineStarts);
3665 outputs[SCAN_ERRORS] = removeDuplicateErrors(errorListener.errors);
3666 } else if (target is Source) {
3667 String content = getRequiredInput(CONTENT_INPUT_NAME);
3668
3669 Scanner scanner =
3670 new Scanner(source, new CharSequenceReader(content), errorListener);
3671 scanner.preserveComments = context.analysisOptions.preserveComments;
3672
3673 outputs[TOKEN_STREAM] = scanner.tokenize();
3674 outputs[LINE_INFO] = new LineInfo(scanner.lineStarts);
3675 outputs[SCAN_ERRORS] = removeDuplicateErrors(errorListener.errors);
3676 } else {
3677 throw new AnalysisException(
3678 'Cannot scan Dart code from a ${target.runtimeType}');
3679 }
3680 }
3681
3682 /**
3683 * Return a map from the names of the inputs of this kind of task to the task
3684 * input descriptors describing those inputs for a task with the given
3685 * [source].
3686 */
3687 static Map<String, TaskInput> buildInputs(AnalysisTarget target) {
3688 if (target is Source) {
3689 return <String, TaskInput>{CONTENT_INPUT_NAME: CONTENT.of(target)};
3690 } else if (target is DartScript) {
3691 // This task does not use the following input; it is included only to add
3692 // a dependency between this value and the containing source so that when
3693 // the containing source is modified these results will be invalidated.
3694 return <String, TaskInput>{'-': DART_SCRIPTS.of(target.source)};
3695 }
3696 throw new AnalysisException(
3697 'Cannot build inputs for a ${target.runtimeType}');
3698 }
3699
3700 /**
3701 * Create a [ScanDartTask] based on the given [target] in the given [context].
3702 */
3703 static ScanDartTask createTask(
3704 AnalysisContext context, AnalysisTarget target) {
3705 return new ScanDartTask(context, target);
3706 }
3707 }
3708
3709 /**
3710 * A task that builds [VERIFY_ERRORS] for a unit.
3711 */
3712 class VerifyUnitTask extends SourceBasedAnalysisTask {
3713 /**
3714 * The name of the [RESOLVED_UNIT] input.
3715 */
3716 static const String UNIT_INPUT = 'UNIT_INPUT';
3717
3718 /**
3719 * The name of the [TYPE_PROVIDER] input.
3720 */
3721 static const String TYPE_PROVIDER_INPUT = 'TYPE_PROVIDER_INPUT';
3722
3723 /**
3724 * The task descriptor describing this kind of task.
3725 */
3726 static final TaskDescriptor DESCRIPTOR = new TaskDescriptor('VerifyUnitTask',
3727 createTask, buildInputs, <ResultDescriptor>[VERIFY_ERRORS]);
3728
3729 /**
3730 * The [ErrorReporter] to report errors to.
3731 */
3732 ErrorReporter errorReporter;
3733
3734 VerifyUnitTask(InternalAnalysisContext context, AnalysisTarget target)
3735 : super(context, target);
3736
3737 @override
3738 TaskDescriptor get descriptor => DESCRIPTOR;
3739
3740 @override
3741 void internalPerform() {
3742 RecordingErrorListener errorListener = new RecordingErrorListener();
3743 Source source = getRequiredSource();
3744 errorReporter = new ErrorReporter(errorListener, source);
3745 //
3746 // Prepare inputs.
3747 //
3748 TypeProvider typeProvider = getRequiredInput(TYPE_PROVIDER_INPUT);
3749 CompilationUnit unit = getRequiredInput(UNIT_INPUT);
3750 CompilationUnitElement unitElement = unit.element;
3751 LibraryElement libraryElement = unitElement.library;
3752 //
3753 // Validate the directives.
3754 //
3755 validateDirectives(unit);
3756 //
3757 // Use the ConstantVerifier to compute errors.
3758 //
3759 ConstantVerifier constantVerifier = new ConstantVerifier(
3760 errorReporter, libraryElement, typeProvider, context.declaredVariables);
3761 unit.accept(constantVerifier);
3762 //
3763 // Use the ErrorVerifier to compute errors.
3764 //
3765 ErrorVerifier errorVerifier = new ErrorVerifier(
3766 errorReporter,
3767 libraryElement,
3768 typeProvider,
3769 new InheritanceManager(libraryElement),
3770 context.analysisOptions.enableSuperMixins);
3771 unit.accept(errorVerifier);
3772 //
3773 // Record outputs.
3774 //
3775 outputs[VERIFY_ERRORS] = removeDuplicateErrors(errorListener.errors);
3776 }
3777
3778 /**
3779 * Check each directive in the given [unit] to see if the referenced source
3780 * exists and report an error if it does not.
3781 */
3782 void validateDirectives(CompilationUnit unit) {
3783 for (Directive directive in unit.directives) {
3784 if (directive is UriBasedDirective) {
3785 validateReferencedSource(directive);
3786 }
3787 }
3788 }
3789
3790 /**
3791 * Check the given [directive] to see if the referenced source exists and
3792 * report an error if it does not.
3793 */
3794 void validateReferencedSource(UriBasedDirective directive) {
3795 Source source = directive.source;
3796 if (source != null) {
3797 if (context.exists(source)) {
3798 return;
3799 }
3800 } else {
3801 // Don't report errors already reported by ParseDartTask.resolveDirective
3802 if (directive.validate() != null) {
3803 return;
3804 }
3805 }
3806 StringLiteral uriLiteral = directive.uri;
3807 errorReporter.reportErrorForNode(CompileTimeErrorCode.URI_DOES_NOT_EXIST,
3808 uriLiteral, [directive.uriContent]);
3809 }
3810
3811 /**
3812 * Return a map from the names of the inputs of this kind of task to the task
3813 * input descriptors describing those inputs for a task with the
3814 * given [target].
3815 */
3816 static Map<String, TaskInput> buildInputs(AnalysisTarget target) {
3817 LibrarySpecificUnit unit = target;
3818 return <String, TaskInput>{
3819 'resolvedUnits': IMPORT_EXPORT_SOURCE_CLOSURE
3820 .of(unit.library)
3821 .toMapOf(UNITS)
3822 .toFlattenList((Source library, Source unit) =>
3823 RESOLVED_UNIT.of(new LibrarySpecificUnit(library, unit))),
3824 UNIT_INPUT: RESOLVED_UNIT.of(unit),
3825 TYPE_PROVIDER_INPUT: TYPE_PROVIDER.of(AnalysisContextTarget.request)
3826 };
3827 }
3828
3829 /**
3830 * Create a [VerifyUnitTask] based on the given [target] in
3831 * the given [context].
3832 */
3833 static VerifyUnitTask createTask(
3834 AnalysisContext context, AnalysisTarget target) {
3835 return new VerifyUnitTask(context, target);
3836 }
3837 }
3838
3839 /**
3840 * A [TaskInput] whose value is a list of library sources exported directly
3841 * or indirectly by the target [Source].
3842 *
3843 * [resultDescriptor] is the type of result which should be produced for each
3844 * target [Source].
3845 */
3846 class _ExportSourceClosureTaskInput extends TaskInputImpl<List<Source>> {
3847 final Source target;
3848 final ResultDescriptor resultDescriptor;
3849
3850 _ExportSourceClosureTaskInput(this.target, this.resultDescriptor);
3851
3852 @override
3853 TaskInputBuilder<List<Source>> createBuilder() =>
3854 new _SourceClosureTaskInputBuilder(
3855 target, _SourceClosureKind.EXPORT, resultDescriptor);
3856 }
3857
3858 /**
3859 * A [TaskInput] whose value is a list of library sources imported or exported,
3860 * directly or indirectly by the target [Source].
3861 *
3862 * [resultDescriptor] is the type of result which should be produced for each
3863 * target [Source].
3864 */
3865 class _ImportExportSourceClosureTaskInput extends TaskInputImpl<List<Source>> {
3866 final Source target;
3867 final ResultDescriptor resultDescriptor;
3868
3869 _ImportExportSourceClosureTaskInput(this.target, this.resultDescriptor);
3870
3871 @override
3872 TaskInputBuilder<List<Source>> createBuilder() =>
3873 new _SourceClosureTaskInputBuilder(
3874 target, _SourceClosureKind.IMPORT_EXPORT, resultDescriptor);
3875 }
3876
3877 /**
3878 * A [TaskInput] whose value is a list of library sources imported directly
3879 * or indirectly by the target [Source].
3880 *
3881 * [resultDescriptor] is the type of result which should be produced for each
3882 * target [Source].
3883 */
3884 class _ImportSourceClosureTaskInput extends TaskInputImpl<List<Source>> {
3885 final Source target;
3886 final ResultDescriptor resultDescriptor;
3887
3888 _ImportSourceClosureTaskInput(this.target, this.resultDescriptor);
3889
3890 @override
3891 TaskInputBuilder<List<Source>> createBuilder() =>
3892 new _SourceClosureTaskInputBuilder(
3893 target, _SourceClosureKind.IMPORT, resultDescriptor);
3894 }
3895
3896 /**
3897 * The kind of the source closure to build.
3898 */
3899 enum _SourceClosureKind { IMPORT, EXPORT, IMPORT_EXPORT }
3900
3901 /**
3902 * A [TaskInputBuilder] to build values for [_ImportSourceClosureTaskInput].
3903 */
3904 class _SourceClosureTaskInputBuilder implements TaskInputBuilder<List<Source>> {
3905 final _SourceClosureKind kind;
3906 final Set<LibraryElement> _libraries = new HashSet<LibraryElement>();
3907 final List<Source> _newSources = <Source>[];
3908
3909 @override
3910 final ResultDescriptor currentResult;
3911
3912 Source currentTarget;
3913
3914 _SourceClosureTaskInputBuilder(
3915 Source librarySource, this.kind, this.currentResult) {
3916 _newSources.add(librarySource);
3917 }
3918
3919 @override
3920 void set currentValue(Object value) {
3921 LibraryElement library = value;
3922 if (_libraries.add(library)) {
3923 if (kind == _SourceClosureKind.IMPORT ||
3924 kind == _SourceClosureKind.IMPORT_EXPORT) {
3925 for (ImportElement importElement in library.imports) {
3926 Source importedSource = importElement.importedLibrary.source;
3927 _newSources.add(importedSource);
3928 }
3929 }
3930 if (kind == _SourceClosureKind.EXPORT ||
3931 kind == _SourceClosureKind.IMPORT_EXPORT) {
3932 for (ExportElement exportElement in library.exports) {
3933 Source exportedSource = exportElement.exportedLibrary.source;
3934 _newSources.add(exportedSource);
3935 }
3936 }
3937 }
3938 }
3939
3940 @override
3941 List<Source> get inputValue {
3942 return _libraries.map((LibraryElement library) => library.source).toList();
3943 }
3944
3945 @override
3946 void currentValueNotAvailable() {
3947 // Nothing needs to be done. moveNext() will simply go on to the next new
3948 // source.
3949 }
3950
3951 @override
3952 bool moveNext() {
3953 if (_newSources.isEmpty) {
3954 return false;
3955 }
3956 currentTarget = _newSources.removeLast();
3957 return true;
3958 }
3959 }
OLDNEW

Powered by Google App Engine
This is Rietveld 408576698