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

Side by Side Diff: observatory_pub_packages/analyzer/src/generated/engine.dart

Issue 816693004: Add observatory_pub_packages snapshot to third_party (Closed) Base URL: http://dart.googlecode.com/svn/third_party/
Patch Set: Created 6 years ago
Use n/p to move between diff chunks; N/P to move between comments. Draft comments are only viewable by you.
Jump to:
View unified diff | Download patch | Annotate | Revision Log
OLDNEW
(Empty)
1 // Copyright (c) 2014, 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 // This code was auto-generated, is not intended to be edited, and is subject to
6 // significant change. Please see the README file for more information.
7
8 library engine;
9
10 import 'dart:collection';
11 import 'java_core.dart';
12 import 'java_engine.dart';
13 import 'utilities_collection.dart';
14 import 'utilities_general.dart';
15 import 'instrumentation.dart';
16 import 'error.dart';
17 import 'source.dart';
18 import 'scanner.dart';
19 import 'ast.dart';
20 import 'parser.dart' show Parser, IncrementalParser;
21 import 'sdk.dart' show DartSdk;
22 import 'constant.dart';
23 import 'element.dart';
24 import 'resolver.dart';
25 import 'html.dart' as ht;
26
27 /**
28 * Instances of the class `AnalysisCache` implement an LRU cache of information related to
29 * analysis.
30 */
31 class AnalysisCache {
32 /**
33 * An array containing the partitions of which this cache is comprised.
34 */
35 final List<CachePartition> _partitions;
36
37 /**
38 * A flag used to control whether trace information should be produced when th e content of the
39 * cache is modified.
40 */
41 static bool _TRACE_CHANGES = false;
42
43 /**
44 * Initialize a newly created cache to have the given partitions. The partitio ns will be searched
45 * in the order in which they appear in the array, so the most specific partit ion (usually an
46 * [SdkCachePartition]) should be first and the most general (usually a
47 * [UniversalCachePartition]) last.
48 *
49 * @param partitions the partitions for the newly created cache
50 */
51 AnalysisCache(this._partitions);
52
53 /**
54 * Record that the AST associated with the given source was just read from the cache.
55 *
56 * @param source the source whose AST was accessed
57 */
58 void accessedAst(Source source) {
59 int count = _partitions.length;
60 for (int i = 0; i < count; i++) {
61 if (_partitions[i].contains(source)) {
62 _partitions[i].accessedAst(source);
63 return;
64 }
65 }
66 }
67
68 /**
69 * Return the entry associated with the given source.
70 *
71 * @param source the source whose entry is to be returned
72 * @return the entry associated with the given source
73 */
74 SourceEntry get(Source source) {
75 int count = _partitions.length;
76 for (int i = 0; i < count; i++) {
77 if (_partitions[i].contains(source)) {
78 return _partitions[i].get(source);
79 }
80 }
81 return null;
82 }
83
84 /**
85 * Return the number of entries in this cache that have an AST associated with them.
86 *
87 * @return the number of entries in this cache that have an AST associated wit h them
88 */
89 int get astSize => _partitions[_partitions.length - 1].astSize;
90
91 /**
92 * Return information about each of the partitions in this cache.
93 *
94 * @return information about each of the partitions in this cache
95 */
96 List<AnalysisContextStatistics_PartitionData> get partitionData {
97 int count = _partitions.length;
98 List<AnalysisContextStatistics_PartitionData> data = new List<AnalysisContex tStatistics_PartitionData>(count);
99 for (int i = 0; i < count; i++) {
100 CachePartition partition = _partitions[i];
101 data[i] = new AnalysisContextStatisticsImpl_PartitionDataImpl(partition.as tSize, partition.map.length);
102 }
103 return data;
104 }
105
106 /**
107 * Return an iterator returning all of the map entries mapping sources to cach e entries.
108 *
109 * @return an iterator returning all of the map entries mapping sources to cac he entries
110 */
111 MapIterator<Source, SourceEntry> iterator() {
112 int count = _partitions.length;
113 List<Map<Source, SourceEntry>> maps = new List<Map>(count);
114 for (int i = 0; i < count; i++) {
115 maps[i] = _partitions[i].map;
116 }
117 return new MultipleMapIterator<Source, SourceEntry>(maps);
118 }
119
120 /**
121 * Associate the given entry with the given source.
122 *
123 * @param source the source with which the entry is to be associated
124 * @param entry the entry to be associated with the source
125 */
126 void put(Source source, SourceEntry entry) {
127 (entry as SourceEntryImpl).fixExceptionState();
128 int count = _partitions.length;
129 for (int i = 0; i < count; i++) {
130 if (_partitions[i].contains(source)) {
131 if (_TRACE_CHANGES) {
132 try {
133 SourceEntry oldEntry = _partitions[i].get(source);
134 if (oldEntry == null) {
135 AnalysisEngine.instance.logger.logInformation("Added a cache entry for '${source.fullName}'.");
136 } else {
137 AnalysisEngine.instance.logger.logInformation("Modified the cache entry for ${source.fullName}'. Diff = ${(entry as SourceEntryImpl).getDiff(oldEn try)}");
138 }
139 } catch (exception) {
140 // Ignored
141 JavaSystem.currentTimeMillis();
142 }
143 }
144 _partitions[i].put(source, entry);
145 return;
146 }
147 }
148 }
149
150 /**
151 * Remove all information related to the given source from this cache.
152 *
153 * @param source the source to be removed
154 */
155 void remove(Source source) {
156 int count = _partitions.length;
157 for (int i = 0; i < count; i++) {
158 if (_partitions[i].contains(source)) {
159 if (_TRACE_CHANGES) {
160 try {
161 AnalysisEngine.instance.logger.logInformation("Removed the cache ent ry for ${source.fullName}'.");
162 } catch (exception) {
163 // Ignored
164 JavaSystem.currentTimeMillis();
165 }
166 }
167 _partitions[i].remove(source);
168 return;
169 }
170 }
171 }
172
173 /**
174 * Record that the AST associated with the given source was just removed from the cache.
175 *
176 * @param source the source whose AST was removed
177 */
178 void removedAst(Source source) {
179 int count = _partitions.length;
180 for (int i = 0; i < count; i++) {
181 if (_partitions[i].contains(source)) {
182 _partitions[i].removedAst(source);
183 return;
184 }
185 }
186 }
187
188 /**
189 * Return the number of sources that are mapped to cache entries.
190 *
191 * @return the number of sources that are mapped to cache entries
192 */
193 int size() {
194 int size = 0;
195 int count = _partitions.length;
196 for (int i = 0; i < count; i++) {
197 size += _partitions[i].size();
198 }
199 return size;
200 }
201
202 /**
203 * Record that the AST associated with the given source was just stored to the cache.
204 *
205 * @param source the source whose AST was stored
206 */
207 void storedAst(Source source) {
208 int count = _partitions.length;
209 for (int i = 0; i < count; i++) {
210 if (_partitions[i].contains(source)) {
211 _partitions[i].storedAst(source);
212 return;
213 }
214 }
215 }
216 }
217
218 /**
219 * The interface `AnalysisContext` defines the behavior of objects that represen t a context in
220 * which a single analysis can be performed and incrementally maintained. The co ntext includes such
221 * information as the version of the SDK being analyzed against as well as the p ackage-root used to
222 * resolve 'package:' URI's. (Both of which are known indirectly through the [So urceFactory
223 ].)
224 *
225 * An analysis context also represents the state of the analysis, which includes knowing which
226 * sources have been included in the analysis (either directly or indirectly) an d the results of the
227 * analysis. Sources must be added and removed from the context using the method
228 * [applyChanges], which is also used to notify the context when sources have be en
229 * modified and, consequently, previously known results might have been invalida ted.
230 *
231 * There are two ways to access the results of the analysis. The most common is to use one of the
232 * 'get' methods to access the results. The 'get' methods have the advantage tha t they will always
233 * return quickly, but have the disadvantage that if the results are not current ly available they
234 * will return either nothing or in some cases an incomplete result. The second way to access
235 * results is by using one of the 'compute' methods. The 'compute' methods will always attempt to
236 * compute the requested results but might block the caller for a significant pe riod of time.
237 *
238 * When results have been invalidated, have never been computed (as is the case for newly added
239 * sources), or have been removed from the cache, they are <b>not</b> automatica lly recreated. They
240 * will only be recreated if one of the 'compute' methods is invoked.
241 *
242 * However, this is not always acceptable. Some clients need to keep the analysi s results
243 * up-to-date. For such clients there is a mechanism that allows them to increme ntally perform
244 * needed analysis and get notified of the consequent changes to the analysis re sults. This
245 * mechanism is realized by the method [performAnalysisTask].
246 *
247 * Analysis engine allows for having more than one context. This can be used, fo r example, to
248 * perform one analysis based on the state of files on disk and a separate analy sis based on the
249 * state of those files in open editors. It can also be used to perform an analy sis based on a
250 * proposed future state, such as the state after a refactoring.
251 */
252 abstract class AnalysisContext {
253 /**
254 * Add the given listener to the list of objects that are to be notified when various analysis
255 * results are produced in this context.
256 *
257 * @param listener the listener to be added
258 */
259 void addListener(AnalysisListener listener);
260
261 /**
262 * Apply the given delta to change the level of analysis that will be performe d for the sources
263 * known to this context.
264 *
265 * @param delta a description of the level of analysis that should be performe d for some sources
266 */
267 void applyAnalysisDelta(AnalysisDelta delta);
268
269 /**
270 * Apply the changes specified by the given change set to this context. Any an alysis results that
271 * have been invalidated by these changes will be removed.
272 *
273 * @param changeSet a description of the changes that are to be applied
274 */
275 void applyChanges(ChangeSet changeSet);
276
277 /**
278 * Return the documentation comment for the given element as it appears in the original source
279 * (complete with the beginning and ending delimiters) for block documentation comments, or lines
280 * starting with `"///"` and separated with `"\n"` characters for end-of-line
281 * documentation comments, or `null` if the element does not have a documentat ion comment
282 * associated with it. This can be a long-running operation if the information needed to access
283 * the comment is not cached.
284 *
285 * <b>Note:</b> This method cannot be used in an async environment.
286 *
287 * @param element the element whose documentation comment is to be returned
288 * @return the element's documentation comment
289 * @throws AnalysisException if the documentation comment could not be determi ned because the
290 * analysis could not be performed
291 */
292 String computeDocumentationComment(Element element);
293
294 /**
295 * Return an array containing all of the errors associated with the given sour ce. If the errors
296 * are not already known then the source will be analyzed in order to determin e the errors
297 * associated with it.
298 *
299 * <b>Note:</b> This method cannot be used in an async environment.
300 *
301 * @param source the source whose errors are to be returned
302 * @return all of the errors associated with the given source
303 * @throws AnalysisException if the errors could not be determined because the analysis could not
304 * be performed
305 * @see #getErrors(Source)
306 */
307 List<AnalysisError> computeErrors(Source source);
308
309 /**
310 * Return the element model corresponding to the HTML file defined by the give n source. If the
311 * element model does not yet exist it will be created. The process of creatin g an element model
312 * for an HTML file can be long-running, depending on the size of the file and the number of
313 * libraries that are defined in it (via script tags) that also need to have a model built for
314 * them.
315 *
316 * <b>Note:</b> This method cannot be used in an async environment.
317 *
318 * @param source the source defining the HTML file whose element model is to b e returned
319 * @return the element model corresponding to the HTML file defined by the giv en source
320 * @throws AnalysisException if the element model could not be determined beca use the analysis
321 * could not be performed
322 * @see #getHtmlElement(Source)
323 */
324 HtmlElement computeHtmlElement(Source source);
325
326 /**
327 * Return the kind of the given source, computing it's kind if it is not alrea dy known. Return
328 * [SourceKind#UNKNOWN] if the source is not contained in this context.
329 *
330 * <b>Note:</b> This method cannot be used in an async environment.
331 *
332 * @param source the source whose kind is to be returned
333 * @return the kind of the given source
334 * @see #getKindOf(Source)
335 */
336 SourceKind computeKindOf(Source source);
337
338 /**
339 * Return the element model corresponding to the library defined by the given source. If the
340 * element model does not yet exist it will be created. The process of creatin g an element model
341 * for a library can long-running, depending on the size of the library and th e number of
342 * libraries that are imported into it that also need to have a model built fo r them.
343 *
344 * <b>Note:</b> This method cannot be used in an async environment.
345 *
346 * @param source the source defining the library whose element model is to be returned
347 * @return the element model corresponding to the library defined by the given source
348 * @throws AnalysisException if the element model could not be determined beca use the analysis
349 * could not be performed
350 * @see #getLibraryElement(Source)
351 */
352 LibraryElement computeLibraryElement(Source source);
353
354 /**
355 * Return the line information for the given source, or `null` if the source i s not of a
356 * recognized kind (neither a Dart nor HTML file). If the line information was not previously
357 * known it will be created. The line information is used to map offsets from the beginning of the
358 * source to line and column pairs.
359 *
360 * <b>Note:</b> This method cannot be used in an async environment.
361 *
362 * @param source the source whose line information is to be returned
363 * @return the line information for the given source
364 * @throws AnalysisException if the line information could not be determined b ecause the analysis
365 * could not be performed
366 * @see #getLineInfo(Source)
367 */
368 LineInfo computeLineInfo(Source source);
369
370 /**
371 * Notifies the context that the client is going to stop using this context.
372 */
373 void dispose();
374
375 /**
376 * Return `true` if the given source exists.
377 *
378 * This method should be used rather than the method [Source#exists] because c ontexts can
379 * have local overrides of the content of a source that the source is not awar e of and a source
380 * with local content is considered to exist even if there is no file on disk.
381 *
382 * @param source the source whose modification stamp is to be returned
383 * @return `true` if the source exists
384 */
385 bool exists(Source source);
386
387 /**
388 * Create a new context in which analysis can be performed. Any sources in the specified container
389 * will be removed from this context and added to the newly created context.
390 *
391 * @param container the container containing sources that should be removed fr om this context and
392 * added to the returned context
393 * @return the analysis context that was created
394 */
395 AnalysisContext extractContext(SourceContainer container);
396
397 /**
398 * Return the set of analysis options controlling the behavior of this context . Clients should not
399 * modify the returned set of options. The options should only be set by invok ing the method
400 * [setAnalysisOptions].
401 *
402 * @return the set of analysis options controlling the behavior of this contex t
403 */
404 AnalysisOptions get analysisOptions;
405
406 /**
407 * Return the Angular application that contains the HTML file defined by the g iven source, or
408 * `null` if the source does not represent an HTML file, the Angular applicati on containing
409 * the file has not yet been resolved, or the analysis of the HTML file failed for some reason.
410 *
411 * @param htmlSource the source defining the HTML file
412 * @return the Angular application that contains the HTML file defined by the given source
413 */
414 AngularApplication getAngularApplicationWithHtml(Source htmlSource);
415
416 /**
417 * Return the element model corresponding to the compilation unit defined by t he given source in
418 * the library defined by the given source, or `null` if the element model doe s not
419 * currently exist or if the library cannot be analyzed for some reason.
420 *
421 * @param unitSource the source of the compilation unit
422 * @param librarySource the source of the defining compilation unit of the lib rary containing the
423 * compilation unit
424 * @return the element model corresponding to the compilation unit defined by the given source
425 */
426 CompilationUnitElement getCompilationUnitElement(Source unitSource, Source lib rarySource);
427
428 /**
429 * Get the contents and timestamp of the given source.
430 *
431 * This method should be used rather than the method [Source#getContents] beca use contexts
432 * can have local overrides of the content of a source that the source is not aware of.
433 *
434 * @param source the source whose content is to be returned
435 * @return the contents and timestamp of the source
436 * @throws Exception if the contents of the source could not be accessed
437 */
438 TimestampedData<String> getContents(Source source);
439
440 /**
441 * Return the set of declared variables used when computing constant values.
442 *
443 * @return the set of declared variables used when computing constant values
444 */
445 DeclaredVariables get declaredVariables;
446
447 /**
448 * Return the element referenced by the given location, or `null` if the eleme nt is not
449 * immediately available or if there is no element with the given location. Th e latter condition
450 * can occur, for example, if the location describes an element from a differe nt context or if the
451 * element has been removed from this context as a result of some change since it was originally
452 * obtained.
453 *
454 * @param location the reference describing the element to be returned
455 * @return the element referenced by the given location
456 */
457 Element getElement(ElementLocation location);
458
459 /**
460 * Return an analysis error info containing the array of all of the errors and the line info
461 * associated with the given source. The array of errors will be empty if the source is not known
462 * to this context or if there are no errors in the source. The errors contain ed in the array can
463 * be incomplete.
464 *
465 * @param source the source whose errors are to be returned
466 * @return all of the errors associated with the given source and the line inf o
467 * @see #computeErrors(Source)
468 */
469 AnalysisErrorInfo getErrors(Source source);
470
471 /**
472 * Return the element model corresponding to the HTML file defined by the give n source, or
473 * `null` if the source does not represent an HTML file, the element represent ing the file
474 * has not yet been created, or the analysis of the HTML file failed for some reason.
475 *
476 * @param source the source defining the HTML file whose element model is to b e returned
477 * @return the element model corresponding to the HTML file defined by the giv en source
478 * @see #computeHtmlElement(Source)
479 */
480 HtmlElement getHtmlElement(Source source);
481
482 /**
483 * Return the sources for the HTML files that reference the given compilation unit. If the source
484 * does not represent a Dart source or is not known to this context, the retur ned array will be
485 * empty. The contents of the array can be incomplete.
486 *
487 * @param source the source referenced by the returned HTML files
488 * @return the sources for the HTML files that reference the given compilation unit
489 */
490 List<Source> getHtmlFilesReferencing(Source source);
491
492 /**
493 * Return an array containing all of the sources known to this context that re present HTML files.
494 * The contents of the array can be incomplete.
495 *
496 * @return the sources known to this context that represent HTML files
497 */
498 List<Source> get htmlSources;
499
500 /**
501 * Return the kind of the given source, or `null` if the kind is not known to this context.
502 *
503 * @param source the source whose kind is to be returned
504 * @return the kind of the given source
505 * @see #computeKindOf(Source)
506 */
507 SourceKind getKindOf(Source source);
508
509 /**
510 * Return an array containing all of the sources known to this context that re present the defining
511 * compilation unit of a library that can be run within a browser. The sources that are returned
512 * represent libraries that have a 'main' method and are either referenced by an HTML file or
513 * import, directly or indirectly, a client-only library. The contents of the array can be
514 * incomplete.
515 *
516 * @return the sources known to this context that represent the defining compi lation unit of a
517 * library that can be run within a browser
518 */
519 List<Source> get launchableClientLibrarySources;
520
521 /**
522 * Return an array containing all of the sources known to this context that re present the defining
523 * compilation unit of a library that can be run outside of a browser. The con tents of the array
524 * can be incomplete.
525 *
526 * @return the sources known to this context that represent the defining compi lation unit of a
527 * library that can be run outside of a browser
528 */
529 List<Source> get launchableServerLibrarySources;
530
531 /**
532 * Return the sources for the defining compilation units of any libraries of w hich the given
533 * source is a part. The array will normally contain a single library because most Dart sources
534 * are only included in a single library, but it is possible to have a part th at is contained in
535 * multiple identically named libraries. If the source represents the defining compilation unit of
536 * a library, then the returned array will contain the given source as its onl y element. If the
537 * source does not represent a Dart source or is not known to this context, th e returned array
538 * will be empty. The contents of the array can be incomplete.
539 *
540 * @param source the source contained in the returned libraries
541 * @return the sources for the libraries containing the given source
542 */
543 List<Source> getLibrariesContaining(Source source);
544
545 /**
546 * Return the sources for the defining compilation units of any libraries that depend on the given
547 * library. One library depends on another if it either imports or exports tha t library.
548 *
549 * @param librarySource the source for the defining compilation unit of the li brary being depended
550 * on
551 * @return the sources for the libraries that depend on the given library
552 */
553 List<Source> getLibrariesDependingOn(Source librarySource);
554
555 /**
556 * Return the sources for the defining compilation units of any libraries that are referenced from
557 * the given HTML file.
558 *
559 * @param htmlSource the source for the HTML file
560 * @return the sources for the libraries that are referenced by the given HTML file
561 */
562 List<Source> getLibrariesReferencedFromHtml(Source htmlSource);
563
564 /**
565 * Return the element model corresponding to the library defined by the given source, or
566 * `null` if the element model does not currently exist or if the library cann ot be analyzed
567 * for some reason.
568 *
569 * @param source the source defining the library whose element model is to be returned
570 * @return the element model corresponding to the library defined by the given source
571 */
572 LibraryElement getLibraryElement(Source source);
573
574 /**
575 * Return an array containing all of the sources known to this context that re present the defining
576 * compilation unit of a library. The contents of the array can be incomplete.
577 *
578 * @return the sources known to this context that represent the defining compi lation unit of a
579 * library
580 */
581 List<Source> get librarySources;
582
583 /**
584 * Return the line information for the given source, or `null` if the line inf ormation is
585 * not known. The line information is used to map offsets from the beginning o f the source to line
586 * and column pairs.
587 *
588 * @param source the source whose line information is to be returned
589 * @return the line information for the given source
590 * @see #computeLineInfo(Source)
591 */
592 LineInfo getLineInfo(Source source);
593
594 /**
595 * Return the modification stamp for the given source. A modification stamp is a non-negative
596 * integer with the property that if the contents of the source have not been modified since the
597 * last time the modification stamp was accessed then the same value will be r eturned, but if the
598 * contents of the source have been modified one or more times (even if the ne t change is zero)
599 * the stamps will be different.
600 *
601 * This method should be used rather than the method [Source#getModificationSt amp] because
602 * contexts can have local overrides of the content of a source that the sourc e is not aware of.
603 *
604 * @param source the source whose modification stamp is to be returned
605 * @return the modification stamp for the source
606 */
607 int getModificationStamp(Source source);
608
609 /**
610 * Return an array containing all of the sources known to this context and the ir resolution state
611 * is not valid or flush. So, these sources are not safe to update during refa ctoring, because we
612 * may be don't know all the references in them.
613 *
614 * @return the sources known to this context and are not safe for refactoring
615 */
616 List<Source> get refactoringUnsafeSources;
617
618 /**
619 * Return a fully resolved AST for a single compilation unit within the given library, or
620 * `null` if the resolved AST is not already computed.
621 *
622 * @param unitSource the source of the compilation unit
623 * @param library the library containing the compilation unit
624 * @return a fully resolved AST for the compilation unit
625 * @see #resolveCompilationUnit(Source, LibraryElement)
626 */
627 CompilationUnit getResolvedCompilationUnit(Source unitSource, LibraryElement l ibrary);
628
629 /**
630 * Return a fully resolved AST for a single compilation unit within the given library, or
631 * `null` if the resolved AST is not already computed.
632 *
633 * @param unitSource the source of the compilation unit
634 * @param librarySource the source of the defining compilation unit of the lib rary containing the
635 * compilation unit
636 * @return a fully resolved AST for the compilation unit
637 * @see #resolveCompilationUnit(Source, Source)
638 */
639 CompilationUnit getResolvedCompilationUnit2(Source unitSource, Source libraryS ource);
640
641 /**
642 * Return a fully resolved HTML unit, or `null` if the resolved unit is not al ready
643 * computed.
644 *
645 * @param htmlSource the source of the HTML unit
646 * @return a fully resolved HTML unit
647 * @see #resolveHtmlUnit(Source)
648 */
649 ht.HtmlUnit getResolvedHtmlUnit(Source htmlSource);
650
651 /**
652 * Return the source factory used to create the sources that can be analyzed i n this context.
653 *
654 * @return the source factory used to create the sources that can be analyzed in this context
655 */
656 SourceFactory get sourceFactory;
657
658 /**
659 * Return `true` if the given source is known to be the defining compilation u nit of a
660 * library that can be run on a client (references 'dart:html', either directl y or indirectly).
661 *
662 * <b>Note:</b> In addition to the expected case of returning `false` if the s ource is known
663 * to be a library that cannot be run on a client, this method will also retur n `false` if
664 * the source is not known to be a library or if we do not know whether it can be run on a client.
665 *
666 * @param librarySource the source being tested
667 * @return `true` if the given source is known to be a library that can be run on a client
668 */
669 bool isClientLibrary(Source librarySource);
670
671 /**
672 * Returns `true` if this context was disposed using [dispose].
673 *
674 * @return `true` if this context was disposed
675 */
676 bool get isDisposed;
677
678 /**
679 * Return `true` if the given source is known to be the defining compilation u nit of a
680 * library that can be run on the server (does not reference 'dart:html', eith er directly or
681 * indirectly).
682 *
683 * <b>Note:</b> In addition to the expected case of returning `false` if the s ource is known
684 * to be a library that cannot be run on the server, this method will also ret urn `false` if
685 * the source is not known to be a library or if we do not know whether it can be run on the
686 * server.
687 *
688 * @param librarySource the source being tested
689 * @return `true` if the given source is known to be a library that can be run on the server
690 */
691 bool isServerLibrary(Source librarySource);
692
693 /**
694 * Add the sources contained in the specified context to this context's collec tion of sources.
695 * This method is called when an existing context's pubspec has been removed, and the contained
696 * sources should be reanalyzed as part of this context.
697 *
698 * @param context the context being merged
699 */
700 void mergeContext(AnalysisContext context);
701
702 /**
703 * Parse a single source to produce an AST structure. The resulting AST struct ure may or may not
704 * be resolved, and may have a slightly different structure depending upon whe ther it is resolved.
705 *
706 * <b>Note:</b> This method cannot be used in an async environment.
707 *
708 * @param source the source to be parsed
709 * @return the AST structure representing the content of the source
710 * @throws AnalysisException if the analysis could not be performed
711 */
712 CompilationUnit parseCompilationUnit(Source source);
713
714 /**
715 * Parse a single HTML source to produce an AST structure. The resulting HTML AST structure may or
716 * may not be resolved, and may have a slightly different structure depending upon whether it is
717 * resolved.
718 *
719 * <b>Note:</b> This method cannot be used in an async environment.
720 *
721 * @param source the HTML source to be parsed
722 * @return the parse result (not `null`)
723 * @throws AnalysisException if the analysis could not be performed
724 */
725 ht.HtmlUnit parseHtmlUnit(Source source);
726
727 /**
728 * Perform the next unit of work required to keep the analysis results up-to-d ate and return
729 * information about the consequent changes to the analysis results. This meth od can be long
730 * running.
731 *
732 * @return the results of performing the analysis
733 */
734 AnalysisResult performAnalysisTask();
735
736 /**
737 * Remove the given listener from the list of objects that are to be notified when various
738 * analysis results are produced in this context.
739 *
740 * @param listener the listener to be removed
741 */
742 void removeListener(AnalysisListener listener);
743
744 /**
745 * Parse and resolve a single source within the given context to produce a ful ly resolved AST.
746 *
747 * <b>Note:</b> This method cannot be used in an async environment.
748 *
749 * @param unitSource the source to be parsed and resolved
750 * @param library the library containing the source to be resolved
751 * @return the result of resolving the AST structure representing the content of the source in the
752 * context of the given library
753 * @throws AnalysisException if the analysis could not be performed
754 * @see #getResolvedCompilationUnit(Source, LibraryElement)
755 */
756 CompilationUnit resolveCompilationUnit(Source unitSource, LibraryElement libra ry);
757
758 /**
759 * Parse and resolve a single source within the given context to produce a ful ly resolved AST.
760 * Return the resolved AST structure, or `null` if the source could not be eit her parsed or
761 * resolved.
762 *
763 * <b>Note:</b> This method cannot be used in an async environment.
764 *
765 * @param unitSource the source to be parsed and resolved
766 * @param librarySource the source of the defining compilation unit of the lib rary containing the
767 * source to be resolved
768 * @return the result of resolving the AST structure representing the content of the source in the
769 * context of the given library
770 * @throws AnalysisException if the analysis could not be performed
771 * @see #getResolvedCompilationUnit(Source, Source)
772 */
773 CompilationUnit resolveCompilationUnit2(Source unitSource, Source librarySourc e);
774
775 /**
776 * Parse and resolve a single source within the given context to produce a ful ly resolved AST.
777 *
778 * <b>Note:</b> This method cannot be used in an async environment.
779 *
780 * @param htmlSource the source to be parsed and resolved
781 * @return the result of resolving the AST structure representing the content of the source
782 * @throws AnalysisException if the analysis could not be performed
783 */
784 ht.HtmlUnit resolveHtmlUnit(Source htmlSource);
785
786 /**
787 * Set the set of analysis options controlling the behavior of this context to the given options.
788 * Clients can safely assume that all necessary analysis results have been inv alidated.
789 *
790 * @param options the set of analysis options that will control the behavior o f this context
791 */
792 void set analysisOptions(AnalysisOptions options);
793
794 /**
795 * Set the order in which sources will be analyzed by [performAnalysisTask] to match the
796 * order of the sources in the given list. If a source that needs to be analyz ed is not contained
797 * in the list, then it will be treated as if it were at the end of the list. If the list is empty
798 * (or `null`) then no sources will be given priority over other sources.
799 *
800 * Changes made to the list after this method returns will <b>not</b> be refle cted in the priority
801 * order.
802 *
803 * @param sources the sources to be given priority over other sources
804 */
805 void set analysisPriorityOrder(List<Source> sources);
806
807 /**
808 * Set the contents of the given source to the given contents and mark the sou rce as having
809 * changed. The additional offset and length information is used by the contex t to determine what
810 * reanalysis is necessary.
811 *
812 * @param source the source whose contents are being overridden
813 * @param contents the text to replace the range in the current contents
814 * @param offset the offset into the current contents
815 * @param oldLength the number of characters in the original contents that wer e replaced
816 * @param newLength the number of characters in the replacement text
817 */
818 void setChangedContents(Source source, String contents, int offset, int oldLen gth, int newLength);
819
820 /**
821 * Set the contents of the given source to the given contents and mark the sou rce as having
822 * changed. This has the effect of overriding the default contents of the sour ce. If the contents
823 * are `null` the override is removed so that the default contents will be ret urned.
824 *
825 * @param source the source whose contents are being overridden
826 * @param contents the new contents of the source
827 */
828 void setContents(Source source, String contents);
829
830 /**
831 * Set the source factory used to create the sources that can be analyzed in t his context to the
832 * given source factory. Clients can safely assume that all analysis results h ave been
833 * invalidated.
834 *
835 * @param factory the source factory used to create the sources that can be an alyzed in this
836 * context
837 */
838 void set sourceFactory(SourceFactory factory);
839 }
840
841 /**
842 * Instances of the class `AnalysisContextImpl` implement an [AnalysisContext].
843 */
844 class AnalysisContextImpl implements InternalAnalysisContext {
845 /**
846 * The difference between the maximum cache size and the maximum priority orde r size. The priority
847 * list must be capped so that it is less than the cache size. Failure to do s o can result in an
848 * infinite loop in performAnalysisTask() because re-caching one AST structure can cause another
849 * priority source's AST structure to be flushed.
850 */
851 static int _PRIORITY_ORDER_SIZE_DELTA = 4;
852
853 /**
854 * A flag indicating whether trace output should be produced as analysis tasks are performed. Used
855 * for debugging.
856 */
857 static bool _TRACE_PERFORM_TASK = false;
858
859 /**
860 * The set of analysis options controlling the behavior of this context.
861 */
862 AnalysisOptionsImpl _options = new AnalysisOptionsImpl();
863
864 /**
865 * A flag indicating whether errors related to sources in the SDK should be ge nerated and
866 * reported.
867 */
868 bool _generateSdkErrors = true;
869
870 /**
871 * A flag indicating whether this context is disposed.
872 */
873 bool _disposed = false;
874
875 /**
876 * A cache of content used to override the default content of a source.
877 */
878 ContentCache _contentCache = new ContentCache();
879
880 /**
881 * The source factory used to create the sources that can be analyzed in this context.
882 */
883 SourceFactory _sourceFactory;
884
885 /**
886 * The set of declared variables used when computing constant values.
887 */
888 DeclaredVariables _declaredVariables = new DeclaredVariables();
889
890 /**
891 * A source representing the core library.
892 */
893 Source _coreLibrarySource;
894
895 /**
896 * The partition that contains analysis results that are not shared with other contexts.
897 */
898 CachePartition _privatePartition;
899
900 /**
901 * A table mapping the sources known to the context to the information known a bout the source.
902 */
903 AnalysisCache _cache;
904
905 /**
906 * An array containing sources for which data should not be flushed.
907 */
908 List<Source> _priorityOrder = Source.EMPTY_ARRAY;
909
910 /**
911 * An array containing sources whose AST structure is needed in order to resol ve the next library
912 * to be resolved.
913 */
914 HashSet<Source> _neededForResolution = null;
915
916 /**
917 * A table mapping sources to the change notices that are waiting to be return ed related to that
918 * source.
919 */
920 HashMap<Source, ChangeNoticeImpl> _pendingNotices = new HashMap<Source, Change NoticeImpl>();
921
922 /**
923 * A set containing information about the tasks that have been performed since the last change
924 * notification. Used to detect infinite loops in [performAnalysisTask].
925 */
926 HashSet<String> _recentTasks = new HashSet<String>();
927
928 /**
929 * The object used to synchronize access to all of the caches. The rules relat ed to the use of
930 * this lock object are
931 * * no analysis work is done while holding the lock, and
932 * * no analysis results can be recorded unless we have obtained the lock and validated that the
933 * results are for the same version (modification time) of the source as our c urrent cache
934 * content.
935 */
936 static Object _cacheLock = new Object();
937
938 /**
939 * The object used to record the results of performing an analysis task.
940 */
941 AnalysisContextImpl_AnalysisTaskResultRecorder _resultRecorder;
942
943 /**
944 * Cached information used in incremental analysis or `null` if none. Synchron ize against
945 * [cacheLock] before accessing this field.
946 */
947 IncrementalAnalysisCache _incrementalAnalysisCache;
948
949 /**
950 * The object used to manage the list of sources that need to be analyzed.
951 */
952 WorkManager _workManager = new WorkManager();
953
954 /**
955 * The set of [AngularApplication] in this context.
956 */
957 Set<AngularApplication> _angularApplications = new Set();
958
959 /**
960 * The listeners that are to be notified when various analysis results are pro duced in this
961 * context.
962 */
963 List<AnalysisListener> _listeners = new List<AnalysisListener>();
964
965 /**
966 * Initialize a newly created analysis context.
967 */
968 AnalysisContextImpl() : super() {
969 _resultRecorder = new AnalysisContextImpl_AnalysisTaskResultRecorder(this);
970 _privatePartition = new UniversalCachePartition(AnalysisOptionsImpl.DEFAULT_ CACHE_SIZE, new AnalysisContextImpl_ContextRetentionPolicy(this));
971 _cache = createCacheFromSourceFactory(null);
972 }
973
974 @override
975 void addListener(AnalysisListener listener) {
976 if (!_listeners.contains(listener)) {
977 _listeners.add(listener);
978 }
979 }
980
981 @override
982 void addSourceInfo(Source source, SourceEntry info) {
983 // This implementation assumes that the access to the cache does not need to be synchronized
984 // because no other object can have access to this context while this method is being invoked.
985 _cache.put(source, info);
986 }
987
988 @override
989 void applyAnalysisDelta(AnalysisDelta delta) {
990 ChangeSet changeSet = new ChangeSet();
991 for (MapEntry<Source, AnalysisLevel> entry in getMapEntrySet(delta.analysisL evels)) {
992 Source source = entry.getKey();
993 if (entry.getValue() == AnalysisLevel.NONE) {
994 changeSet.removedSource(source);
995 } else {
996 changeSet.addedSource(source);
997 }
998 }
999 applyChanges(changeSet);
1000 }
1001
1002 @override
1003 void applyChanges(ChangeSet changeSet) {
1004 if (changeSet.isEmpty) {
1005 return;
1006 }
1007 _recentTasks.clear();
1008 //
1009 // First, compute the list of sources that have been removed.
1010 //
1011 List<Source> removedSources = new List<Source>.from(changeSet.removedSources );
1012 for (SourceContainer container in changeSet.removedContainers) {
1013 _addSourcesInContainer(removedSources, container);
1014 }
1015 //
1016 // Then determine which cached results are no longer valid.
1017 //
1018 bool addedDartSource = false;
1019 for (Source source in changeSet.addedSources) {
1020 if (_sourceAvailable(source)) {
1021 addedDartSource = true;
1022 }
1023 }
1024 for (Source source in changeSet.changedSources) {
1025 if (_contentCache.getContents(source) != null) {
1026 // This source is overridden in the content cache, so the change will ha ve no effect.
1027 // Just ignore it to avoid wasting time doing re-analysis.
1028 continue;
1029 }
1030 _sourceChanged(source);
1031 }
1032 for (MapEntry<Source, String> entry in getMapEntrySet(changeSet.changedConte nts)) {
1033 setContents(entry.getKey(), entry.getValue());
1034 }
1035 for (MapEntry<Source, ChangeSet_ContentChange> entry in getMapEntrySet(chang eSet.changedRanges)) {
1036 ChangeSet_ContentChange change = entry.getValue();
1037 setChangedContents(entry.getKey(), change.contents, change.offset, change. oldLength, change.newLength);
1038 }
1039 for (Source source in changeSet.deletedSources) {
1040 _sourceDeleted(source);
1041 }
1042 for (Source source in removedSources) {
1043 _sourceRemoved(source);
1044 }
1045 if (addedDartSource) {
1046 // TODO(brianwilkerson) This is hugely inefficient, but we need to re-anal yze any libraries
1047 // that might have been referencing the not-yet-existing source that was j ust added. Longer
1048 // term we need to keep track of which libraries are referencing non-exist ing sources and
1049 // only re-analyze those libraries.
1050 // logInformation("Added Dart sources, invalidating all resolution information");
1051 List<Source> sourcesToInvalidate = new List<Source>();
1052 MapIterator<Source, SourceEntry> iterator = _cache.iterator();
1053 while (iterator.moveNext()) {
1054 Source source = iterator.key;
1055 SourceEntry sourceEntry = iterator.value;
1056 if (!source.isInSystemLibrary && (sourceEntry is DartEntry || sourceEntr y is HtmlEntry)) {
1057 sourcesToInvalidate.add(source);
1058 }
1059 }
1060 int count = sourcesToInvalidate.length;
1061 for (int i = 0; i < count; i++) {
1062 Source source = sourcesToInvalidate[i];
1063 SourceEntry entry = _getReadableSourceEntry(source);
1064 if (entry is DartEntry) {
1065 DartEntry dartEntry = entry;
1066 DartEntryImpl dartCopy = dartEntry.writableCopy;
1067 dartCopy.invalidateAllResolutionInformation(false);
1068 _cache.put(source, dartCopy);
1069 _workManager.add(source, _computePriority(dartCopy));
1070 } else if (entry is HtmlEntry) {
1071 HtmlEntry htmlEntry = entry;
1072 HtmlEntryImpl htmlCopy = htmlEntry.writableCopy;
1073 htmlCopy.invalidateAllResolutionInformation(false);
1074 _cache.put(source, htmlCopy);
1075 _workManager.add(source, SourcePriority.HTML);
1076 }
1077 }
1078 }
1079 }
1080
1081 @override
1082 String computeDocumentationComment(Element element) {
1083 if (element == null) {
1084 return null;
1085 }
1086 Source source = element.source;
1087 if (source == null) {
1088 return null;
1089 }
1090 CompilationUnit unit = parseCompilationUnit(source);
1091 if (unit == null) {
1092 return null;
1093 }
1094 NodeLocator locator = new NodeLocator.con1(element.nameOffset);
1095 AstNode nameNode = locator.searchWithin(unit);
1096 while (nameNode != null) {
1097 if (nameNode is AnnotatedNode) {
1098 Comment comment = (nameNode as AnnotatedNode).documentationComment;
1099 if (comment == null) {
1100 return null;
1101 }
1102 JavaStringBuilder builder = new JavaStringBuilder();
1103 List<Token> tokens = comment.tokens;
1104 for (int i = 0; i < tokens.length; i++) {
1105 if (i > 0) {
1106 builder.append("\n");
1107 }
1108 builder.append(tokens[i].lexeme);
1109 }
1110 return builder.toString();
1111 }
1112 nameNode = nameNode.parent;
1113 }
1114 return null;
1115 }
1116
1117 @override
1118 List<AnalysisError> computeErrors(Source source) {
1119 bool enableHints = _options.hint;
1120 SourceEntry sourceEntry = _getReadableSourceEntry(source);
1121 if (sourceEntry is DartEntry) {
1122 List<AnalysisError> errors = new List<AnalysisError>();
1123 try {
1124 DartEntry dartEntry = sourceEntry;
1125 ListUtilities.addAll(errors, _getDartScanData(source, dartEntry, DartEnt ry.SCAN_ERRORS));
1126 dartEntry = _getReadableDartEntry(source);
1127 ListUtilities.addAll(errors, _getDartParseData(source, dartEntry, DartEn try.PARSE_ERRORS));
1128 dartEntry = _getReadableDartEntry(source);
1129 if (dartEntry.getValue(DartEntry.SOURCE_KIND) == SourceKind.LIBRARY) {
1130 ListUtilities.addAll(errors, _getDartResolutionData(source, source, da rtEntry, DartEntry.RESOLUTION_ERRORS));
1131 dartEntry = _getReadableDartEntry(source);
1132 ListUtilities.addAll(errors, _getDartVerificationData(source, source, dartEntry, DartEntry.VERIFICATION_ERRORS));
1133 if (enableHints) {
1134 dartEntry = _getReadableDartEntry(source);
1135 ListUtilities.addAll(errors, _getDartHintData(source, source, dartEn try, DartEntry.HINTS));
1136 }
1137 } else {
1138 List<Source> libraries = getLibrariesContaining(source);
1139 for (Source librarySource in libraries) {
1140 ListUtilities.addAll(errors, _getDartResolutionData(source, libraryS ource, dartEntry, DartEntry.RESOLUTION_ERRORS));
1141 dartEntry = _getReadableDartEntry(source);
1142 ListUtilities.addAll(errors, _getDartVerificationData(source, librar ySource, dartEntry, DartEntry.VERIFICATION_ERRORS));
1143 if (enableHints) {
1144 dartEntry = _getReadableDartEntry(source);
1145 ListUtilities.addAll(errors, _getDartHintData(source, librarySourc e, dartEntry, DartEntry.HINTS));
1146 }
1147 }
1148 }
1149 } on ObsoleteSourceAnalysisException catch (exception) {
1150 AnalysisEngine.instance.logger.logInformation2("Could not compute errors ", exception);
1151 }
1152 if (errors.isEmpty) {
1153 return AnalysisError.NO_ERRORS;
1154 }
1155 return new List.from(errors);
1156 } else if (sourceEntry is HtmlEntry) {
1157 HtmlEntry htmlEntry = sourceEntry;
1158 try {
1159 return _getHtmlResolutionData2(source, htmlEntry, HtmlEntry.RESOLUTION_E RRORS);
1160 } on ObsoleteSourceAnalysisException catch (exception) {
1161 AnalysisEngine.instance.logger.logInformation2("Could not compute errors ", exception);
1162 }
1163 }
1164 return AnalysisError.NO_ERRORS;
1165 }
1166
1167 @override
1168 List<Source> computeExportedLibraries(Source source) => _getDartParseData2(sou rce, DartEntry.EXPORTED_LIBRARIES, Source.EMPTY_ARRAY);
1169
1170 @override
1171 HtmlElement computeHtmlElement(Source source) => _getHtmlResolutionData(source , HtmlEntry.ELEMENT, null);
1172
1173 @override
1174 List<Source> computeImportedLibraries(Source source) => _getDartParseData2(sou rce, DartEntry.IMPORTED_LIBRARIES, Source.EMPTY_ARRAY);
1175
1176 @override
1177 SourceKind computeKindOf(Source source) {
1178 SourceEntry sourceEntry = _getReadableSourceEntry(source);
1179 if (sourceEntry == null) {
1180 return SourceKind.UNKNOWN;
1181 } else if (sourceEntry is DartEntry) {
1182 try {
1183 return _getDartParseData(source, sourceEntry, DartEntry.SOURCE_KIND);
1184 } on AnalysisException catch (exception) {
1185 return SourceKind.UNKNOWN;
1186 }
1187 }
1188 return sourceEntry.kind;
1189 }
1190
1191 @override
1192 LibraryElement computeLibraryElement(Source source) => _getDartResolutionData2 (source, source, DartEntry.ELEMENT, null);
1193
1194 @override
1195 LineInfo computeLineInfo(Source source) {
1196 SourceEntry sourceEntry = _getReadableSourceEntry(source);
1197 try {
1198 if (sourceEntry is HtmlEntry) {
1199 return _getHtmlParseData(source, SourceEntry.LINE_INFO, null);
1200 } else if (sourceEntry is DartEntry) {
1201 return _getDartScanData2(source, SourceEntry.LINE_INFO, null);
1202 }
1203 } on ObsoleteSourceAnalysisException catch (exception) {
1204 AnalysisEngine.instance.logger.logInformation2("Could not compute ${Source Entry.LINE_INFO.toString()}", exception);
1205 }
1206 return null;
1207 }
1208
1209 @override
1210 ResolvableCompilationUnit computeResolvableCompilationUnit(Source source) {
1211 DartEntry dartEntry = _getReadableDartEntry(source);
1212 if (dartEntry == null) {
1213 throw new AnalysisException("computeResolvableCompilationUnit for non-Dart : ${source.fullName}");
1214 }
1215 dartEntry = _cacheDartParseData(source, dartEntry, DartEntry.PARSED_UNIT);
1216 DartEntryImpl dartCopy = dartEntry.writableCopy;
1217 CompilationUnit unit = dartCopy.resolvableCompilationUnit;
1218 if (unit == null) {
1219 throw new AnalysisException("Internal error: computeResolvableCompilationU nit could not parse ${source.fullName}", new CaughtException(dartEntry.exception , null));
1220 }
1221 _cache.put(source, dartCopy);
1222 return new ResolvableCompilationUnit.con1(dartCopy.modificationTime, unit);
1223 }
1224
1225 @override
1226 void dispose() {
1227 _disposed = true;
1228 }
1229
1230 @override
1231 bool exists(Source source) {
1232 if (source == null) {
1233 return false;
1234 }
1235 if (_contentCache.getContents(source) != null) {
1236 return true;
1237 }
1238 return source.exists();
1239 }
1240
1241 @override
1242 AnalysisContext extractContext(SourceContainer container) => extractContextInt o(container, AnalysisEngine.instance.createAnalysisContext() as InternalAnalysis Context);
1243
1244 @override
1245 InternalAnalysisContext extractContextInto(SourceContainer container, Internal AnalysisContext newContext) {
1246 List<Source> sourcesToRemove = new List<Source>();
1247 // Move sources in the specified directory to the new context
1248 MapIterator<Source, SourceEntry> iterator = _cache.iterator();
1249 while (iterator.moveNext()) {
1250 Source source = iterator.key;
1251 SourceEntry sourceEntry = iterator.value;
1252 if (container.contains(source)) {
1253 sourcesToRemove.add(source);
1254 newContext.addSourceInfo(source, sourceEntry.writableCopy);
1255 }
1256 }
1257 return newContext;
1258 }
1259
1260 @override
1261 AnalysisOptions get analysisOptions => _options;
1262
1263 @override
1264 AngularApplication getAngularApplicationWithHtml(Source htmlSource) {
1265 SourceEntry sourceEntry = _getReadableSourceEntryOrNull(htmlSource);
1266 if (sourceEntry is HtmlEntry) {
1267 HtmlEntry htmlEntry = sourceEntry;
1268 AngularApplication application = htmlEntry.getValue(HtmlEntry.ANGULAR_APPL ICATION);
1269 if (application != null) {
1270 return application;
1271 }
1272 return htmlEntry.getValue(HtmlEntry.ANGULAR_ENTRY);
1273 }
1274 return null;
1275 }
1276
1277 @override
1278 CompilationUnitElement getCompilationUnitElement(Source unitSource, Source lib rarySource) {
1279 LibraryElement libraryElement = getLibraryElement(librarySource);
1280 if (libraryElement != null) {
1281 // try defining unit
1282 CompilationUnitElement definingUnit = libraryElement.definingCompilationUn it;
1283 if (definingUnit.source == unitSource) {
1284 return definingUnit;
1285 }
1286 // try parts
1287 for (CompilationUnitElement partUnit in libraryElement.parts) {
1288 if (partUnit.source == unitSource) {
1289 return partUnit;
1290 }
1291 }
1292 }
1293 return null;
1294 }
1295
1296 @override
1297 TimestampedData<String> getContents(Source source) {
1298 String contents = _contentCache.getContents(source);
1299 if (contents != null) {
1300 return new TimestampedData<String>(_contentCache.getModificationStamp(sour ce), contents);
1301 }
1302 return source.contents;
1303 }
1304
1305 @override
1306 DeclaredVariables get declaredVariables => _declaredVariables;
1307
1308 @override
1309 Element getElement(ElementLocation location) {
1310 // TODO(brianwilkerson) This should not be a "get" method.
1311 try {
1312 List<String> components = location.components;
1313 Source source = _computeSourceFromEncoding(components[0]);
1314 String sourceName = source.shortName;
1315 if (AnalysisEngine.isDartFileName(sourceName)) {
1316 ElementImpl element = computeLibraryElement(source) as ElementImpl;
1317 for (int i = 1; i < components.length; i++) {
1318 if (element == null) {
1319 return null;
1320 }
1321 element = element.getChild(components[i]);
1322 }
1323 return element;
1324 }
1325 if (AnalysisEngine.isHtmlFileName(sourceName)) {
1326 return computeHtmlElement(source);
1327 }
1328 } on AnalysisException catch (exception) {
1329 }
1330 return null;
1331 }
1332
1333 @override
1334 AnalysisErrorInfo getErrors(Source source) {
1335 SourceEntry sourceEntry = _getReadableSourceEntryOrNull(source);
1336 if (sourceEntry is DartEntry) {
1337 DartEntry dartEntry = sourceEntry;
1338 return new AnalysisErrorInfoImpl(dartEntry.allErrors, dartEntry.getValue(S ourceEntry.LINE_INFO));
1339 } else if (sourceEntry is HtmlEntry) {
1340 HtmlEntry htmlEntry = sourceEntry;
1341 return new AnalysisErrorInfoImpl(htmlEntry.allErrors, htmlEntry.getValue(S ourceEntry.LINE_INFO));
1342 }
1343 return new AnalysisErrorInfoImpl(AnalysisError.NO_ERRORS, null);
1344 }
1345
1346 @override
1347 HtmlElement getHtmlElement(Source source) {
1348 SourceEntry sourceEntry = _getReadableSourceEntryOrNull(source);
1349 if (sourceEntry is HtmlEntry) {
1350 return sourceEntry.getValue(HtmlEntry.ELEMENT);
1351 }
1352 return null;
1353 }
1354
1355 @override
1356 List<Source> getHtmlFilesReferencing(Source source) {
1357 SourceKind sourceKind = getKindOf(source);
1358 if (sourceKind == null) {
1359 return Source.EMPTY_ARRAY;
1360 }
1361 List<Source> htmlSources = new List<Source>();
1362 while (true) {
1363 if (sourceKind == SourceKind.LIBRARY) {
1364 } else if (sourceKind == SourceKind.PART) {
1365 List<Source> librarySources = getLibrariesContaining(source);
1366 MapIterator<Source, SourceEntry> partIterator = _cache.iterator();
1367 while (partIterator.moveNext()) {
1368 SourceEntry sourceEntry = partIterator.value;
1369 if (sourceEntry.kind == SourceKind.HTML) {
1370 List<Source> referencedLibraries = (sourceEntry as HtmlEntry).getVal ue(HtmlEntry.REFERENCED_LIBRARIES);
1371 if (_containsAny(referencedLibraries, librarySources)) {
1372 htmlSources.add(partIterator.key);
1373 }
1374 }
1375 }
1376 }
1377 break;
1378 }
1379 if (htmlSources.isEmpty) {
1380 return Source.EMPTY_ARRAY;
1381 }
1382 return new List.from(htmlSources);
1383 }
1384
1385 @override
1386 List<Source> get htmlSources => _getSources(SourceKind.HTML);
1387
1388 @override
1389 SourceKind getKindOf(Source source) {
1390 SourceEntry sourceEntry = _getReadableSourceEntryOrNull(source);
1391 if (sourceEntry == null) {
1392 return SourceKind.UNKNOWN;
1393 }
1394 return sourceEntry.kind;
1395 }
1396
1397 @override
1398 List<Source> get launchableClientLibrarySources {
1399 // TODO(brianwilkerson) This needs to filter out libraries that do not refer ence dart:html,
1400 // either directly or indirectly.
1401 List<Source> sources = new List<Source>();
1402 MapIterator<Source, SourceEntry> iterator = _cache.iterator();
1403 while (iterator.moveNext()) {
1404 Source source = iterator.key;
1405 SourceEntry sourceEntry = iterator.value;
1406 if (sourceEntry.kind == SourceKind.LIBRARY && !source.isInSystemLibrary) {
1407 // DartEntry dartEntry = (DartEntry) sourceEntry;
1408 // if (dartEntry.getValue(DartEntry.IS_LAUNCHABLE) && dartEntry .getValue(DartEntry.IS_CLIENT)) {
1409 sources.add(source);
1410 }
1411 }
1412 return new List.from(sources);
1413 }
1414
1415 @override
1416 List<Source> get launchableServerLibrarySources {
1417 // TODO(brianwilkerson) This needs to filter out libraries that reference da rt:html, either
1418 // directly or indirectly.
1419 List<Source> sources = new List<Source>();
1420 MapIterator<Source, SourceEntry> iterator = _cache.iterator();
1421 while (iterator.moveNext()) {
1422 Source source = iterator.key;
1423 SourceEntry sourceEntry = iterator.value;
1424 if (sourceEntry.kind == SourceKind.LIBRARY && !source.isInSystemLibrary) {
1425 // DartEntry dartEntry = (DartEntry) sourceEntry;
1426 // if (dartEntry.getValue(DartEntry.IS_LAUNCHABLE) && !dartEntr y.getValue(DartEntry.IS_CLIENT)) {
1427 sources.add(source);
1428 }
1429 }
1430 return new List.from(sources);
1431 }
1432
1433 @override
1434 List<Source> getLibrariesContaining(Source source) {
1435 SourceEntry sourceEntry = _getReadableSourceEntryOrNull(source);
1436 if (sourceEntry is DartEntry) {
1437 return sourceEntry.getValue(DartEntry.CONTAINING_LIBRARIES);
1438 }
1439 return Source.EMPTY_ARRAY;
1440 }
1441
1442 @override
1443 List<Source> getLibrariesDependingOn(Source librarySource) {
1444 List<Source> dependentLibraries = new List<Source>();
1445 MapIterator<Source, SourceEntry> iterator = _cache.iterator();
1446 while (iterator.moveNext()) {
1447 SourceEntry sourceEntry = iterator.value;
1448 if (sourceEntry.kind == SourceKind.LIBRARY) {
1449 if (_contains((sourceEntry as DartEntry).getValue(DartEntry.EXPORTED_LIB RARIES), librarySource)) {
1450 dependentLibraries.add(iterator.key);
1451 }
1452 if (_contains((sourceEntry as DartEntry).getValue(DartEntry.IMPORTED_LIB RARIES), librarySource)) {
1453 dependentLibraries.add(iterator.key);
1454 }
1455 }
1456 }
1457 if (dependentLibraries.isEmpty) {
1458 return Source.EMPTY_ARRAY;
1459 }
1460 return new List.from(dependentLibraries);
1461 }
1462
1463 @override
1464 List<Source> getLibrariesReferencedFromHtml(Source htmlSource) {
1465 SourceEntry sourceEntry = _getReadableSourceEntryOrNull(htmlSource);
1466 if (sourceEntry is HtmlEntry) {
1467 HtmlEntry htmlEntry = sourceEntry;
1468 return htmlEntry.getValue(HtmlEntry.REFERENCED_LIBRARIES);
1469 }
1470 return Source.EMPTY_ARRAY;
1471 }
1472
1473 @override
1474 LibraryElement getLibraryElement(Source source) {
1475 SourceEntry sourceEntry = _getReadableSourceEntryOrNull(source);
1476 if (sourceEntry is DartEntry) {
1477 return sourceEntry.getValue(DartEntry.ELEMENT);
1478 }
1479 return null;
1480 }
1481
1482 @override
1483 List<Source> get librarySources => _getSources(SourceKind.LIBRARY);
1484
1485 @override
1486 LineInfo getLineInfo(Source source) {
1487 SourceEntry sourceEntry = _getReadableSourceEntryOrNull(source);
1488 if (sourceEntry != null) {
1489 return sourceEntry.getValue(SourceEntry.LINE_INFO);
1490 }
1491 return null;
1492 }
1493
1494 @override
1495 int getModificationStamp(Source source) {
1496 int stamp = _contentCache.getModificationStamp(source);
1497 if (stamp != null) {
1498 return stamp;
1499 }
1500 return source.modificationStamp;
1501 }
1502
1503 @override
1504 List<Source> get prioritySources => _priorityOrder;
1505
1506 @override
1507 Namespace getPublicNamespace(LibraryElement library) {
1508 // TODO(brianwilkerson) Rename this to not start with 'get'. Note that this is not part of the
1509 // API of the interface.
1510 Source source = library.definingCompilationUnit.source;
1511 DartEntry dartEntry = _getReadableDartEntry(source);
1512 if (dartEntry == null) {
1513 return null;
1514 }
1515 Namespace namespace = null;
1516 if (identical(dartEntry.getValue(DartEntry.ELEMENT), library)) {
1517 namespace = dartEntry.getValue(DartEntry.PUBLIC_NAMESPACE);
1518 }
1519 if (namespace == null) {
1520 NamespaceBuilder builder = new NamespaceBuilder();
1521 namespace = builder.createPublicNamespaceForLibrary(library);
1522 dartEntry = _getReadableDartEntry(source);
1523 if (dartEntry == null) {
1524 AnalysisEngine.instance.logger.logError2("Could not compute the public n amespace for ${library.source.fullName}", new CaughtException(new AnalysisExcept ion("A Dart file became a non-Dart file: ${source.fullName}"), null));
1525 return null;
1526 }
1527 if (identical(dartEntry.getValue(DartEntry.ELEMENT), library)) {
1528 DartEntryImpl dartCopy = _getReadableDartEntry(source).writableCopy;
1529 dartCopy.setValue(DartEntry.PUBLIC_NAMESPACE, namespace);
1530 _cache.put(source, dartCopy);
1531 }
1532 }
1533 return namespace;
1534 }
1535
1536 @override
1537 List<Source> get refactoringUnsafeSources {
1538 List<Source> sources = new List<Source>();
1539 MapIterator<Source, SourceEntry> iterator = _cache.iterator();
1540 while (iterator.moveNext()) {
1541 SourceEntry sourceEntry = iterator.value;
1542 if (sourceEntry is DartEntry) {
1543 if (!sourceEntry.isRefactoringSafe) {
1544 sources.add(iterator.key);
1545 }
1546 }
1547 }
1548 return new List.from(sources);
1549 }
1550
1551 @override
1552 CompilationUnit getResolvedCompilationUnit(Source unitSource, LibraryElement l ibrary) {
1553 if (library == null) {
1554 return null;
1555 }
1556 return getResolvedCompilationUnit2(unitSource, library.source);
1557 }
1558
1559 @override
1560 CompilationUnit getResolvedCompilationUnit2(Source unitSource, Source libraryS ource) {
1561 SourceEntry sourceEntry = _getReadableSourceEntryOrNull(unitSource);
1562 if (sourceEntry is DartEntry) {
1563 return sourceEntry.getValueInLibrary(DartEntry.RESOLVED_UNIT, librarySourc e);
1564 }
1565 return null;
1566 }
1567
1568 @override
1569 ht.HtmlUnit getResolvedHtmlUnit(Source htmlSource) {
1570 SourceEntry sourceEntry = _getReadableSourceEntryOrNull(htmlSource);
1571 if (sourceEntry is HtmlEntry) {
1572 HtmlEntry htmlEntry = sourceEntry;
1573 return htmlEntry.getValue(HtmlEntry.RESOLVED_UNIT);
1574 }
1575 return null;
1576 }
1577
1578 @override
1579 SourceFactory get sourceFactory => _sourceFactory;
1580
1581 /**
1582 * Return a list of the sources that would be processed by [performAnalysisTas k]. This
1583 * method duplicates, and must therefore be kept in sync with, [getNextAnalysi sTask].
1584 * This method is intended to be used for testing purposes only.
1585 *
1586 * @return a list of the sources that would be processed by [performAnalysisTa sk]
1587 */
1588 List<Source> get sourcesNeedingProcessing {
1589 HashSet<Source> sources = new HashSet<Source>();
1590 bool hintsEnabled = _options.hint;
1591 //
1592 // Look for priority sources that need to be analyzed.
1593 //
1594 for (Source source in _priorityOrder) {
1595 _getSourcesNeedingProcessing(source, _cache.get(source), true, hintsEnable d, sources);
1596 }
1597 //
1598 // Look for non-priority sources that need to be analyzed.
1599 //
1600 MapIterator<Source, SourceEntry> iterator = _cache.iterator();
1601 while (iterator.moveNext()) {
1602 _getSourcesNeedingProcessing(iterator.key, iterator.value, false, hintsEna bled, sources);
1603 }
1604 return new List<Source>.from(sources);
1605 }
1606
1607 @override
1608 AnalysisContextStatistics get statistics {
1609 bool hintsEnabled = _options.hint;
1610 AnalysisContextStatisticsImpl statistics = new AnalysisContextStatisticsImpl ();
1611 MapIterator<Source, SourceEntry> iterator = _cache.iterator();
1612 while (iterator.moveNext()) {
1613 SourceEntry sourceEntry = iterator.value;
1614 if (sourceEntry is DartEntry) {
1615 Source source = iterator.key;
1616 DartEntry dartEntry = sourceEntry;
1617 SourceKind kind = dartEntry.getValue(DartEntry.SOURCE_KIND);
1618 // get library independent values
1619 statistics.putCacheItem(dartEntry, SourceEntry.LINE_INFO);
1620 statistics.putCacheItem(dartEntry, DartEntry.PARSE_ERRORS);
1621 statistics.putCacheItem(dartEntry, DartEntry.PARSED_UNIT);
1622 statistics.putCacheItem(dartEntry, DartEntry.SOURCE_KIND);
1623 if (kind == SourceKind.LIBRARY) {
1624 statistics.putCacheItem(dartEntry, DartEntry.ELEMENT);
1625 statistics.putCacheItem(dartEntry, DartEntry.EXPORTED_LIBRARIES);
1626 statistics.putCacheItem(dartEntry, DartEntry.IMPORTED_LIBRARIES);
1627 statistics.putCacheItem(dartEntry, DartEntry.INCLUDED_PARTS);
1628 statistics.putCacheItem(dartEntry, DartEntry.IS_CLIENT);
1629 statistics.putCacheItem(dartEntry, DartEntry.IS_LAUNCHABLE);
1630 }
1631 // get library-specific values
1632 List<Source> librarySources = getLibrariesContaining(source);
1633 for (Source librarySource in librarySources) {
1634 statistics.putCacheItemInLibrary(dartEntry, librarySource, DartEntry.R ESOLUTION_ERRORS);
1635 statistics.putCacheItemInLibrary(dartEntry, librarySource, DartEntry.R ESOLVED_UNIT);
1636 if (_generateSdkErrors || !source.isInSystemLibrary) {
1637 statistics.putCacheItemInLibrary(dartEntry, librarySource, DartEntry .VERIFICATION_ERRORS);
1638 if (hintsEnabled) {
1639 statistics.putCacheItemInLibrary(dartEntry, librarySource, DartEnt ry.HINTS);
1640 }
1641 }
1642 }
1643 } else if (sourceEntry is HtmlEntry) {
1644 HtmlEntry htmlEntry = sourceEntry;
1645 statistics.putCacheItem(htmlEntry, SourceEntry.LINE_INFO);
1646 statistics.putCacheItem(htmlEntry, HtmlEntry.PARSE_ERRORS);
1647 statistics.putCacheItem(htmlEntry, HtmlEntry.PARSED_UNIT);
1648 statistics.putCacheItem(htmlEntry, HtmlEntry.RESOLUTION_ERRORS);
1649 statistics.putCacheItem(htmlEntry, HtmlEntry.RESOLVED_UNIT);
1650 }
1651 }
1652 statistics.partitionData = _cache.partitionData;
1653 return statistics;
1654 }
1655
1656 @override
1657 TypeProvider get typeProvider {
1658 Source coreSource = sourceFactory.forUri(DartSdk.DART_CORE);
1659 if (coreSource == null) {
1660 throw new AnalysisException("Could not create a source for dart:core");
1661 }
1662 LibraryElement coreElement = computeLibraryElement(coreSource);
1663 if (coreElement == null) {
1664 throw new AnalysisException("Could not create an element for dart:core");
1665 }
1666 return new TypeProviderImpl(coreElement);
1667 }
1668
1669 @override
1670 bool isClientLibrary(Source librarySource) {
1671 SourceEntry sourceEntry = _getReadableSourceEntry(librarySource);
1672 if (sourceEntry is DartEntry) {
1673 DartEntry dartEntry = sourceEntry;
1674 return dartEntry.getValue(DartEntry.IS_CLIENT) && dartEntry.getValue(DartE ntry.IS_LAUNCHABLE);
1675 }
1676 return false;
1677 }
1678
1679 @override
1680 bool get isDisposed => _disposed;
1681
1682 @override
1683 bool isServerLibrary(Source librarySource) {
1684 SourceEntry sourceEntry = _getReadableSourceEntry(librarySource);
1685 if (sourceEntry is DartEntry) {
1686 DartEntry dartEntry = sourceEntry;
1687 return !dartEntry.getValue(DartEntry.IS_CLIENT) && dartEntry.getValue(Dart Entry.IS_LAUNCHABLE);
1688 }
1689 return false;
1690 }
1691
1692 @override
1693 void mergeContext(AnalysisContext context) {
1694 if (context is InstrumentedAnalysisContextImpl) {
1695 context = (context as InstrumentedAnalysisContextImpl).basis;
1696 }
1697 if (context is! AnalysisContextImpl) {
1698 return;
1699 }
1700 // TODO(brianwilkerson) This does not lock against the other context's cache Lock.
1701 MapIterator<Source, SourceEntry> iterator = _cache.iterator();
1702 while (iterator.moveNext()) {
1703 Source newSource = iterator.key;
1704 SourceEntry existingEntry = _getReadableSourceEntry(newSource);
1705 if (existingEntry == null) {
1706 // TODO(brianwilkerson) Decide whether we really need to copy the info.
1707 _cache.put(newSource, iterator.value.writableCopy);
1708 } else {
1709 }
1710 }
1711 }
1712
1713 @override
1714 CompilationUnit parseCompilationUnit(Source source) => _getDartParseData2(sour ce, DartEntry.PARSED_UNIT, null);
1715
1716 @override
1717 ht.HtmlUnit parseHtmlUnit(Source source) => _getHtmlParseData(source, HtmlEntr y.PARSED_UNIT, null);
1718
1719 @override
1720 AnalysisResult performAnalysisTask() {
1721 if (_TRACE_PERFORM_TASK) {
1722 print("----------------------------------------");
1723 }
1724 int getStart = JavaSystem.currentTimeMillis();
1725 AnalysisTask task = nextAnalysisTask;
1726 int getEnd = JavaSystem.currentTimeMillis();
1727 if (task == null && _validateCacheConsistency()) {
1728 task = nextAnalysisTask;
1729 }
1730 if (task == null) {
1731 return new AnalysisResult(_getChangeNotices(true), getEnd - getStart, null , -1);
1732 }
1733 String taskDescription = task.toString();
1734 // if (recentTasks.add(taskDescription)) {
1735 // logInformation("Performing task: " + taskDescription);
1736 // } else {
1737 // if (TRACE_PERFORM_TASK) {
1738 // System.out.print("* ");
1739 // }
1740 // logInformation("*** Performing repeated task: " + taskDescription);
1741 // }
1742 _notifyAboutToPerformTask(taskDescription);
1743 if (_TRACE_PERFORM_TASK) {
1744 print(taskDescription);
1745 }
1746 int performStart = JavaSystem.currentTimeMillis();
1747 try {
1748 task.perform(_resultRecorder);
1749 } on ObsoleteSourceAnalysisException catch (exception) {
1750 AnalysisEngine.instance.logger.logInformation2("Could not perform analysis task: ${taskDescription}", exception);
1751 } on AnalysisException catch (exception) {
1752 if (exception.cause is! JavaIOException) {
1753 AnalysisEngine.instance.logger.logError2("Internal error while performin g the task: ${task}", exception);
1754 }
1755 }
1756 int performEnd = JavaSystem.currentTimeMillis();
1757 List<ChangeNotice> notices = _getChangeNotices(false);
1758 int noticeCount = notices.length;
1759 for (int i = 0; i < noticeCount; i++) {
1760 ChangeNotice notice = notices[i];
1761 Source source = notice.source;
1762 // TODO(brianwilkerson) Figure out whether the compilation unit is always resolved, or whether
1763 // we need to decide whether to invoke the "parsed" or "resolved" method. This might be better
1764 // done when recording task results in order to reduce the chance of error s.
1765 // if (notice.getCompilationUnit() != null) {
1766 // notifyResolvedDart(source, notice.getCompilationUnit());
1767 // } else if (notice.getHtmlUnit() != null) {
1768 // notifyResolvedHtml(source, notice.getHtmlUnit());
1769 // }
1770 _notifyErrors(source, notice.errors, notice.lineInfo);
1771 }
1772 return new AnalysisResult(notices, getEnd - getStart, task.runtimeType.toStr ing(), performEnd - performStart);
1773 }
1774
1775 @override
1776 void recordLibraryElements(Map<Source, LibraryElement> elementMap) {
1777 Source htmlSource = _sourceFactory.forUri(DartSdk.DART_HTML);
1778 for (MapEntry<Source, LibraryElement> entry in getMapEntrySet(elementMap)) {
1779 Source librarySource = entry.getKey();
1780 LibraryElement library = entry.getValue();
1781 //
1782 // Cache the element in the library's info.
1783 //
1784 DartEntry dartEntry = _getReadableDartEntry(librarySource);
1785 if (dartEntry != null) {
1786 DartEntryImpl dartCopy = dartEntry.writableCopy;
1787 _recordElementData(dartCopy, library, library.source, htmlSource);
1788 dartCopy.setValue(DartEntry.SCAN_ERRORS, AnalysisError.NO_ERRORS);
1789 dartCopy.setValue(DartEntry.PARSE_ERRORS, AnalysisError.NO_ERRORS);
1790 dartCopy.setState(DartEntry.PARSED_UNIT, CacheState.FLUSHED);
1791 dartCopy.setValueInLibrary(DartEntry.RESOLUTION_ERRORS, librarySource, A nalysisError.NO_ERRORS);
1792 dartCopy.setStateInLibrary(DartEntry.RESOLVED_UNIT, librarySource, Cache State.FLUSHED);
1793 dartCopy.setValueInLibrary(DartEntry.VERIFICATION_ERRORS, librarySource, AnalysisError.NO_ERRORS);
1794 dartCopy.setValue(DartEntry.ANGULAR_ERRORS, AnalysisError.NO_ERRORS);
1795 dartCopy.setValueInLibrary(DartEntry.HINTS, librarySource, AnalysisError .NO_ERRORS);
1796 _cache.put(librarySource, dartCopy);
1797 }
1798 }
1799 }
1800
1801 @override
1802 void removeListener(AnalysisListener listener) {
1803 _listeners.remove(listener);
1804 }
1805
1806 @override
1807 CompilationUnit resolveCompilationUnit(Source unitSource, LibraryElement libra ry) {
1808 if (library == null) {
1809 return null;
1810 }
1811 return resolveCompilationUnit2(unitSource, library.source);
1812 }
1813
1814 @override
1815 CompilationUnit resolveCompilationUnit2(Source unitSource, Source librarySourc e) => _getDartResolutionData2(unitSource, librarySource, DartEntry.RESOLVED_UNIT , null);
1816
1817 @override
1818 ht.HtmlUnit resolveHtmlUnit(Source htmlSource) {
1819 computeHtmlElement(htmlSource);
1820 return parseHtmlUnit(htmlSource);
1821 }
1822
1823 @override
1824 void set analysisOptions(AnalysisOptions options) {
1825 bool needsRecompute = this._options.analyzeAngular != options.analyzeAngular || this._options.analyzeFunctionBodies != options.analyzeFunctionBodies || this ._options.generateSdkErrors != options.generateSdkErrors || this._options.enable Async != options.enableAsync || this._options.enableDeferredLoading != options.e nableDeferredLoading || this._options.enableEnum != options.enableEnum || this._ options.dart2jsHint != options.dart2jsHint || (this._options.hint && !options.hi nt) || this._options.preserveComments != options.preserveComments;
1826 int cacheSize = options.cacheSize;
1827 if (this._options.cacheSize != cacheSize) {
1828 this._options.cacheSize = cacheSize;
1829 //cache.setMaxCacheSize(cacheSize);
1830 _privatePartition.maxCacheSize = cacheSize;
1831 //
1832 // Cap the size of the priority list to being less than the cache size. Fa ilure to do so can
1833 // result in an infinite loop in performAnalysisTask() because re-caching one AST structure
1834 // can cause another priority source's AST structure to be flushed.
1835 //
1836 int maxPriorityOrderSize = cacheSize - _PRIORITY_ORDER_SIZE_DELTA;
1837 if (_priorityOrder.length > maxPriorityOrderSize) {
1838 List<Source> newPriorityOrder = new List<Source>(maxPriorityOrderSize);
1839 JavaSystem.arraycopy(_priorityOrder, 0, newPriorityOrder, 0, maxPriority OrderSize);
1840 _priorityOrder = newPriorityOrder;
1841 }
1842 }
1843 this._options.analyzeAngular = options.analyzeAngular;
1844 this._options.analyzeFunctionBodies = options.analyzeFunctionBodies;
1845 this._options.generateSdkErrors = options.generateSdkErrors;
1846 this._options.enableAsync = options.enableAsync;
1847 this._options.enableDeferredLoading = options.enableDeferredLoading;
1848 this._options.enableEnum = options.enableEnum;
1849 this._options.dart2jsHint = options.dart2jsHint;
1850 this._options.hint = options.hint;
1851 this._options.incremental = options.incremental;
1852 this._options.preserveComments = options.preserveComments;
1853 _generateSdkErrors = options.generateSdkErrors;
1854 if (needsRecompute) {
1855 _invalidateAllLocalResolutionInformation(false);
1856 }
1857 }
1858
1859 @override
1860 void set analysisPriorityOrder(List<Source> sources) {
1861 if (sources == null || sources.isEmpty) {
1862 _priorityOrder = Source.EMPTY_ARRAY;
1863 } else {
1864 while (sources.remove(null)) {
1865 }
1866 if (sources.isEmpty) {
1867 _priorityOrder = Source.EMPTY_ARRAY;
1868 }
1869 //
1870 // Cap the size of the priority list to being less than the cache size. Fa ilure to do so can
1871 // result in an infinite loop in performAnalysisTask() because re-caching one AST structure
1872 // can cause another priority source's AST structure to be flushed.
1873 //
1874 int count = Math.min(sources.length, _options.cacheSize - _PRIORITY_ORDER_ SIZE_DELTA);
1875 _priorityOrder = new List<Source>(count);
1876 for (int i = 0; i < count; i++) {
1877 _priorityOrder[i] = sources[i];
1878 }
1879 }
1880 }
1881
1882 @override
1883 void setChangedContents(Source source, String contents, int offset, int oldLen gth, int newLength) {
1884 _recentTasks.clear();
1885 String originalContents = _contentCache.setContents(source, contents);
1886 if (contents != null) {
1887 if (contents != originalContents) {
1888 if (_options.incremental) {
1889 _incrementalAnalysisCache = IncrementalAnalysisCache.update(_increment alAnalysisCache, source, originalContents, contents, offset, oldLength, newLengt h, _getReadableSourceEntry(source));
1890 }
1891 _sourceChanged(source);
1892 SourceEntry sourceEntry = _cache.get(source);
1893 if (sourceEntry != null) {
1894 SourceEntryImpl sourceCopy = sourceEntry.writableCopy;
1895 sourceCopy.modificationTime = _contentCache.getModificationStamp(sourc e);
1896 sourceCopy.setValue(SourceEntry.CONTENT, contents);
1897 _cache.put(source, sourceCopy);
1898 }
1899 }
1900 } else if (originalContents != null) {
1901 _incrementalAnalysisCache = IncrementalAnalysisCache.clear(_incrementalAna lysisCache, source);
1902 _sourceChanged(source);
1903 }
1904 }
1905
1906 @override
1907 void setContents(Source source, String contents) {
1908 _recentTasks.clear();
1909 String originalContents = _contentCache.setContents(source, contents);
1910 if (contents != null) {
1911 if (contents != originalContents) {
1912 _incrementalAnalysisCache = IncrementalAnalysisCache.clear(_incrementalA nalysisCache, source);
1913 _sourceChanged(source);
1914 SourceEntry sourceEntry = _cache.get(source);
1915 if (sourceEntry != null) {
1916 SourceEntryImpl sourceCopy = sourceEntry.writableCopy;
1917 sourceCopy.modificationTime = _contentCache.getModificationStamp(sourc e);
1918 sourceCopy.setValue(SourceEntry.CONTENT, contents);
1919 _cache.put(source, sourceCopy);
1920 }
1921 }
1922 } else if (originalContents != null) {
1923 _incrementalAnalysisCache = IncrementalAnalysisCache.clear(_incrementalAna lysisCache, source);
1924 _sourceChanged(source);
1925 }
1926 }
1927
1928 @override
1929 void set sourceFactory(SourceFactory factory) {
1930 if (identical(_sourceFactory, factory)) {
1931 return;
1932 } else if (factory.context != null) {
1933 throw new IllegalStateException("Source factories cannot be shared between contexts");
1934 }
1935 if (_sourceFactory != null) {
1936 _sourceFactory.context = null;
1937 }
1938 factory.context = this;
1939 _sourceFactory = factory;
1940 _coreLibrarySource = _sourceFactory.forUri(DartSdk.DART_CORE);
1941 _cache = createCacheFromSourceFactory(factory);
1942 _invalidateAllLocalResolutionInformation(true);
1943 }
1944
1945 /**
1946 * Create an analysis cache based on the given source factory.
1947 *
1948 * @param factory the source factory containing the information needed to crea te the cache
1949 * @return the cache that was created
1950 */
1951 AnalysisCache createCacheFromSourceFactory(SourceFactory factory) {
1952 if (factory == null) {
1953 return new AnalysisCache(<CachePartition> [_privatePartition]);
1954 }
1955 DartSdk sdk = factory.dartSdk;
1956 if (sdk == null) {
1957 return new AnalysisCache(<CachePartition> [_privatePartition]);
1958 }
1959 return new AnalysisCache(<CachePartition> [
1960 AnalysisEngine.instance.partitionManager.forSdk(sdk),
1961 _privatePartition]);
1962 }
1963
1964 /**
1965 * Record the results produced by performing a [ResolveDartLibraryCycleTask]. If the results
1966 * were computed from data that is now out-of-date, then the results will not be recorded.
1967 *
1968 * @param task the task that was performed
1969 * @return an entry containing the computed results
1970 * @throws AnalysisException if the results could not be recorded
1971 */
1972 DartEntry recordResolveDartLibraryCycleTaskResults(ResolveDartLibraryCycleTask task) {
1973 LibraryResolver2 resolver = task.libraryResolver;
1974 CaughtException thrownException = task.exception;
1975 DartEntry unitEntry = null;
1976 Source unitSource = task.unitSource;
1977 if (resolver != null) {
1978 //
1979 // The resolver should only be null if an exception was thrown before (or while) it was
1980 // being created.
1981 //
1982 List<ResolvableLibrary> resolvedLibraries = resolver.resolvedLibraries;
1983 if (resolvedLibraries == null) {
1984 //
1985 // The resolved libraries should only be null if an exception was thrown during resolution.
1986 //
1987 unitEntry = _getReadableDartEntry(unitSource);
1988 if (unitEntry == null) {
1989 throw new AnalysisException("A Dart file became a non-Dart file: ${uni tSource.fullName}");
1990 }
1991 DartEntryImpl dartCopy = unitEntry.writableCopy;
1992 if (thrownException == null) {
1993 dartCopy.recordResolutionError(new CaughtException(new AnalysisExcepti on("In recordResolveDartLibraryCycleTaskResults, resolvedLibraries was null and there was no thrown exception"), null));
1994 } else {
1995 dartCopy.recordResolutionError(thrownException);
1996 }
1997 _cache.put(unitSource, dartCopy);
1998 _cache.remove(unitSource);
1999 if (thrownException != null) {
2000 throw new AnalysisException('<rethrow>', thrownException);
2001 }
2002 return dartCopy;
2003 }
2004 if (_allModificationTimesMatch(resolvedLibraries)) {
2005 Source htmlSource = sourceFactory.forUri(DartSdk.DART_HTML);
2006 RecordingErrorListener errorListener = resolver.errorListener;
2007 for (ResolvableLibrary library in resolvedLibraries) {
2008 Source librarySource = library.librarySource;
2009 for (Source source in library.compilationUnitSources) {
2010 CompilationUnit unit = library.getAST(source);
2011 List<AnalysisError> errors = errorListener.getErrorsForSource(source );
2012 LineInfo lineInfo = getLineInfo(source);
2013 DartEntryImpl dartCopy = _cache.get(source).writableCopy as DartEntr yImpl;
2014 if (thrownException == null) {
2015 dartCopy.setState(DartEntry.PARSED_UNIT, CacheState.FLUSHED);
2016 dartCopy.setValueInLibrary(DartEntry.RESOLVED_UNIT, librarySource, unit);
2017 dartCopy.setValueInLibrary(DartEntry.RESOLUTION_ERRORS, librarySou rce, errors);
2018 if (source == librarySource) {
2019 _recordElementData(dartCopy, library.libraryElement, librarySour ce, htmlSource);
2020 }
2021 _cache.storedAst(source);
2022 } else {
2023 dartCopy.recordResolutionErrorInLibrary(librarySource, thrownExcep tion);
2024 _cache.remove(source);
2025 }
2026 _cache.put(source, dartCopy);
2027 if (source != librarySource) {
2028 _workManager.add(source, SourcePriority.PRIORITY_PART);
2029 }
2030 if (source == unitSource) {
2031 unitEntry = dartCopy;
2032 }
2033 ChangeNoticeImpl notice = _getNotice(source);
2034 notice.compilationUnit = unit;
2035 notice.setErrors(dartCopy.allErrors, lineInfo);
2036 }
2037 }
2038 } else {
2039 PrintStringWriter writer = new PrintStringWriter();
2040 writer.println("Library resolution results discarded for");
2041 for (ResolvableLibrary library in resolvedLibraries) {
2042 for (Source source in library.compilationUnitSources) {
2043 DartEntry dartEntry = _getReadableDartEntry(source);
2044 if (dartEntry != null) {
2045 int resultTime = library.getModificationTime(source);
2046 writer.println(" ${_debuggingString(source)}; sourceTime = ${getM odificationStamp(source)}, resultTime = ${resultTime}, cacheTime = ${dartEntry.m odificationTime}");
2047 DartEntryImpl dartCopy = dartEntry.writableCopy;
2048 if (thrownException == null || resultTime >= 0) {
2049 //
2050 // The analysis was performed on out-of-date sources. Mark the c ache so that the
2051 // sources will be re-analyzed using the up-to-date sources.
2052 //
2053 dartCopy.recordResolutionNotInProcess();
2054 } else {
2055 //
2056 // We could not determine whether the sources were up-to-date or out-of-date. Mark
2057 // the cache so that we won't attempt to re-analyze the sources until there's a
2058 // good chance that we'll be able to do so without error.
2059 //
2060 dartCopy.recordResolutionError(thrownException);
2061 _cache.remove(source);
2062 }
2063 _cache.put(source, dartCopy);
2064 if (source == unitSource) {
2065 unitEntry = dartCopy;
2066 }
2067 } else {
2068 writer.println(" ${_debuggingString(source)}; sourceTime = ${getM odificationStamp(source)}, no entry");
2069 }
2070 }
2071 }
2072 _logInformation(writer.toString());
2073 }
2074 }
2075 if (thrownException != null) {
2076 throw new AnalysisException('<rethrow>', thrownException);
2077 }
2078 if (unitEntry == null) {
2079 unitEntry = _getReadableDartEntry(unitSource);
2080 if (unitEntry == null) {
2081 throw new AnalysisException("A Dart file became a non-Dart file: ${unitS ource.fullName}");
2082 }
2083 }
2084 return unitEntry;
2085 }
2086
2087 DartEntry recordResolveDartLibraryTaskResults(ResolveDartLibraryTask task) {
2088 LibraryResolver resolver = task.libraryResolver;
2089 CaughtException thrownException = task.exception;
2090 DartEntry unitEntry = null;
2091 Source unitSource = task.unitSource;
2092 if (resolver != null) {
2093 //
2094 // The resolver should only be null if an exception was thrown before (or while) it was
2095 // being created.
2096 //
2097 Set<Library> resolvedLibraries = resolver.resolvedLibraries;
2098 if (resolvedLibraries == null) {
2099 //
2100 // The resolved libraries should only be null if an exception was thrown during resolution.
2101 //
2102 unitEntry = _getReadableDartEntry(unitSource);
2103 if (unitEntry == null) {
2104 throw new AnalysisException("A Dart file became a non-Dart file: ${uni tSource.fullName}");
2105 }
2106 DartEntryImpl dartCopy = unitEntry.writableCopy;
2107 if (thrownException == null) {
2108 dartCopy.recordResolutionError(new CaughtException(new AnalysisExcepti on("In recordResolveDartLibraryTaskResults, resolvedLibraries was null and there was no thrown exception"), null));
2109 } else {
2110 dartCopy.recordResolutionError(thrownException);
2111 }
2112 _cache.put(unitSource, dartCopy);
2113 _cache.remove(unitSource);
2114 if (thrownException != null) {
2115 throw new AnalysisException('<rethrow>', thrownException);
2116 }
2117 return dartCopy;
2118 }
2119 if (_allModificationTimesMatch2(resolvedLibraries)) {
2120 Source htmlSource = sourceFactory.forUri(DartSdk.DART_HTML);
2121 RecordingErrorListener errorListener = resolver.errorListener;
2122 for (Library library in resolvedLibraries) {
2123 Source librarySource = library.librarySource;
2124 for (Source source in library.compilationUnitSources) {
2125 CompilationUnit unit = library.getAST(source);
2126 List<AnalysisError> errors = errorListener.getErrorsForSource(source );
2127 LineInfo lineInfo = getLineInfo(source);
2128 DartEntry dartEntry = _cache.get(source) as DartEntry;
2129 int sourceTime = getModificationStamp(source);
2130 if (dartEntry.modificationTime != sourceTime) {
2131 // The source has changed without the context being notified. Simu late notification.
2132 _sourceChanged(source);
2133 dartEntry = _getReadableDartEntry(source);
2134 if (dartEntry == null) {
2135 throw new AnalysisException("A Dart file became a non-Dart file: ${source.fullName}");
2136 }
2137 }
2138 DartEntryImpl dartCopy = dartEntry.writableCopy;
2139 if (thrownException == null) {
2140 dartCopy.setValue(SourceEntry.LINE_INFO, lineInfo);
2141 dartCopy.setState(DartEntry.PARSED_UNIT, CacheState.FLUSHED);
2142 dartCopy.setValueInLibrary(DartEntry.RESOLVED_UNIT, librarySource, unit);
2143 dartCopy.setValueInLibrary(DartEntry.RESOLUTION_ERRORS, librarySou rce, errors);
2144 if (source == librarySource) {
2145 _recordElementData(dartCopy, library.libraryElement, librarySour ce, htmlSource);
2146 }
2147 _cache.storedAst(source);
2148 } else {
2149 dartCopy.recordResolutionErrorInLibrary(librarySource, thrownExcep tion);
2150 _cache.remove(source);
2151 }
2152 _cache.put(source, dartCopy);
2153 if (source != librarySource) {
2154 _workManager.add(source, SourcePriority.PRIORITY_PART);
2155 }
2156 if (source == unitSource) {
2157 unitEntry = dartCopy;
2158 }
2159 ChangeNoticeImpl notice = _getNotice(source);
2160 notice.compilationUnit = unit;
2161 notice.setErrors(dartCopy.allErrors, lineInfo);
2162 }
2163 }
2164 } else {
2165 PrintStringWriter writer = new PrintStringWriter();
2166 writer.println("Library resolution results discarded for");
2167 for (Library library in resolvedLibraries) {
2168 for (Source source in library.compilationUnitSources) {
2169 DartEntry dartEntry = _getReadableDartEntry(source);
2170 if (dartEntry != null) {
2171 int resultTime = library.getModificationTime(source);
2172 writer.println(" ${_debuggingString(source)}; sourceTime = ${getM odificationStamp(source)}, resultTime = ${resultTime}, cacheTime = ${dartEntry.m odificationTime}");
2173 DartEntryImpl dartCopy = dartEntry.writableCopy;
2174 if (thrownException == null || resultTime >= 0) {
2175 //
2176 // The analysis was performed on out-of-date sources. Mark the c ache so that the
2177 // sources will be re-analyzed using the up-to-date sources.
2178 //
2179 dartCopy.recordResolutionNotInProcess();
2180 } else {
2181 //
2182 // We could not determine whether the sources were up-to-date or out-of-date. Mark
2183 // the cache so that we won't attempt to re-analyze the sources until there's a
2184 // good chance that we'll be able to do so without error.
2185 //
2186 dartCopy.recordResolutionError(thrownException);
2187 _cache.remove(source);
2188 }
2189 _cache.put(source, dartCopy);
2190 if (source == unitSource) {
2191 unitEntry = dartCopy;
2192 }
2193 } else {
2194 writer.println(" ${_debuggingString(source)}; sourceTime = ${getM odificationStamp(source)}, no entry");
2195 }
2196 }
2197 }
2198 _logInformation(writer.toString());
2199 }
2200 }
2201 if (thrownException != null) {
2202 throw new AnalysisException('<rethrow>', thrownException);
2203 }
2204 if (unitEntry == null) {
2205 unitEntry = _getReadableDartEntry(unitSource);
2206 if (unitEntry == null) {
2207 throw new AnalysisException("A Dart file became a non-Dart file: ${unitS ource.fullName}");
2208 }
2209 }
2210 return unitEntry;
2211 }
2212
2213 /**
2214 * Record that we have accessed the AST structure associated with the given so urce. At the moment,
2215 * there is no differentiation between the parsed and resolved forms of the AS T.
2216 *
2217 * @param source the source whose AST structure was accessed
2218 */
2219 void _accessedAst(Source source) {
2220 _cache.accessedAst(source);
2221 }
2222
2223 /**
2224 * Add all of the sources contained in the given source container to the given list of sources.
2225 *
2226 * Note: This method must only be invoked while we are synchronized on [cacheL ock].
2227 *
2228 * @param sources the list to which sources are to be added
2229 * @param container the source container containing the sources to be added to the list
2230 */
2231 void _addSourcesInContainer(List<Source> sources, SourceContainer container) {
2232 MapIterator<Source, SourceEntry> iterator = _cache.iterator();
2233 while (iterator.moveNext()) {
2234 Source source = iterator.key;
2235 if (container.contains(source)) {
2236 sources.add(source);
2237 }
2238 }
2239 }
2240
2241 /**
2242 * Return `true` if the modification times of the sources used by the given li brary resolver
2243 * to resolve one or more libraries are consistent with the modification times in the cache.
2244 *
2245 * @param resolver the library resolver used to resolve one or more libraries
2246 * @return `true` if we should record the results of the resolution
2247 * @throws AnalysisException if any of the modification times could not be det ermined (this should
2248 * not happen)
2249 */
2250 bool _allModificationTimesMatch(List<ResolvableLibrary> resolvedLibraries) {
2251 bool allTimesMatch = true;
2252 for (ResolvableLibrary library in resolvedLibraries) {
2253 for (Source source in library.compilationUnitSources) {
2254 DartEntry dartEntry = _getReadableDartEntry(source);
2255 if (dartEntry == null) {
2256 // This shouldn't be possible because we should never have performed t he task if the
2257 // source didn't represent a Dart file, but check to be safe.
2258 throw new AnalysisException("Internal error: attempting to resolve non -Dart file as a Dart file: ${source.fullName}");
2259 }
2260 int sourceTime = getModificationStamp(source);
2261 int resultTime = library.getModificationTime(source);
2262 if (sourceTime != resultTime) {
2263 // The source has changed without the context being notified. Simulate notification.
2264 _sourceChanged(source);
2265 allTimesMatch = false;
2266 }
2267 }
2268 }
2269 return allTimesMatch;
2270 }
2271
2272 /**
2273 * Return `true` if the modification times of the sources used by the given li brary resolver
2274 * to resolve one or more libraries are consistent with the modification times in the cache.
2275 *
2276 * @param resolver the library resolver used to resolve one or more libraries
2277 * @return `true` if we should record the results of the resolution
2278 * @throws AnalysisException if any of the modification times could not be det ermined (this should
2279 * not happen)
2280 */
2281 bool _allModificationTimesMatch2(Set<Library> resolvedLibraries) {
2282 bool allTimesMatch = true;
2283 for (Library library in resolvedLibraries) {
2284 for (Source source in library.compilationUnitSources) {
2285 DartEntry dartEntry = _getReadableDartEntry(source);
2286 if (dartEntry == null) {
2287 // This shouldn't be possible because we should never have performed t he task if the
2288 // source didn't represent a Dart file, but check to be safe.
2289 throw new AnalysisException("Internal error: attempting to resolve non -Dart file as a Dart file: ${source.fullName}");
2290 }
2291 int sourceTime = getModificationStamp(source);
2292 int resultTime = library.getModificationTime(source);
2293 if (sourceTime != resultTime) {
2294 // The source has changed without the context being notified. Simulate notification.
2295 _sourceChanged(source);
2296 allTimesMatch = false;
2297 }
2298 }
2299 }
2300 return allTimesMatch;
2301 }
2302
2303 /**
2304 * Given a source for a Dart file and the library that contains it, return a c ache entry in which
2305 * the state of the data represented by the given descriptor is either [CacheS tate#VALID] or
2306 * [CacheState#ERROR]. This method assumes that the data can be produced by ge nerating hints
2307 * for the library if the data is not already cached.
2308 *
2309 * <b>Note:</b> This method cannot be used in an async environment.
2310 *
2311 * @param unitSource the source representing the Dart file
2312 * @param librarySource the source representing the library containing the Dar t file
2313 * @param dartEntry the cache entry associated with the Dart file
2314 * @param descriptor the descriptor representing the data to be returned
2315 * @return a cache entry containing the required data
2316 * @throws AnalysisException if data could not be returned because the source could not be parsed
2317 */
2318 DartEntry _cacheDartHintData(Source unitSource, Source librarySource, DartEntr y dartEntry, DataDescriptor descriptor) {
2319 //
2320 // Check to see whether we already have the information being requested.
2321 //
2322 CacheState state = dartEntry.getStateInLibrary(descriptor, librarySource);
2323 while (state != CacheState.ERROR && state != CacheState.VALID) {
2324 //
2325 // If not, compute the information. Unless the modification date of the so urce continues to
2326 // change, this loop will eventually terminate.
2327 //
2328 DartEntry libraryEntry = _getReadableDartEntry(librarySource);
2329 libraryEntry = _cacheDartResolutionData(librarySource, librarySource, libr aryEntry, DartEntry.ELEMENT);
2330 LibraryElement libraryElement = libraryEntry.getValue(DartEntry.ELEMENT);
2331 CompilationUnitElement definingUnit = libraryElement.definingCompilationUn it;
2332 List<CompilationUnitElement> parts = libraryElement.parts;
2333 List<TimestampedData<CompilationUnit>> units = new List<TimestampedData>(p arts.length + 1);
2334 units[0] = _getResolvedUnit(definingUnit, librarySource);
2335 if (units[0] == null) {
2336 Source source = definingUnit.source;
2337 units[0] = new TimestampedData<CompilationUnit>(getModificationStamp(sou rce), resolveCompilationUnit(source, libraryElement));
2338 }
2339 for (int i = 0; i < parts.length; i++) {
2340 units[i + 1] = _getResolvedUnit(parts[i], librarySource);
2341 if (units[i + 1] == null) {
2342 Source source = parts[i].source;
2343 units[i + 1] = new TimestampedData<CompilationUnit>(getModificationSta mp(source), resolveCompilationUnit(source, libraryElement));
2344 }
2345 }
2346 dartEntry = new GenerateDartHintsTask(this, units, getLibraryElement(libra rySource)).perform(_resultRecorder) as DartEntry;
2347 state = dartEntry.getStateInLibrary(descriptor, librarySource);
2348 }
2349 return dartEntry;
2350 }
2351
2352 /**
2353 * Given a source for a Dart file, return a cache entry in which the state of the data represented
2354 * by the given descriptor is either [CacheState#VALID] or [CacheState#ERROR]. This
2355 * method assumes that the data can be produced by parsing the source if it is not already cached.
2356 *
2357 * <b>Note:</b> This method cannot be used in an async environment.
2358 *
2359 * @param source the source representing the Dart file
2360 * @param dartEntry the cache entry associated with the Dart file
2361 * @param descriptor the descriptor representing the data to be returned
2362 * @return a cache entry containing the required data
2363 * @throws AnalysisException if data could not be returned because the source could not be parsed
2364 */
2365 DartEntry _cacheDartParseData(Source source, DartEntry dartEntry, DataDescript or descriptor) {
2366 if (identical(descriptor, DartEntry.PARSED_UNIT)) {
2367 if (dartEntry.hasResolvableCompilationUnit) {
2368 return dartEntry;
2369 }
2370 }
2371 //
2372 // Check to see whether we already have the information being requested.
2373 //
2374 CacheState state = dartEntry.getState(descriptor);
2375 while (state != CacheState.ERROR && state != CacheState.VALID) {
2376 //
2377 // If not, compute the information. Unless the modification date of the so urce continues to
2378 // change, this loop will eventually terminate.
2379 //
2380 dartEntry = _cacheDartScanData(source, dartEntry, DartEntry.TOKEN_STREAM);
2381 dartEntry = new ParseDartTask(this, source, dartEntry.modificationTime, da rtEntry.getValue(DartEntry.TOKEN_STREAM), dartEntry.getValue(SourceEntry.LINE_IN FO)).perform(_resultRecorder) as DartEntry;
2382 state = dartEntry.getState(descriptor);
2383 }
2384 return dartEntry;
2385 }
2386
2387 /**
2388 * Given a source for a Dart file and the library that contains it, return a c ache entry in which
2389 * the state of the data represented by the given descriptor is either [CacheS tate#VALID] or
2390 * [CacheState#ERROR]. This method assumes that the data can be produced by re solving the
2391 * source in the context of the library if it is not already cached.
2392 *
2393 * <b>Note:</b> This method cannot be used in an async environment.
2394 *
2395 * @param unitSource the source representing the Dart file
2396 * @param librarySource the source representing the library containing the Dar t file
2397 * @param dartEntry the cache entry associated with the Dart file
2398 * @param descriptor the descriptor representing the data to be returned
2399 * @return a cache entry containing the required data
2400 * @throws AnalysisException if data could not be returned because the source could not be parsed
2401 */
2402 DartEntry _cacheDartResolutionData(Source unitSource, Source librarySource, Da rtEntry dartEntry, DataDescriptor descriptor) {
2403 //
2404 // Check to see whether we already have the information being requested.
2405 //
2406 CacheState state = (identical(descriptor, DartEntry.ELEMENT)) ? dartEntry.ge tState(descriptor) : dartEntry.getStateInLibrary(descriptor, librarySource);
2407 while (state != CacheState.ERROR && state != CacheState.VALID) {
2408 //
2409 // If not, compute the information. Unless the modification date of the so urce continues to
2410 // change, this loop will eventually terminate.
2411 //
2412 // TODO(brianwilkerson) As an optimization, if we already have the element model for the
2413 // library we can use ResolveDartUnitTask to produce the resolved AST stru cture much faster.
2414 dartEntry = new ResolveDartLibraryTask(this, unitSource, librarySource).pe rform(_resultRecorder) as DartEntry;
2415 state = (identical(descriptor, DartEntry.ELEMENT)) ? dartEntry.getState(de scriptor) : dartEntry.getStateInLibrary(descriptor, librarySource);
2416 }
2417 return dartEntry;
2418 }
2419
2420 /**
2421 * Given a source for a Dart file, return a cache entry in which the state of the data represented
2422 * by the given descriptor is either [CacheState#VALID] or [CacheState#ERROR]. This
2423 * method assumes that the data can be produced by scanning the source if it i s not already
2424 * cached.
2425 *
2426 * <b>Note:</b> This method cannot be used in an async environment.
2427 *
2428 * @param source the source representing the Dart file
2429 * @param dartEntry the cache entry associated with the Dart file
2430 * @param descriptor the descriptor representing the data to be returned
2431 * @return a cache entry containing the required data
2432 * @throws AnalysisException if data could not be returned because the source could not be scanned
2433 */
2434 DartEntry _cacheDartScanData(Source source, DartEntry dartEntry, DataDescripto r descriptor) {
2435 //
2436 // Check to see whether we already have the information being requested.
2437 //
2438 CacheState state = dartEntry.getState(descriptor);
2439 while (state != CacheState.ERROR && state != CacheState.VALID) {
2440 //
2441 // If not, compute the information. Unless the modification date of the so urce continues to
2442 // change, this loop will eventually terminate.
2443 //
2444 try {
2445 if (dartEntry.getState(SourceEntry.CONTENT) != CacheState.VALID) {
2446 dartEntry = new GetContentTask(this, source).perform(_resultRecorder) as DartEntry;
2447 }
2448 dartEntry = new ScanDartTask(this, source, dartEntry.modificationTime, d artEntry.getValue(SourceEntry.CONTENT)).perform(_resultRecorder) as DartEntry;
2449 } on AnalysisException catch (exception) {
2450 throw exception;
2451 } catch (exception, stackTrace) {
2452 throw new AnalysisException("Exception", new CaughtException(exception, stackTrace));
2453 }
2454 state = dartEntry.getState(descriptor);
2455 }
2456 return dartEntry;
2457 }
2458
2459 /**
2460 * Given a source for a Dart file and the library that contains it, return a c ache entry in which
2461 * the state of the data represented by the given descriptor is either [CacheS tate#VALID] or
2462 * [CacheState#ERROR]. This method assumes that the data can be produced by ve rifying the
2463 * source in the given library if the data is not already cached.
2464 *
2465 * <b>Note:</b> This method cannot be used in an async environment.
2466 *
2467 * @param unitSource the source representing the Dart file
2468 * @param librarySource the source representing the library containing the Dar t file
2469 * @param dartEntry the cache entry associated with the Dart file
2470 * @param descriptor the descriptor representing the data to be returned
2471 * @return a cache entry containing the required data
2472 * @throws AnalysisException if data could not be returned because the source could not be parsed
2473 */
2474 DartEntry _cacheDartVerificationData(Source unitSource, Source librarySource, DartEntry dartEntry, DataDescriptor descriptor) {
2475 //
2476 // Check to see whether we already have the information being requested.
2477 //
2478 CacheState state = dartEntry.getStateInLibrary(descriptor, librarySource);
2479 while (state != CacheState.ERROR && state != CacheState.VALID) {
2480 //
2481 // If not, compute the information. Unless the modification date of the so urce continues to
2482 // change, this loop will eventually terminate.
2483 //
2484 LibraryElement library = computeLibraryElement(librarySource);
2485 CompilationUnit unit = resolveCompilationUnit(unitSource, library);
2486 if (unit == null) {
2487 throw new AnalysisException("Could not resolve compilation unit ${unitSo urce.fullName} in ${librarySource.fullName}");
2488 }
2489 dartEntry = new GenerateDartErrorsTask(this, unitSource, dartEntry.modific ationTime, unit, library).perform(_resultRecorder) as DartEntry;
2490 state = dartEntry.getStateInLibrary(descriptor, librarySource);
2491 }
2492 return dartEntry;
2493 }
2494
2495 /**
2496 * Given a source for an HTML file, return a cache entry in which all of the d ata represented by
2497 * the state of the given descriptors is either [CacheState#VALID] or
2498 * [CacheState#ERROR]. This method assumes that the data can be produced by pa rsing the
2499 * source if it is not already cached.
2500 *
2501 * <b>Note:</b> This method cannot be used in an async environment.
2502 *
2503 * @param source the source representing the HTML file
2504 * @param htmlEntry the cache entry associated with the HTML file
2505 * @param descriptor the descriptor representing the data to be returned
2506 * @return a cache entry containing the required data
2507 * @throws AnalysisException if data could not be returned because the source could not be
2508 * resolved
2509 */
2510 HtmlEntry _cacheHtmlParseData(Source source, HtmlEntry htmlEntry, DataDescript or descriptor) {
2511 if (identical(descriptor, HtmlEntry.PARSED_UNIT)) {
2512 ht.HtmlUnit unit = htmlEntry.anyParsedUnit;
2513 if (unit != null) {
2514 return htmlEntry;
2515 }
2516 }
2517 //
2518 // Check to see whether we already have the information being requested.
2519 //
2520 CacheState state = htmlEntry.getState(descriptor);
2521 while (state != CacheState.ERROR && state != CacheState.VALID) {
2522 //
2523 // If not, compute the information. Unless the modification date of the so urce continues to
2524 // change, this loop will eventually terminate.
2525 //
2526 try {
2527 if (htmlEntry.getState(SourceEntry.CONTENT) != CacheState.VALID) {
2528 htmlEntry = new GetContentTask(this, source).perform(_resultRecorder) as HtmlEntry;
2529 }
2530 htmlEntry = new ParseHtmlTask(this, source, htmlEntry.modificationTime, htmlEntry.getValue(SourceEntry.CONTENT)).perform(_resultRecorder) as HtmlEntry;
2531 } on AnalysisException catch (exception) {
2532 throw exception;
2533 } catch (exception, stackTrace) {
2534 throw new AnalysisException("Exception", new CaughtException(exception, stackTrace));
2535 }
2536 state = htmlEntry.getState(descriptor);
2537 }
2538 return htmlEntry;
2539 }
2540
2541 /**
2542 * Given a source for an HTML file, return a cache entry in which the state of the data
2543 * represented by the given descriptor is either [CacheState#VALID] or
2544 * [CacheState#ERROR]. This method assumes that the data can be produced by re solving the
2545 * source if it is not already cached.
2546 *
2547 * <b>Note:</b> This method cannot be used in an async environment.
2548 *
2549 * @param source the source representing the HTML file
2550 * @param dartEntry the cache entry associated with the HTML file
2551 * @param descriptor the descriptor representing the data to be returned
2552 * @return a cache entry containing the required data
2553 * @throws AnalysisException if data could not be returned because the source could not be
2554 * resolved
2555 */
2556 HtmlEntry _cacheHtmlResolutionData(Source source, HtmlEntry htmlEntry, DataDes criptor descriptor) {
2557 //
2558 // Check to see whether we already have the information being requested.
2559 //
2560 CacheState state = htmlEntry.getState(descriptor);
2561 while (state != CacheState.ERROR && state != CacheState.VALID) {
2562 //
2563 // If not, compute the information. Unless the modification date of the so urce continues to
2564 // change, this loop will eventually terminate.
2565 //
2566 htmlEntry = _cacheHtmlParseData(source, htmlEntry, HtmlEntry.PARSED_UNIT);
2567 htmlEntry = new ResolveHtmlTask(this, source, htmlEntry.modificationTime, htmlEntry.getValue(HtmlEntry.PARSED_UNIT)).perform(_resultRecorder) as HtmlEntry ;
2568 state = htmlEntry.getState(descriptor);
2569 }
2570 return htmlEntry;
2571 }
2572
2573 /**
2574 * Compute the transitive closure of all libraries that depend on the given li brary by adding such
2575 * libraries to the given collection.
2576 *
2577 * @param library the library on which the other libraries depend
2578 * @param librariesToInvalidate the libraries that depend on the given library
2579 */
2580 void _computeAllLibrariesDependingOn(Source library, HashSet<Source> libraries ToInvalidate) {
2581 if (librariesToInvalidate.add(library)) {
2582 for (Source dependentLibrary in getLibrariesDependingOn(library)) {
2583 _computeAllLibrariesDependingOn(dependentLibrary, librariesToInvalidate) ;
2584 }
2585 }
2586 }
2587
2588 /**
2589 * Compute the priority that should be used when the source associated with th e given entry is
2590 * added to the work manager.
2591 *
2592 * @param dartEntry the entry associated with the source
2593 * @return the priority that was computed
2594 */
2595 SourcePriority _computePriority(DartEntry dartEntry) {
2596 SourceKind kind = dartEntry.kind;
2597 if (kind == SourceKind.LIBRARY) {
2598 return SourcePriority.LIBRARY;
2599 } else if (kind == SourceKind.PART) {
2600 return SourcePriority.NORMAL_PART;
2601 }
2602 return SourcePriority.UNKNOWN;
2603 }
2604
2605 /**
2606 * Given the encoded form of a source, use the source factory to reconstitute the original source.
2607 *
2608 * @param encoding the encoded form of a source
2609 * @return the source represented by the encoding
2610 */
2611 Source _computeSourceFromEncoding(String encoding) => _sourceFactory.fromEncod ing(encoding);
2612
2613 /**
2614 * Return `true` if the given array of sources contains the given source.
2615 *
2616 * @param sources the sources being searched
2617 * @param targetSource the source being searched for
2618 * @return `true` if the given source is in the array
2619 */
2620 bool _contains(List<Source> sources, Source targetSource) {
2621 for (Source source in sources) {
2622 if (source == targetSource) {
2623 return true;
2624 }
2625 }
2626 return false;
2627 }
2628
2629 /**
2630 * Return `true` if the given array of sources contains any of the given targe t sources.
2631 *
2632 * @param sources the sources being searched
2633 * @param targetSources the sources being searched for
2634 * @return `true` if any of the given target sources are in the array
2635 */
2636 bool _containsAny(List<Source> sources, List<Source> targetSources) {
2637 for (Source targetSource in targetSources) {
2638 if (_contains(sources, targetSource)) {
2639 return true;
2640 }
2641 }
2642 return false;
2643 }
2644
2645 /**
2646 * Create a [GenerateDartErrorsTask] for the given source, marking the verific ation errors
2647 * as being in-process. The compilation unit and the library can be the same i f the compilation
2648 * unit is the defining compilation unit of the library.
2649 *
2650 * @param unitSource the source for the compilation unit to be verified
2651 * @param unitEntry the entry for the compilation unit
2652 * @param librarySource the source for the library containing the compilation unit
2653 * @param libraryEntry the entry for the library
2654 * @return task data representing the created task
2655 */
2656 AnalysisContextImpl_TaskData _createGenerateDartErrorsTask(Source unitSource, DartEntry unitEntry, Source librarySource, DartEntry libraryEntry) {
2657 if (unitEntry.getStateInLibrary(DartEntry.RESOLVED_UNIT, librarySource) != C acheState.VALID || libraryEntry.getState(DartEntry.ELEMENT) != CacheState.VALID) {
2658 return _createResolveDartLibraryTask(librarySource, libraryEntry);
2659 }
2660 CompilationUnit unit = unitEntry.getValueInLibrary(DartEntry.RESOLVED_UNIT, librarySource);
2661 if (unit == null) {
2662 CaughtException exception = new CaughtException(new AnalysisException("Ent ry has VALID state for RESOLVED_UNIT but null value for ${unitSource.fullName} i n ${librarySource.fullName}"), null);
2663 AnalysisEngine.instance.logger.logInformation2(exception.toString(), excep tion);
2664 DartEntryImpl dartCopy = unitEntry.writableCopy;
2665 dartCopy.recordResolutionError(exception);
2666 _cache.put(unitSource, dartCopy);
2667 return new AnalysisContextImpl_TaskData(null, false);
2668 }
2669 LibraryElement libraryElement = libraryEntry.getValue(DartEntry.ELEMENT);
2670 DartEntryImpl dartCopy = unitEntry.writableCopy;
2671 dartCopy.setStateInLibrary(DartEntry.VERIFICATION_ERRORS, librarySource, Cac heState.IN_PROCESS);
2672 _cache.put(unitSource, dartCopy);
2673 return new AnalysisContextImpl_TaskData(new GenerateDartErrorsTask(this, uni tSource, dartCopy.modificationTime, unit, libraryElement), false);
2674 }
2675
2676 /**
2677 * Create a [GenerateDartHintsTask] for the given source, marking the hints as being
2678 * in-process.
2679 *
2680 * @param source the source whose content is to be verified
2681 * @param dartEntry the entry for the source
2682 * @param librarySource the source for the library containing the source
2683 * @param libraryEntry the entry for the library
2684 * @return task data representing the created task
2685 */
2686 AnalysisContextImpl_TaskData _createGenerateDartHintsTask(Source source, DartE ntry dartEntry, Source librarySource, DartEntry libraryEntry) {
2687 if (libraryEntry.getState(DartEntry.ELEMENT) != CacheState.VALID) {
2688 return _createResolveDartLibraryTask(librarySource, libraryEntry);
2689 }
2690 LibraryElement libraryElement = libraryEntry.getValue(DartEntry.ELEMENT);
2691 CompilationUnitElement definingUnit = libraryElement.definingCompilationUnit ;
2692 List<CompilationUnitElement> parts = libraryElement.parts;
2693 List<TimestampedData<CompilationUnit>> units = new List<TimestampedData>(par ts.length + 1);
2694 units[0] = _getResolvedUnit(definingUnit, librarySource);
2695 if (units[0] == null) {
2696 // TODO(brianwilkerson) We should return a ResolveDartUnitTask (unless the re are multiple ASTs
2697 // that need to be resolved.
2698 return _createResolveDartLibraryTask(librarySource, libraryEntry);
2699 }
2700 for (int i = 0; i < parts.length; i++) {
2701 units[i + 1] = _getResolvedUnit(parts[i], librarySource);
2702 if (units[i + 1] == null) {
2703 // TODO(brianwilkerson) We should return a ResolveDartUnitTask (unless t here are multiple
2704 // ASTs that need to be resolved.
2705 return _createResolveDartLibraryTask(librarySource, libraryEntry);
2706 }
2707 }
2708 DartEntryImpl dartCopy = dartEntry.writableCopy;
2709 dartCopy.setStateInLibrary(DartEntry.HINTS, librarySource, CacheState.IN_PRO CESS);
2710 _cache.put(source, dartCopy);
2711 return new AnalysisContextImpl_TaskData(new GenerateDartHintsTask(this, unit s, libraryElement), false);
2712 }
2713
2714 /**
2715 * Create a [GetContentTask] for the given source, marking the content as bein g in-process.
2716 *
2717 * @param source the source whose content is to be accessed
2718 * @param sourceEntry the entry for the source
2719 * @return task data representing the created task
2720 */
2721 AnalysisContextImpl_TaskData _createGetContentTask(Source source, SourceEntry sourceEntry) {
2722 SourceEntryImpl sourceCopy = sourceEntry.writableCopy;
2723 sourceCopy.setState(SourceEntry.CONTENT, CacheState.IN_PROCESS);
2724 _cache.put(source, sourceCopy);
2725 return new AnalysisContextImpl_TaskData(new GetContentTask(this, source), fa lse);
2726 }
2727
2728 /**
2729 * Create a [ParseDartTask] for the given source, marking the parse errors as being
2730 * in-process.
2731 *
2732 * @param source the source whose content is to be parsed
2733 * @param dartEntry the entry for the source
2734 * @return task data representing the created task
2735 */
2736 AnalysisContextImpl_TaskData _createParseDartTask(Source source, DartEntry dar tEntry) {
2737 if (dartEntry.getState(DartEntry.TOKEN_STREAM) != CacheState.VALID || dartEn try.getState(SourceEntry.LINE_INFO) != CacheState.VALID) {
2738 return _createScanDartTask(source, dartEntry);
2739 }
2740 Token tokenStream = dartEntry.getValue(DartEntry.TOKEN_STREAM);
2741 DartEntryImpl dartCopy = dartEntry.writableCopy;
2742 dartCopy.setState(DartEntry.TOKEN_STREAM, CacheState.FLUSHED);
2743 dartCopy.setState(DartEntry.PARSE_ERRORS, CacheState.IN_PROCESS);
2744 _cache.put(source, dartCopy);
2745 return new AnalysisContextImpl_TaskData(new ParseDartTask(this, source, dart Copy.modificationTime, tokenStream, dartEntry.getValue(SourceEntry.LINE_INFO)), false);
2746 }
2747
2748 /**
2749 * Create a [ParseHtmlTask] for the given source, marking the parse errors as being
2750 * in-process.
2751 *
2752 * @param source the source whose content is to be parsed
2753 * @param htmlEntry the entry for the source
2754 * @return task data representing the created task
2755 */
2756 AnalysisContextImpl_TaskData _createParseHtmlTask(Source source, HtmlEntry htm lEntry) {
2757 if (htmlEntry.getState(SourceEntry.CONTENT) != CacheState.VALID) {
2758 return _createGetContentTask(source, htmlEntry);
2759 }
2760 String content = htmlEntry.getValue(SourceEntry.CONTENT);
2761 HtmlEntryImpl htmlCopy = htmlEntry.writableCopy;
2762 htmlCopy.setState(SourceEntry.CONTENT, CacheState.FLUSHED);
2763 htmlCopy.setState(HtmlEntry.PARSE_ERRORS, CacheState.IN_PROCESS);
2764 _cache.put(source, htmlCopy);
2765 return new AnalysisContextImpl_TaskData(new ParseHtmlTask(this, source, html Copy.modificationTime, content), false);
2766 }
2767
2768 /**
2769 * Create a [PolymerBuildHtmlTask] for the given source, marking the Polymer e lements as
2770 * being in-process.
2771 *
2772 * @param source the source whose content is to be processed
2773 * @param htmlEntry the entry for the source
2774 * @return task data representing the created task
2775 */
2776 AnalysisContextImpl_TaskData _createPolymerBuildHtmlTask(Source source, HtmlEn try htmlEntry) {
2777 if (htmlEntry.getState(HtmlEntry.RESOLVED_UNIT) != CacheState.VALID) {
2778 return _createResolveHtmlTask(source, htmlEntry);
2779 }
2780 HtmlEntryImpl htmlCopy = htmlEntry.writableCopy;
2781 htmlCopy.setState(HtmlEntry.POLYMER_BUILD_ERRORS, CacheState.IN_PROCESS);
2782 _cache.put(source, htmlCopy);
2783 return new AnalysisContextImpl_TaskData(new PolymerBuildHtmlTask(this, sourc e, htmlCopy.modificationTime, htmlEntry.getValue(SourceEntry.LINE_INFO), htmlCop y.getValue(HtmlEntry.RESOLVED_UNIT)), false);
2784 }
2785
2786 /**
2787 * Create a [PolymerResolveHtmlTask] for the given source, marking the Polymer errors as
2788 * being in-process.
2789 *
2790 * @param source the source whose content is to be resolved
2791 * @param htmlEntry the entry for the source
2792 * @return task data representing the created task
2793 */
2794 AnalysisContextImpl_TaskData _createPolymerResolveHtmlTask(Source source, Html Entry htmlEntry) {
2795 if (htmlEntry.getState(HtmlEntry.RESOLVED_UNIT) != CacheState.VALID) {
2796 return _createResolveHtmlTask(source, htmlEntry);
2797 }
2798 HtmlEntryImpl htmlCopy = htmlEntry.writableCopy;
2799 htmlCopy.setState(HtmlEntry.POLYMER_RESOLUTION_ERRORS, CacheState.IN_PROCESS );
2800 _cache.put(source, htmlCopy);
2801 return new AnalysisContextImpl_TaskData(new PolymerResolveHtmlTask(this, sou rce, htmlCopy.modificationTime, htmlEntry.getValue(SourceEntry.LINE_INFO), htmlC opy.getValue(HtmlEntry.RESOLVED_UNIT)), false);
2802 }
2803
2804 /**
2805 * Create a [ResolveAngularComponentTemplateTask] for the given source, markin g the angular
2806 * errors as being in-process.
2807 *
2808 * @param source the source whose content is to be resolved
2809 * @param htmlEntry the entry for the source
2810 * @return task data representing the created task
2811 */
2812 AnalysisContextImpl_TaskData _createResolveAngularComponentTemplateTask(Source source, HtmlEntry htmlEntry) {
2813 if (htmlEntry.getState(HtmlEntry.RESOLVED_UNIT) != CacheState.VALID) {
2814 return _createResolveHtmlTask(source, htmlEntry);
2815 }
2816 AngularApplication application = htmlEntry.getValue(HtmlEntry.ANGULAR_APPLIC ATION);
2817 AngularComponentElement component = htmlEntry.getValue(HtmlEntry.ANGULAR_COM PONENT);
2818 HtmlEntryImpl htmlCopy = htmlEntry.writableCopy;
2819 htmlCopy.setState(HtmlEntry.ANGULAR_ERRORS, CacheState.IN_PROCESS);
2820 _cache.put(source, htmlCopy);
2821 return new AnalysisContextImpl_TaskData(new ResolveAngularComponentTemplateT ask(this, source, htmlCopy.modificationTime, htmlCopy.getValue(HtmlEntry.RESOLVE D_UNIT), component, application), false);
2822 }
2823
2824 /**
2825 * Create a [ResolveAngularEntryHtmlTask] for the given source, marking the an gular entry as
2826 * being in-process.
2827 *
2828 * @param source the source whose content is to be resolved
2829 * @param htmlEntry the entry for the source
2830 * @return task data representing the created task
2831 */
2832 AnalysisContextImpl_TaskData _createResolveAngularEntryHtmlTask(Source source, HtmlEntry htmlEntry) {
2833 if (htmlEntry.getState(HtmlEntry.RESOLVED_UNIT) != CacheState.VALID) {
2834 return _createResolveHtmlTask(source, htmlEntry);
2835 }
2836 HtmlEntryImpl htmlCopy = htmlEntry.writableCopy;
2837 htmlCopy.setState(HtmlEntry.ANGULAR_ENTRY, CacheState.IN_PROCESS);
2838 _cache.put(source, htmlCopy);
2839 return new AnalysisContextImpl_TaskData(new ResolveAngularEntryHtmlTask(this , source, htmlCopy.modificationTime, htmlCopy.getValue(HtmlEntry.RESOLVED_UNIT)) , false);
2840 }
2841
2842 /**
2843 * Create a [ResolveDartLibraryTask] for the given source, marking ? as being in-process.
2844 *
2845 * @param source the source whose content is to be resolved
2846 * @param dartEntry the entry for the source
2847 * @return task data representing the created task
2848 */
2849 AnalysisContextImpl_TaskData _createResolveDartLibraryTask(Source source, Dart Entry dartEntry) {
2850 try {
2851 AnalysisContextImpl_CycleBuilder builder = new AnalysisContextImpl_CycleBu ilder(this);
2852 builder.computeCycleContaining(source);
2853 AnalysisContextImpl_TaskData taskData = builder.taskData;
2854 if (taskData != null) {
2855 return taskData;
2856 }
2857 return new AnalysisContextImpl_TaskData(new ResolveDartLibraryCycleTask(th is, source, source, builder.librariesInCycle), false);
2858 } on AnalysisException catch (exception, stackTrace) {
2859 DartEntryImpl dartCopy = dartEntry.writableCopy;
2860 dartCopy.recordResolutionError(new CaughtException(exception, stackTrace)) ;
2861 _cache.put(source, dartCopy);
2862 AnalysisEngine.instance.logger.logError2("Internal error trying to create a ResolveDartLibraryTask", new CaughtException(exception, stackTrace));
2863 }
2864 return new AnalysisContextImpl_TaskData(null, false);
2865 }
2866
2867 /**
2868 * Create a [ResolveHtmlTask] for the given source, marking the resolved unit as being
2869 * in-process.
2870 *
2871 * @param source the source whose content is to be resolved
2872 * @param htmlEntry the entry for the source
2873 * @return task data representing the created task
2874 */
2875 AnalysisContextImpl_TaskData _createResolveHtmlTask(Source source, HtmlEntry h tmlEntry) {
2876 if (htmlEntry.getState(HtmlEntry.PARSED_UNIT) != CacheState.VALID) {
2877 return _createParseHtmlTask(source, htmlEntry);
2878 }
2879 HtmlEntryImpl htmlCopy = htmlEntry.writableCopy;
2880 htmlCopy.setState(HtmlEntry.RESOLVED_UNIT, CacheState.IN_PROCESS);
2881 _cache.put(source, htmlCopy);
2882 return new AnalysisContextImpl_TaskData(new ResolveHtmlTask(this, source, ht mlCopy.modificationTime, htmlCopy.getValue(HtmlEntry.PARSED_UNIT)), false);
2883 }
2884
2885 /**
2886 * Create a [ScanDartTask] for the given source, marking the scan errors as be ing
2887 * in-process.
2888 *
2889 * @param source the source whose content is to be scanned
2890 * @param dartEntry the entry for the source
2891 * @return task data representing the created task
2892 */
2893 AnalysisContextImpl_TaskData _createScanDartTask(Source source, DartEntry dart Entry) {
2894 if (dartEntry.getState(SourceEntry.CONTENT) != CacheState.VALID) {
2895 return _createGetContentTask(source, dartEntry);
2896 }
2897 String content = dartEntry.getValue(SourceEntry.CONTENT);
2898 DartEntryImpl dartCopy = dartEntry.writableCopy;
2899 dartCopy.setState(SourceEntry.CONTENT, CacheState.FLUSHED);
2900 dartCopy.setState(DartEntry.SCAN_ERRORS, CacheState.IN_PROCESS);
2901 _cache.put(source, dartCopy);
2902 return new AnalysisContextImpl_TaskData(new ScanDartTask(this, source, dartC opy.modificationTime, content), false);
2903 }
2904
2905 /**
2906 * Create a source information object suitable for the given source. Return th e source information
2907 * object that was created, or `null` if the source should not be tracked by t his context.
2908 *
2909 * @param source the source for which an information object is being created
2910 * @param explicitlyAdded `true` if the source was explicitly added to the con text
2911 * @return the source information object that was created
2912 */
2913 SourceEntry _createSourceEntry(Source source, bool explicitlyAdded) {
2914 String name = source.shortName;
2915 if (AnalysisEngine.isHtmlFileName(name)) {
2916 HtmlEntryImpl htmlEntry = new HtmlEntryImpl();
2917 htmlEntry.modificationTime = getModificationStamp(source);
2918 htmlEntry.explicitlyAdded = explicitlyAdded;
2919 _cache.put(source, htmlEntry);
2920 return htmlEntry;
2921 } else {
2922 DartEntryImpl dartEntry = new DartEntryImpl();
2923 dartEntry.modificationTime = getModificationStamp(source);
2924 dartEntry.explicitlyAdded = explicitlyAdded;
2925 _cache.put(source, dartEntry);
2926 return dartEntry;
2927 }
2928 }
2929
2930 /**
2931 * Return a string with debugging information about the given source (the full name and
2932 * modification stamp of the source).
2933 *
2934 * @param source the source for which a debugging string is to be produced
2935 * @return debugging information about the given source
2936 */
2937 String _debuggingString(Source source) => "'${source.fullName}' [${getModifica tionStamp(source)}]";
2938
2939 /**
2940 * Return an array containing all of the change notices that are waiting to be returned. If there
2941 * are no notices, then return either `null` or an empty array, depending on t he value of
2942 * the argument.
2943 *
2944 * @param nullIfEmpty `true` if `null` should be returned when there are no no tices
2945 * @return the change notices that are waiting to be returned
2946 */
2947 List<ChangeNotice> _getChangeNotices(bool nullIfEmpty) {
2948 if (_pendingNotices.isEmpty) {
2949 if (nullIfEmpty) {
2950 return null;
2951 }
2952 return ChangeNoticeImpl.EMPTY_ARRAY;
2953 }
2954 List<ChangeNotice> notices = new List.from(_pendingNotices.values);
2955 _pendingNotices.clear();
2956 return notices;
2957 }
2958
2959 /**
2960 * Given a source for a Dart file and the library that contains it, return the data represented by
2961 * the given descriptor that is associated with that source. This method assum es that the data can
2962 * be produced by generating hints for the library if it is not already cached .
2963 *
2964 * <b>Note:</b> This method cannot be used in an async environment.
2965 *
2966 * @param unitSource the source representing the Dart file
2967 * @param librarySource the source representing the library containing the Dar t file
2968 * @param dartEntry the entry representing the Dart file
2969 * @param descriptor the descriptor representing the data to be returned
2970 * @return the requested data about the given source
2971 * @throws AnalysisException if data could not be returned because the source could not be
2972 * resolved
2973 */
2974 Object _getDartHintData(Source unitSource, Source librarySource, DartEntry dar tEntry, DataDescriptor descriptor) {
2975 dartEntry = _cacheDartHintData(unitSource, librarySource, dartEntry, descrip tor);
2976 if (identical(descriptor, DartEntry.ELEMENT)) {
2977 return dartEntry.getValue(descriptor);
2978 }
2979 return dartEntry.getValueInLibrary(descriptor, librarySource);
2980 }
2981
2982 /**
2983 * Given a source for a Dart file, return the data represented by the given de scriptor that is
2984 * associated with that source. This method assumes that the data can be produ ced by parsing the
2985 * source if it is not already cached.
2986 *
2987 * <b>Note:</b> This method cannot be used in an async environment.
2988 *
2989 * @param source the source representing the Dart file
2990 * @param dartEntry the cache entry associated with the Dart file
2991 * @param descriptor the descriptor representing the data to be returned
2992 * @return the requested data about the given source
2993 * @throws AnalysisException if data could not be returned because the source could not be parsed
2994 */
2995 Object _getDartParseData(Source source, DartEntry dartEntry, DataDescriptor de scriptor) {
2996 dartEntry = _cacheDartParseData(source, dartEntry, descriptor);
2997 if (identical(descriptor, DartEntry.PARSED_UNIT)) {
2998 _accessedAst(source);
2999 return dartEntry.anyParsedCompilationUnit;
3000 }
3001 return dartEntry.getValue(descriptor);
3002 }
3003
3004 /**
3005 * Given a source for a Dart file, return the data represented by the given de scriptor that is
3006 * associated with that source, or the given default value if the source is no t a Dart file. This
3007 * method assumes that the data can be produced by parsing the source if it is not already cached.
3008 *
3009 * <b>Note:</b> This method cannot be used in an async environment.
3010 *
3011 * @param source the source representing the Dart file
3012 * @param descriptor the descriptor representing the data to be returned
3013 * @param defaultValue the value to be returned if the source is not a Dart fi le
3014 * @return the requested data about the given source
3015 * @throws AnalysisException if data could not be returned because the source could not be parsed
3016 */
3017 Object _getDartParseData2(Source source, DataDescriptor descriptor, Object def aultValue) {
3018 DartEntry dartEntry = _getReadableDartEntry(source);
3019 if (dartEntry == null) {
3020 return defaultValue;
3021 }
3022 try {
3023 return _getDartParseData(source, dartEntry, descriptor);
3024 } on ObsoleteSourceAnalysisException catch (exception) {
3025 AnalysisEngine.instance.logger.logInformation2("Could not compute ${descri ptor.toString()}", exception);
3026 return defaultValue;
3027 }
3028 }
3029
3030 /**
3031 * Given a source for a Dart file and the library that contains it, return the data represented by
3032 * the given descriptor that is associated with that source. This method assum es that the data can
3033 * be produced by resolving the source in the context of the library if it is not already cached.
3034 *
3035 * <b>Note:</b> This method cannot be used in an async environment.
3036 *
3037 * @param unitSource the source representing the Dart file
3038 * @param librarySource the source representing the library containing the Dar t file
3039 * @param dartEntry the entry representing the Dart file
3040 * @param descriptor the descriptor representing the data to be returned
3041 * @return the requested data about the given source
3042 * @throws AnalysisException if data could not be returned because the source could not be
3043 * resolved
3044 */
3045 Object _getDartResolutionData(Source unitSource, Source librarySource, DartEnt ry dartEntry, DataDescriptor descriptor) {
3046 dartEntry = _cacheDartResolutionData(unitSource, librarySource, dartEntry, d escriptor);
3047 if (identical(descriptor, DartEntry.ELEMENT)) {
3048 return dartEntry.getValue(descriptor);
3049 } else if (identical(descriptor, DartEntry.RESOLVED_UNIT)) {
3050 _accessedAst(unitSource);
3051 }
3052 return dartEntry.getValueInLibrary(descriptor, librarySource);
3053 }
3054
3055 /**
3056 * Given a source for a Dart file and the library that contains it, return the data represented by
3057 * the given descriptor that is associated with that source, or the given defa ult value if the
3058 * source is not a Dart file. This method assumes that the data can be produce d by resolving the
3059 * source in the context of the library if it is not already cached.
3060 *
3061 * <b>Note:</b> This method cannot be used in an async environment.
3062 *
3063 * @param unitSource the source representing the Dart file
3064 * @param librarySource the source representing the library containing the Dar t file
3065 * @param descriptor the descriptor representing the data to be returned
3066 * @param defaultValue the value to be returned if the source is not a Dart fi le
3067 * @return the requested data about the given source
3068 * @throws AnalysisException if data could not be returned because the source could not be
3069 * resolved
3070 */
3071 Object _getDartResolutionData2(Source unitSource, Source librarySource, DataDe scriptor descriptor, Object defaultValue) {
3072 DartEntry dartEntry = _getReadableDartEntry(unitSource);
3073 if (dartEntry == null) {
3074 return defaultValue;
3075 }
3076 try {
3077 return _getDartResolutionData(unitSource, librarySource, dartEntry, descri ptor);
3078 } on ObsoleteSourceAnalysisException catch (exception) {
3079 AnalysisEngine.instance.logger.logInformation2("Could not compute ${descri ptor.toString()}", exception);
3080 return defaultValue;
3081 }
3082 }
3083
3084 /**
3085 * Given a source for a Dart file, return the data represented by the given de scriptor that is
3086 * associated with that source. This method assumes that the data can be produ ced by scanning the
3087 * source if it is not already cached.
3088 *
3089 * <b>Note:</b> This method cannot be used in an async environment.
3090 *
3091 * @param source the source representing the Dart file
3092 * @param dartEntry the cache entry associated with the Dart file
3093 * @param descriptor the descriptor representing the data to be returned
3094 * @return the requested data about the given source
3095 * @throws AnalysisException if data could not be returned because the source could not be scanned
3096 */
3097 Object _getDartScanData(Source source, DartEntry dartEntry, DataDescriptor des criptor) {
3098 dartEntry = _cacheDartScanData(source, dartEntry, descriptor);
3099 return dartEntry.getValue(descriptor);
3100 }
3101
3102 /**
3103 * Given a source for a Dart file, return the data represented by the given de scriptor that is
3104 * associated with that source, or the given default value if the source is no t a Dart file. This
3105 * method assumes that the data can be produced by scanning the source if it i s not already
3106 * cached.
3107 *
3108 * <b>Note:</b> This method cannot be used in an async environment.
3109 *
3110 * @param source the source representing the Dart file
3111 * @param descriptor the descriptor representing the data to be returned
3112 * @param defaultValue the value to be returned if the source is not a Dart fi le
3113 * @return the requested data about the given source
3114 * @throws AnalysisException if data could not be returned because the source could not be scanned
3115 */
3116 Object _getDartScanData2(Source source, DataDescriptor descriptor, Object defa ultValue) {
3117 DartEntry dartEntry = _getReadableDartEntry(source);
3118 if (dartEntry == null) {
3119 return defaultValue;
3120 }
3121 try {
3122 return _getDartScanData(source, dartEntry, descriptor);
3123 } on ObsoleteSourceAnalysisException catch (exception) {
3124 AnalysisEngine.instance.logger.logInformation2("Could not compute ${descri ptor.toString()}", exception);
3125 return defaultValue;
3126 }
3127 }
3128
3129 /**
3130 * Given a source for a Dart file and the library that contains it, return the data represented by
3131 * the given descriptor that is associated with that source. This method assum es that the data can
3132 * be produced by verifying the source within the given library if it is not a lready cached.
3133 *
3134 * <b>Note:</b> This method cannot be used in an async environment.
3135 *
3136 * @param unitSource the source representing the Dart file
3137 * @param librarySource the source representing the library containing the Dar t file
3138 * @param dartEntry the entry representing the Dart file
3139 * @param descriptor the descriptor representing the data to be returned
3140 * @return the requested data about the given source
3141 * @throws AnalysisException if data could not be returned because the source could not be
3142 * resolved
3143 */
3144 Object _getDartVerificationData(Source unitSource, Source librarySource, DartE ntry dartEntry, DataDescriptor descriptor) {
3145 dartEntry = _cacheDartVerificationData(unitSource, librarySource, dartEntry, descriptor);
3146 return dartEntry.getValueInLibrary(descriptor, librarySource);
3147 }
3148
3149 /**
3150 * Given a source for an HTML file, return the data represented by the given d escriptor that is
3151 * associated with that source, or the given default value if the source is no t an HTML file. This
3152 * method assumes that the data can be produced by parsing the source if it is not already cached.
3153 *
3154 * <b>Note:</b> This method cannot be used in an async environment.
3155 *
3156 * @param source the source representing the Dart file
3157 * @param descriptor the descriptor representing the data to be returned
3158 * @param defaultValue the value to be returned if the source is not an HTML f ile
3159 * @return the requested data about the given source
3160 * @throws AnalysisException if data could not be returned because the source could not be parsed
3161 */
3162 Object _getHtmlParseData(Source source, DataDescriptor descriptor, Object defa ultValue) {
3163 HtmlEntry htmlEntry = _getReadableHtmlEntry(source);
3164 if (htmlEntry == null) {
3165 return defaultValue;
3166 }
3167 htmlEntry = _cacheHtmlParseData(source, htmlEntry, descriptor);
3168 if (identical(descriptor, HtmlEntry.PARSED_UNIT)) {
3169 _accessedAst(source);
3170 return htmlEntry.anyParsedUnit;
3171 }
3172 return htmlEntry.getValue(descriptor);
3173 }
3174
3175 /**
3176 * Given a source for an HTML file, return the data represented by the given d escriptor that is
3177 * associated with that source, or the given default value if the source is no t an HTML file. This
3178 * method assumes that the data can be produced by resolving the source if it is not already
3179 * cached.
3180 *
3181 * <b>Note:</b> This method cannot be used in an async environment.
3182 *
3183 * @param source the source representing the HTML file
3184 * @param descriptor the descriptor representing the data to be returned
3185 * @param defaultValue the value to be returned if the source is not an HTML f ile
3186 * @return the requested data about the given source
3187 * @throws AnalysisException if data could not be returned because the source could not be
3188 * resolved
3189 */
3190 Object _getHtmlResolutionData(Source source, DataDescriptor descriptor, Object defaultValue) {
3191 HtmlEntry htmlEntry = _getReadableHtmlEntry(source);
3192 if (htmlEntry == null) {
3193 return defaultValue;
3194 }
3195 try {
3196 return _getHtmlResolutionData2(source, htmlEntry, descriptor);
3197 } on ObsoleteSourceAnalysisException catch (exception) {
3198 AnalysisEngine.instance.logger.logInformation2("Could not compute ${descri ptor.toString()}", exception);
3199 return defaultValue;
3200 }
3201 }
3202
3203 /**
3204 * Given a source for an HTML file, return the data represented by the given d escriptor that is
3205 * associated with that source. This method assumes that the data can be produ ced by resolving the
3206 * source if it is not already cached.
3207 *
3208 * <b>Note:</b> This method cannot be used in an async environment.
3209 *
3210 * @param source the source representing the HTML file
3211 * @param htmlEntry the entry representing the HTML file
3212 * @param descriptor the descriptor representing the data to be returned
3213 * @return the requested data about the given source
3214 * @throws AnalysisException if data could not be returned because the source could not be
3215 * resolved
3216 */
3217 Object _getHtmlResolutionData2(Source source, HtmlEntry htmlEntry, DataDescrip tor descriptor) {
3218 htmlEntry = _cacheHtmlResolutionData(source, htmlEntry, descriptor);
3219 if (identical(descriptor, HtmlEntry.RESOLVED_UNIT)) {
3220 _accessedAst(source);
3221 }
3222 return htmlEntry.getValue(descriptor);
3223 }
3224
3225 /**
3226 * Look through the cache for a task that needs to be performed. Return the ta sk that was found,
3227 * or `null` if there is no more work to be done.
3228 *
3229 * @return the next task that needs to be performed
3230 */
3231 AnalysisTask get nextAnalysisTask {
3232 bool hintsEnabled = _options.hint;
3233 bool hasBlockedTask = false;
3234 //
3235 // Look for incremental analysis
3236 //
3237 if (_incrementalAnalysisCache != null && _incrementalAnalysisCache.hasWork) {
3238 AnalysisTask task = new IncrementalAnalysisTask(this, _incrementalAnalysis Cache);
3239 _incrementalAnalysisCache = null;
3240 return task;
3241 }
3242 //
3243 // Look for a priority source that needs to be analyzed.
3244 //
3245 int priorityCount = _priorityOrder.length;
3246 for (int i = 0; i < priorityCount; i++) {
3247 Source source = _priorityOrder[i];
3248 AnalysisContextImpl_TaskData taskData = _getNextAnalysisTaskForSource(sour ce, _cache.get(source), true, hintsEnabled);
3249 AnalysisTask task = taskData.task;
3250 if (task != null) {
3251 return task;
3252 } else if (taskData.isBlocked) {
3253 hasBlockedTask = true;
3254 }
3255 }
3256 if (_neededForResolution != null) {
3257 List<Source> sourcesToRemove = new List<Source>();
3258 for (Source source in _neededForResolution) {
3259 SourceEntry sourceEntry = _cache.get(source);
3260 if (sourceEntry is DartEntry) {
3261 DartEntry dartEntry = sourceEntry;
3262 if (!dartEntry.hasResolvableCompilationUnit) {
3263 if (dartEntry.getState(DartEntry.PARSED_UNIT) == CacheState.ERROR) {
3264 sourcesToRemove.add(source);
3265 } else {
3266 AnalysisContextImpl_TaskData taskData = _createParseDartTask(sourc e, dartEntry);
3267 AnalysisTask task = taskData.task;
3268 if (task != null) {
3269 return task;
3270 } else if (taskData.isBlocked) {
3271 hasBlockedTask = true;
3272 }
3273 }
3274 }
3275 }
3276 }
3277 int count = sourcesToRemove.length;
3278 for (int i = 0; i < count; i++) {
3279 _neededForResolution.remove(sourcesToRemove[i]);
3280 }
3281 }
3282 //
3283 // Look for a non-priority source that needs to be analyzed.
3284 //
3285 List<Source> sourcesToRemove = new List<Source>();
3286 WorkManager_WorkIterator sources = _workManager.iterator();
3287 try {
3288 while (sources.hasNext) {
3289 Source source = sources.next();
3290 AnalysisContextImpl_TaskData taskData = _getNextAnalysisTaskForSource(so urce, _cache.get(source), false, hintsEnabled);
3291 AnalysisTask task = taskData.task;
3292 if (task != null) {
3293 return task;
3294 } else if (taskData.isBlocked) {
3295 hasBlockedTask = true;
3296 } else {
3297 sourcesToRemove.add(source);
3298 }
3299 }
3300 } finally {
3301 int count = sourcesToRemove.length;
3302 for (int i = 0; i < count; i++) {
3303 _workManager.remove(sourcesToRemove[i]);
3304 }
3305 }
3306 // //
3307 // // Look for a non-priority source that needs to be analyzed and was missed by the loop above.
3308 // //
3309 // for (Map.Entry<Source, SourceEntry> entry : cache.entrySet()) {
3310 // source = entry.getKey();
3311 // TaskData taskData = getNextAnalysisTaskForSource(source, entry.get Value(), false, hintsEnabled);
3312 // AnalysisTask task = taskData.getTask();
3313 // if (task != null) {
3314 // System.out.println("Failed to analyze " + source.getFullName());
3315 // return task;
3316 // }
3317 // }
3318 if (hasBlockedTask) {
3319 // All of the analysis work is blocked waiting for an asynchronous task to complete.
3320 return WaitForAsyncTask.instance;
3321 }
3322 return null;
3323 }
3324
3325 /**
3326 * Look at the given source to see whether a task needs to be performed relate d to it. Return the
3327 * task that should be performed, or `null` if there is no more work to be don e for the
3328 * source.
3329 *
3330 * <b>Note:</b> This method must only be invoked while we are synchronized on [cacheLock].
3331 *
3332 * @param source the source to be checked
3333 * @param sourceEntry the cache entry associated with the source
3334 * @param isPriority `true` if the source is a priority source
3335 * @param hintsEnabled `true` if hints are currently enabled
3336 * @return the next task that needs to be performed for the given source
3337 */
3338 AnalysisContextImpl_TaskData _getNextAnalysisTaskForSource(Source source, Sour ceEntry sourceEntry, bool isPriority, bool hintsEnabled) {
3339 // Refuse to generate tasks for html based files that are above 1500 KB
3340 if (_isTooBigHtmlSourceEntry(source, sourceEntry)) {
3341 // TODO (jwren) we still need to report an error of some kind back to the client.
3342 return new AnalysisContextImpl_TaskData(null, false);
3343 }
3344 if (sourceEntry == null) {
3345 return new AnalysisContextImpl_TaskData(null, false);
3346 }
3347 CacheState contentState = sourceEntry.getState(SourceEntry.CONTENT);
3348 if (contentState == CacheState.INVALID) {
3349 return _createGetContentTask(source, sourceEntry);
3350 } else if (contentState == CacheState.IN_PROCESS) {
3351 // We are already in the process of getting the content. There's nothing e lse we can do with
3352 // this source until that's complete.
3353 return new AnalysisContextImpl_TaskData(null, true);
3354 } else if (contentState == CacheState.ERROR) {
3355 // We have done all of the analysis we can for this source because we cann ot get its content.
3356 return new AnalysisContextImpl_TaskData(null, false);
3357 }
3358 if (sourceEntry is DartEntry) {
3359 DartEntry dartEntry = sourceEntry;
3360 CacheState scanErrorsState = dartEntry.getState(DartEntry.SCAN_ERRORS);
3361 if (scanErrorsState == CacheState.INVALID || (isPriority && scanErrorsStat e == CacheState.FLUSHED)) {
3362 return _createScanDartTask(source, dartEntry);
3363 }
3364 CacheState parseErrorsState = dartEntry.getState(DartEntry.PARSE_ERRORS);
3365 if (parseErrorsState == CacheState.INVALID || (isPriority && parseErrorsSt ate == CacheState.FLUSHED)) {
3366 return _createParseDartTask(source, dartEntry);
3367 }
3368 if (isPriority && parseErrorsState != CacheState.ERROR) {
3369 if (!dartEntry.hasResolvableCompilationUnit) {
3370 return _createParseDartTask(source, dartEntry);
3371 }
3372 }
3373 SourceKind kind = dartEntry.getValue(DartEntry.SOURCE_KIND);
3374 if (kind == SourceKind.UNKNOWN) {
3375 return _createParseDartTask(source, dartEntry);
3376 } else if (kind == SourceKind.LIBRARY) {
3377 CacheState elementState = dartEntry.getState(DartEntry.ELEMENT);
3378 if (elementState == CacheState.INVALID) {
3379 return _createResolveDartLibraryTask(source, dartEntry);
3380 }
3381 }
3382 List<Source> librariesContaining = dartEntry.getValue(DartEntry.CONTAINING _LIBRARIES);
3383 for (Source librarySource in librariesContaining) {
3384 SourceEntry librarySourceEntry = _cache.get(librarySource);
3385 if (librarySourceEntry is DartEntry) {
3386 DartEntry libraryEntry = librarySourceEntry;
3387 CacheState elementState = libraryEntry.getState(DartEntry.ELEMENT);
3388 if (elementState == CacheState.INVALID || (isPriority && elementState == CacheState.FLUSHED)) {
3389 //return createResolveDartLibraryTask(librarySource, (DartEntry) lib raryEntry);
3390 DartEntryImpl libraryCopy = libraryEntry.writableCopy;
3391 libraryCopy.setState(DartEntry.ELEMENT, CacheState.IN_PROCESS);
3392 _cache.put(librarySource, libraryCopy);
3393 return new AnalysisContextImpl_TaskData(new ResolveDartLibraryTask(t his, source, librarySource), false);
3394 }
3395 CacheState resolvedUnitState = dartEntry.getStateInLibrary(DartEntry.R ESOLVED_UNIT, librarySource);
3396 if (resolvedUnitState == CacheState.INVALID || (isPriority && resolved UnitState == CacheState.FLUSHED)) {
3397 //
3398 // The commented out lines below are an optimization that doesn't qu ite work yet. The
3399 // problem is that if the source was not resolved because it wasn't part of any library,
3400 // then there won't be any elements in the element model that we can use to resolve it.
3401 //
3402 //LibraryElement libraryElement = libraryEntry.getValue(DartEntry.EL EMENT);
3403 //if (libraryElement != null) {
3404 // return new ResolveDartUnitTask(this, source, libraryElement);
3405 //}
3406 // Possibly replace with: return createResolveDartLibraryTask(librar ySource, (DartEntry) libraryEntry);
3407 DartEntryImpl dartCopy = dartEntry.writableCopy;
3408 dartCopy.setStateInLibrary(DartEntry.RESOLVED_UNIT, librarySource, C acheState.IN_PROCESS);
3409 _cache.put(source, dartCopy);
3410 return new AnalysisContextImpl_TaskData(new ResolveDartLibraryTask(t his, source, librarySource), false);
3411 }
3412 if (_generateSdkErrors || !source.isInSystemLibrary) {
3413 CacheState verificationErrorsState = dartEntry.getStateInLibrary(Dar tEntry.VERIFICATION_ERRORS, librarySource);
3414 if (verificationErrorsState == CacheState.INVALID || (isPriority && verificationErrorsState == CacheState.FLUSHED)) {
3415 return _createGenerateDartErrorsTask(source, dartEntry, librarySou rce, libraryEntry);
3416 }
3417 if (hintsEnabled) {
3418 CacheState hintsState = dartEntry.getStateInLibrary(DartEntry.HINT S, librarySource);
3419 if (hintsState == CacheState.INVALID || (isPriority && hintsState == CacheState.FLUSHED)) {
3420 return _createGenerateDartHintsTask(source, dartEntry, librarySo urce, libraryEntry);
3421 }
3422 }
3423 }
3424 }
3425 }
3426 } else if (sourceEntry is HtmlEntry) {
3427 HtmlEntry htmlEntry = sourceEntry;
3428 CacheState parseErrorsState = htmlEntry.getState(HtmlEntry.PARSE_ERRORS);
3429 if (parseErrorsState == CacheState.INVALID || (isPriority && parseErrorsSt ate == CacheState.FLUSHED)) {
3430 return _createParseHtmlTask(source, htmlEntry);
3431 }
3432 if (isPriority && parseErrorsState != CacheState.ERROR) {
3433 ht.HtmlUnit parsedUnit = htmlEntry.anyParsedUnit;
3434 if (parsedUnit == null) {
3435 return _createParseHtmlTask(source, htmlEntry);
3436 }
3437 }
3438 CacheState resolvedUnitState = htmlEntry.getState(HtmlEntry.RESOLVED_UNIT) ;
3439 if (resolvedUnitState == CacheState.INVALID || (isPriority && resolvedUnit State == CacheState.FLUSHED)) {
3440 return _createResolveHtmlTask(source, htmlEntry);
3441 }
3442 //
3443 // Angular support
3444 //
3445 if (_options.analyzeAngular) {
3446 // Try to resolve the HTML as an Angular entry point.
3447 CacheState angularEntryState = htmlEntry.getState(HtmlEntry.ANGULAR_ENTR Y);
3448 if (angularEntryState == CacheState.INVALID || (isPriority && angularEnt ryState == CacheState.FLUSHED)) {
3449 return _createResolveAngularEntryHtmlTask(source, htmlEntry);
3450 }
3451 // Try to resolve the HTML as an Angular application part.
3452 CacheState angularErrorsState = htmlEntry.getState(HtmlEntry.ANGULAR_ERR ORS);
3453 if (angularErrorsState == CacheState.INVALID || (isPriority && angularEr rorsState == CacheState.FLUSHED)) {
3454 return _createResolveAngularComponentTemplateTask(source, htmlEntry);
3455 }
3456 }
3457 //
3458 // Polymer support
3459 //
3460 if (_options.analyzePolymer) {
3461 // Build elements.
3462 CacheState polymerBuildErrorsState = htmlEntry.getState(HtmlEntry.POLYME R_BUILD_ERRORS);
3463 if (polymerBuildErrorsState == CacheState.INVALID || (isPriority && poly merBuildErrorsState == CacheState.FLUSHED)) {
3464 return _createPolymerBuildHtmlTask(source, htmlEntry);
3465 }
3466 // Resolve references.
3467 CacheState polymerResolutionErrorsState = htmlEntry.getState(HtmlEntry.P OLYMER_RESOLUTION_ERRORS);
3468 if (polymerResolutionErrorsState == CacheState.INVALID || (isPriority && polymerResolutionErrorsState == CacheState.FLUSHED)) {
3469 return _createPolymerResolveHtmlTask(source, htmlEntry);
3470 }
3471 }
3472 }
3473 return new AnalysisContextImpl_TaskData(null, false);
3474 }
3475
3476 /**
3477 * Return a change notice for the given source, creating one if one does not a lready exist.
3478 *
3479 * @param source the source for which changes are being reported
3480 * @return a change notice for the given source
3481 */
3482 ChangeNoticeImpl _getNotice(Source source) {
3483 ChangeNoticeImpl notice = _pendingNotices[source];
3484 if (notice == null) {
3485 notice = new ChangeNoticeImpl(source);
3486 _pendingNotices[source] = notice;
3487 }
3488 return notice;
3489 }
3490
3491 /**
3492 * Return the cache entry associated with the given source, or `null` if the s ource is not a
3493 * Dart file.
3494 *
3495 * @param source the source for which a cache entry is being sought
3496 * @return the source cache entry associated with the given source
3497 */
3498 DartEntry _getReadableDartEntry(Source source) {
3499 SourceEntry sourceEntry = _cache.get(source);
3500 if (sourceEntry == null) {
3501 sourceEntry = _createSourceEntry(source, false);
3502 }
3503 if (sourceEntry is DartEntry) {
3504 return sourceEntry as DartEntry;
3505 }
3506 return null;
3507 }
3508
3509 /**
3510 * Return the cache entry associated with the given source, or `null` if the s ource is not
3511 * an HTML file.
3512 *
3513 * @param source the source for which a cache entry is being sought
3514 * @return the source cache entry associated with the given source
3515 */
3516 HtmlEntry _getReadableHtmlEntry(Source source) {
3517 SourceEntry sourceEntry = _cache.get(source);
3518 if (sourceEntry == null) {
3519 sourceEntry = _createSourceEntry(source, false);
3520 }
3521 if (sourceEntry is HtmlEntry) {
3522 return sourceEntry as HtmlEntry;
3523 }
3524 return null;
3525 }
3526
3527 /**
3528 * Return the cache entry associated with the given source, creating it if nec essary.
3529 *
3530 * @param source the source for which a cache entry is being sought
3531 * @return the source cache entry associated with the given source
3532 */
3533 SourceEntry _getReadableSourceEntry(Source source) {
3534 SourceEntry sourceEntry = _cache.get(source);
3535 if (sourceEntry == null) {
3536 sourceEntry = _createSourceEntry(source, false);
3537 }
3538 return sourceEntry;
3539 }
3540
3541 /**
3542 * Return the cache entry associated with the given source, or `null` if there is no entry
3543 * associated with the source.
3544 *
3545 * @param source the source for which a cache entry is being sought
3546 * @return the source cache entry associated with the given source
3547 */
3548 SourceEntry _getReadableSourceEntryOrNull(Source source) => _cache.get(source) ;
3549
3550 /**
3551 * Return a resolved compilation unit corresponding to the given element in th e given library, or
3552 * `null` if the information is not cached.
3553 *
3554 * @param element the element representing the compilation unit
3555 * @param librarySource the source representing the library containing the uni t
3556 * @return the specified resolved compilation unit
3557 */
3558 TimestampedData<CompilationUnit> _getResolvedUnit(CompilationUnitElement eleme nt, Source librarySource) {
3559 SourceEntry sourceEntry = _cache.get(element.source);
3560 if (sourceEntry is DartEntry) {
3561 DartEntry dartEntry = sourceEntry;
3562 if (dartEntry.getStateInLibrary(DartEntry.RESOLVED_UNIT, librarySource) == CacheState.VALID) {
3563 return new TimestampedData<CompilationUnit>(dartEntry.modificationTime, dartEntry.getValueInLibrary(DartEntry.RESOLVED_UNIT, librarySource));
3564 }
3565 }
3566 return null;
3567 }
3568
3569 /**
3570 * Return an array containing all of the sources known to this context that ha ve the given kind.
3571 *
3572 * @param kind the kind of sources to be returned
3573 * @return all of the sources known to this context that have the given kind
3574 */
3575 List<Source> _getSources(SourceKind kind) {
3576 List<Source> sources = new List<Source>();
3577 MapIterator<Source, SourceEntry> iterator = _cache.iterator();
3578 while (iterator.moveNext()) {
3579 if (iterator.value.kind == kind) {
3580 sources.add(iterator.key);
3581 }
3582 }
3583 return new List.from(sources);
3584 }
3585
3586 /**
3587 * Look at the given source to see whether a task needs to be performed relate d to it. If so, add
3588 * the source to the set of sources that need to be processed. This method dup licates, and must
3589 * therefore be kept in sync with,
3590 * [getNextAnalysisTask]. This method is intended to
3591 * be used for testing purposes only.
3592 *
3593 * <b>Note:</b> This method must only be invoked while we are synchronized on [cacheLock].
3594 *
3595 * @param source the source to be checked
3596 * @param sourceEntry the cache entry associated with the source
3597 * @param isPriority `true` if the source is a priority source
3598 * @param hintsEnabled `true` if hints are currently enabled
3599 * @param sources the set to which sources should be added
3600 */
3601 void _getSourcesNeedingProcessing(Source source, SourceEntry sourceEntry, bool isPriority, bool hintsEnabled, HashSet<Source> sources) {
3602 if (sourceEntry is DartEntry) {
3603 DartEntry dartEntry = sourceEntry;
3604 CacheState scanErrorsState = dartEntry.getState(DartEntry.SCAN_ERRORS);
3605 if (scanErrorsState == CacheState.INVALID || (isPriority && scanErrorsStat e == CacheState.FLUSHED)) {
3606 sources.add(source);
3607 return;
3608 }
3609 CacheState parseErrorsState = dartEntry.getState(DartEntry.PARSE_ERRORS);
3610 if (parseErrorsState == CacheState.INVALID || (isPriority && parseErrorsSt ate == CacheState.FLUSHED)) {
3611 sources.add(source);
3612 return;
3613 }
3614 if (isPriority) {
3615 if (!dartEntry.hasResolvableCompilationUnit) {
3616 sources.add(source);
3617 return;
3618 }
3619 }
3620 for (Source librarySource in getLibrariesContaining(source)) {
3621 SourceEntry libraryEntry = _cache.get(librarySource);
3622 if (libraryEntry is DartEntry) {
3623 CacheState elementState = libraryEntry.getState(DartEntry.ELEMENT);
3624 if (elementState == CacheState.INVALID || (isPriority && elementState == CacheState.FLUSHED)) {
3625 sources.add(source);
3626 return;
3627 }
3628 CacheState resolvedUnitState = dartEntry.getStateInLibrary(DartEntry.R ESOLVED_UNIT, librarySource);
3629 if (resolvedUnitState == CacheState.INVALID || (isPriority && resolved UnitState == CacheState.FLUSHED)) {
3630 LibraryElement libraryElement = libraryEntry.getValue(DartEntry.ELEM ENT);
3631 if (libraryElement != null) {
3632 sources.add(source);
3633 return;
3634 }
3635 }
3636 if (_generateSdkErrors || !source.isInSystemLibrary) {
3637 CacheState verificationErrorsState = dartEntry.getStateInLibrary(Dar tEntry.VERIFICATION_ERRORS, librarySource);
3638 if (verificationErrorsState == CacheState.INVALID || (isPriority && verificationErrorsState == CacheState.FLUSHED)) {
3639 LibraryElement libraryElement = libraryEntry.getValue(DartEntry.EL EMENT);
3640 if (libraryElement != null) {
3641 sources.add(source);
3642 return;
3643 }
3644 }
3645 if (hintsEnabled) {
3646 CacheState hintsState = dartEntry.getStateInLibrary(DartEntry.HINT S, librarySource);
3647 if (hintsState == CacheState.INVALID || (isPriority && hintsState == CacheState.FLUSHED)) {
3648 LibraryElement libraryElement = libraryEntry.getValue(DartEntry. ELEMENT);
3649 if (libraryElement != null) {
3650 sources.add(source);
3651 return;
3652 }
3653 }
3654 }
3655 }
3656 }
3657 }
3658 } else if (sourceEntry is HtmlEntry) {
3659 HtmlEntry htmlEntry = sourceEntry;
3660 CacheState parsedUnitState = htmlEntry.getState(HtmlEntry.PARSED_UNIT);
3661 if (parsedUnitState == CacheState.INVALID || (isPriority && parsedUnitStat e == CacheState.FLUSHED)) {
3662 sources.add(source);
3663 return;
3664 }
3665 CacheState resolvedUnitState = htmlEntry.getState(HtmlEntry.RESOLVED_UNIT) ;
3666 if (resolvedUnitState == CacheState.INVALID || (isPriority && resolvedUnit State == CacheState.FLUSHED)) {
3667 sources.add(source);
3668 return;
3669 }
3670 // Angular
3671 if (_options.analyzeAngular) {
3672 CacheState angularErrorsState = htmlEntry.getState(HtmlEntry.ANGULAR_ERR ORS);
3673 if (angularErrorsState == CacheState.INVALID || (isPriority && angularEr rorsState == CacheState.FLUSHED)) {
3674 AngularApplication entryInfo = htmlEntry.getValue(HtmlEntry.ANGULAR_EN TRY);
3675 if (entryInfo != null) {
3676 sources.add(source);
3677 return;
3678 }
3679 AngularApplication applicationInfo = htmlEntry.getValue(HtmlEntry.ANGU LAR_APPLICATION);
3680 if (applicationInfo != null) {
3681 AngularComponentElement component = htmlEntry.getValue(HtmlEntry.ANG ULAR_COMPONENT);
3682 if (component != null) {
3683 sources.add(source);
3684 return;
3685 }
3686 }
3687 }
3688 }
3689 // Polymer
3690 if (_options.analyzePolymer) {
3691 // Elements building.
3692 CacheState polymerBuildErrorsState = htmlEntry.getState(HtmlEntry.POLYME R_BUILD_ERRORS);
3693 if (polymerBuildErrorsState == CacheState.INVALID || (isPriority && poly merBuildErrorsState == CacheState.FLUSHED)) {
3694 sources.add(source);
3695 }
3696 // Resolution.
3697 CacheState polymerResolutionErrorsState = htmlEntry.getState(HtmlEntry.P OLYMER_RESOLUTION_ERRORS);
3698 if (polymerResolutionErrorsState == CacheState.INVALID || (isPriority && polymerResolutionErrorsState == CacheState.FLUSHED)) {
3699 sources.add(source);
3700 }
3701 }
3702 }
3703 }
3704
3705 /**
3706 * Invalidate all of the resolution results computed by this context.
3707 *
3708 * <b>Note:</b> This method must only be invoked while we are synchronized on [cacheLock].
3709 *
3710 * @param invalidateUris `true` if the cached results of converting URIs to so urce files
3711 * should also be invalidated.
3712 */
3713 void _invalidateAllLocalResolutionInformation(bool invalidateUris) {
3714 HashMap<Source, List<Source>> oldPartMap = new HashMap<Source, List<Source>> ();
3715 MapIterator<Source, SourceEntry> iterator = _privatePartition.iterator();
3716 while (iterator.moveNext()) {
3717 Source source = iterator.key;
3718 SourceEntry sourceEntry = iterator.value;
3719 if (sourceEntry is HtmlEntry) {
3720 HtmlEntryImpl htmlCopy = sourceEntry.writableCopy;
3721 htmlCopy.invalidateAllResolutionInformation(invalidateUris);
3722 iterator.value = htmlCopy;
3723 _workManager.add(source, SourcePriority.HTML);
3724 } else if (sourceEntry is DartEntry) {
3725 DartEntry dartEntry = sourceEntry;
3726 oldPartMap[source] = dartEntry.getValue(DartEntry.INCLUDED_PARTS);
3727 DartEntryImpl dartCopy = dartEntry.writableCopy;
3728 dartCopy.invalidateAllResolutionInformation(invalidateUris);
3729 iterator.value = dartCopy;
3730 _workManager.add(source, _computePriority(dartCopy));
3731 }
3732 }
3733 _removeFromPartsUsingMap(oldPartMap);
3734 }
3735
3736 /**
3737 * In response to a change to Angular entry point [HtmlElement], invalidate an y results that
3738 * depend on it.
3739 *
3740 * <b>Note:</b> This method must only be invoked while we are synchronized on [cacheLock].
3741 *
3742 * <b>Note:</b> Any cache entries that were accessed before this method was in voked must be
3743 * re-accessed after this method returns.
3744 *
3745 * @param entryCopy the [HtmlEntryImpl] of the (maybe) Angular entry point bei ng invalidated
3746 */
3747 void _invalidateAngularResolution(HtmlEntryImpl entryCopy) {
3748 AngularApplication application = entryCopy.getValue(HtmlEntry.ANGULAR_ENTRY) ;
3749 if (application == null) {
3750 return;
3751 }
3752 _angularApplications.remove(application);
3753 // invalidate Entry
3754 entryCopy.setState(HtmlEntry.ANGULAR_ENTRY, CacheState.INVALID);
3755 // reset HTML sources
3756 List<AngularElement> oldAngularElements = application.elements;
3757 for (AngularElement angularElement in oldAngularElements) {
3758 if (angularElement is AngularHasTemplateElement) {
3759 AngularHasTemplateElement hasTemplate = angularElement;
3760 Source templateSource = hasTemplate.templateSource;
3761 if (templateSource != null) {
3762 HtmlEntry htmlEntry = _getReadableHtmlEntry(templateSource);
3763 HtmlEntryImpl htmlCopy = htmlEntry.writableCopy;
3764 htmlCopy.setValue(HtmlEntry.ANGULAR_APPLICATION, null);
3765 htmlCopy.setValue(HtmlEntry.ANGULAR_COMPONENT, null);
3766 htmlCopy.setState(HtmlEntry.ANGULAR_ERRORS, CacheState.INVALID);
3767 _cache.put(templateSource, htmlCopy);
3768 _workManager.add(templateSource, SourcePriority.HTML);
3769 }
3770 }
3771 }
3772 // reset Dart sources
3773 List<Source> oldElementSources = application.elementSources;
3774 for (Source elementSource in oldElementSources) {
3775 DartEntry dartEntry = _getReadableDartEntry(elementSource);
3776 DartEntryImpl dartCopy = dartEntry.writableCopy;
3777 dartCopy.setValue(DartEntry.ANGULAR_ERRORS, AnalysisError.NO_ERRORS);
3778 _cache.put(elementSource, dartCopy);
3779 // notify about (disappeared) Angular errors
3780 ChangeNoticeImpl notice = _getNotice(elementSource);
3781 notice.setErrors(dartCopy.allErrors, dartEntry.getValue(SourceEntry.LINE_I NFO));
3782 }
3783 }
3784
3785 /**
3786 * In response to a change to at least one of the compilation units in the giv en library,
3787 * invalidate any results that are dependent on the result of resolving that l ibrary.
3788 *
3789 * <b>Note:</b> This method must only be invoked while we are synchronized on [cacheLock].
3790 *
3791 * <b>Note:</b> Any cache entries that were accessed before this method was in voked must be
3792 * re-accessed after this method returns.
3793 *
3794 * @param librarySource the source of the library being invalidated
3795 */
3796 void _invalidateLibraryResolution(Source librarySource) {
3797 // TODO(brianwilkerson) This could be optimized. There's no need to flush al l of these entries
3798 // if the public namespace hasn't changed, which will be a fairly common cas e. The question is
3799 // whether we can afford the time to compute the namespace to look for diffe rences.
3800 DartEntry libraryEntry = _getReadableDartEntry(librarySource);
3801 if (libraryEntry != null) {
3802 List<Source> includedParts = libraryEntry.getValue(DartEntry.INCLUDED_PART S);
3803 DartEntryImpl libraryCopy = libraryEntry.writableCopy;
3804 libraryCopy.invalidateAllResolutionInformation(false);
3805 _cache.put(librarySource, libraryCopy);
3806 _workManager.add(librarySource, SourcePriority.LIBRARY);
3807 for (Source partSource in includedParts) {
3808 SourceEntry partEntry = _cache.get(partSource);
3809 if (partEntry is DartEntry) {
3810 DartEntryImpl partCopy = partEntry.writableCopy;
3811 partCopy.invalidateAllResolutionInformation(false);
3812 _cache.put(partSource, partCopy);
3813 }
3814 }
3815 }
3816 // invalidate Angular applications
3817 List<AngularApplication> angularApplicationsCopy = [];
3818 for (AngularApplication application in angularApplicationsCopy) {
3819 if (application.dependsOn(librarySource)) {
3820 Source entryPointSource = application.entryPoint;
3821 HtmlEntry entry = _getReadableHtmlEntry(entryPointSource);
3822 HtmlEntryImpl entryCopy = entry.writableCopy;
3823 _invalidateAngularResolution(entryCopy);
3824 _cache.put(entryPointSource, entryCopy);
3825 _workManager.add(entryPointSource, SourcePriority.HTML);
3826 }
3827 }
3828 }
3829
3830 /**
3831 * Return `true` if this library is, or depends on, dart:html.
3832 *
3833 * @param library the library being tested
3834 * @param visitedLibraries a collection of the libraries that have been visite d, used to prevent
3835 * infinite recursion
3836 * @return `true` if this library is, or depends on, dart:html
3837 */
3838 bool _isClient(LibraryElement library, Source htmlSource, HashSet<LibraryEleme nt> visitedLibraries) {
3839 if (visitedLibraries.contains(library)) {
3840 return false;
3841 }
3842 if (library.source == htmlSource) {
3843 return true;
3844 }
3845 visitedLibraries.add(library);
3846 for (LibraryElement imported in library.importedLibraries) {
3847 if (_isClient(imported, htmlSource, visitedLibraries)) {
3848 return true;
3849 }
3850 }
3851 for (LibraryElement exported in library.exportedLibraries) {
3852 if (_isClient(exported, htmlSource, visitedLibraries)) {
3853 return true;
3854 }
3855 }
3856 return false;
3857 }
3858
3859 bool _isTooBigHtmlSourceEntry(Source source, SourceEntry sourceEntry) => false ;
3860
3861 /**
3862 * Log the given debugging information.
3863 *
3864 * @param message the message to be added to the log
3865 */
3866 void _logInformation(String message) {
3867 AnalysisEngine.instance.logger.logInformation(message);
3868 }
3869
3870 /**
3871 * Log the given debugging information.
3872 *
3873 * @param message the message to be added to the log
3874 * @param exception the exception to be included in the log entry
3875 */
3876 void _logInformation2(String message, Exception exception) {
3877 if (exception == null) {
3878 AnalysisEngine.instance.logger.logInformation(message);
3879 } else {
3880 AnalysisEngine.instance.logger.logInformation2(message, exception);
3881 }
3882 }
3883
3884 /**
3885 * Notify all of the analysis listeners that a task is about to be performed.
3886 *
3887 * @param taskDescription a human readable description of the task that is abo ut to be performed
3888 */
3889 void _notifyAboutToPerformTask(String taskDescription) {
3890 int count = _listeners.length;
3891 for (int i = 0; i < count; i++) {
3892 _listeners[i].aboutToPerformTask(this, taskDescription);
3893 }
3894 }
3895
3896 /**
3897 * Notify all of the analysis listeners that the errors associated with the gi ven source has been
3898 * updated to the given errors.
3899 *
3900 * @param source the source containing the errors that were computed
3901 * @param errors the errors that were computed
3902 * @param lineInfo the line information associated with the source
3903 */
3904 void _notifyErrors(Source source, List<AnalysisError> errors, LineInfo lineInf o) {
3905 int count = _listeners.length;
3906 for (int i = 0; i < count; i++) {
3907 _listeners[i].computedErrors(this, source, errors, lineInfo);
3908 }
3909 }
3910
3911 /**
3912 * Notify all of the analysis listeners that the given source is no longer inc luded in the set of
3913 * sources that are being analyzed.
3914 *
3915 * @param source the source that is no longer being analyzed
3916 */
3917 void _notifyExcludedSource(Source source) {
3918 int count = _listeners.length;
3919 for (int i = 0; i < count; i++) {
3920 _listeners[i].excludedSource(this, source);
3921 }
3922 }
3923
3924 /**
3925 * Notify all of the analysis listeners that the given source is now included in the set of
3926 * sources that are being analyzed.
3927 *
3928 * @param source the source that is now being analyzed
3929 */
3930 void _notifyIncludedSource(Source source) {
3931 int count = _listeners.length;
3932 for (int i = 0; i < count; i++) {
3933 _listeners[i].includedSource(this, source);
3934 }
3935 }
3936
3937 /**
3938 * Notify all of the analysis listeners that the given Dart source was parsed.
3939 *
3940 * @param source the source that was parsed
3941 * @param unit the result of parsing the source
3942 */
3943 void _notifyParsedDart(Source source, CompilationUnit unit) {
3944 int count = _listeners.length;
3945 for (int i = 0; i < count; i++) {
3946 _listeners[i].parsedDart(this, source, unit);
3947 }
3948 }
3949
3950 /**
3951 * Notify all of the analysis listeners that the given HTML source was parsed.
3952 *
3953 * @param source the source that was parsed
3954 * @param unit the result of parsing the source
3955 */
3956 void _notifyParsedHtml(Source source, ht.HtmlUnit unit) {
3957 int count = _listeners.length;
3958 for (int i = 0; i < count; i++) {
3959 _listeners[i].parsedHtml(this, source, unit);
3960 }
3961 }
3962
3963 /**
3964 * Notify all of the analysis listeners that the given Dart source was resolve d.
3965 *
3966 * @param source the source that was resolved
3967 * @param unit the result of resolving the source
3968 */
3969 void _notifyResolvedDart(Source source, CompilationUnit unit) {
3970 int count = _listeners.length;
3971 for (int i = 0; i < count; i++) {
3972 _listeners[i].resolvedDart(this, source, unit);
3973 }
3974 }
3975
3976 /**
3977 * Notify all of the analysis listeners that the given HTML source was resolve d.
3978 *
3979 * @param source the source that was resolved
3980 * @param unit the result of resolving the source
3981 */
3982 void _notifyResolvedHtml(Source source, ht.HtmlUnit unit) {
3983 int count = _listeners.length;
3984 for (int i = 0; i < count; i++) {
3985 _listeners[i].resolvedHtml(this, source, unit);
3986 }
3987 }
3988
3989 /**
3990 * Updates [HtmlEntry]s that correspond to the previously known and new Angula r application
3991 * information.
3992 */
3993 void _recordAngularEntryPoint(HtmlEntryImpl entry, ResolveAngularEntryHtmlTask task) {
3994 AngularApplication application = task.application;
3995 if (application != null) {
3996 _angularApplications.add(application);
3997 // if this is an entry point, then we already resolved it
3998 entry.setValue(HtmlEntry.ANGULAR_ERRORS, task.entryErrors);
3999 // schedule HTML templates analysis
4000 List<AngularElement> newAngularElements = application.elements;
4001 for (AngularElement angularElement in newAngularElements) {
4002 if (angularElement is AngularHasTemplateElement) {
4003 AngularHasTemplateElement hasTemplate = angularElement;
4004 Source templateSource = hasTemplate.templateSource;
4005 if (templateSource != null) {
4006 HtmlEntry htmlEntry = _getReadableHtmlEntry(templateSource);
4007 HtmlEntryImpl htmlCopy = htmlEntry.writableCopy;
4008 htmlCopy.setValue(HtmlEntry.ANGULAR_APPLICATION, application);
4009 if (hasTemplate is AngularComponentElement) {
4010 AngularComponentElement component = hasTemplate;
4011 htmlCopy.setValue(HtmlEntry.ANGULAR_COMPONENT, component);
4012 }
4013 htmlCopy.setState(HtmlEntry.ANGULAR_ERRORS, CacheState.INVALID);
4014 _cache.put(templateSource, htmlCopy);
4015 _workManager.add(templateSource, SourcePriority.HTML);
4016 }
4017 }
4018 }
4019 // update Dart sources errors
4020 List<Source> newElementSources = application.elementSources;
4021 for (Source elementSource in newElementSources) {
4022 DartEntry dartEntry = _getReadableDartEntry(elementSource);
4023 DartEntryImpl dartCopy = dartEntry.writableCopy;
4024 dartCopy.setValue(DartEntry.ANGULAR_ERRORS, task.getErrors(elementSource ));
4025 _cache.put(elementSource, dartCopy);
4026 // notify about Dart errors
4027 ChangeNoticeImpl notice = _getNotice(elementSource);
4028 notice.setErrors(dartCopy.allErrors, computeLineInfo(elementSource));
4029 }
4030 }
4031 // remember Angular entry point
4032 entry.setValue(HtmlEntry.ANGULAR_ENTRY, application);
4033 }
4034
4035 /**
4036 * Given a cache entry and a library element, record the library element and o ther information
4037 * gleaned from the element in the cache entry.
4038 *
4039 * @param dartCopy the cache entry in which data is to be recorded
4040 * @param library the library element used to record information
4041 * @param librarySource the source for the library used to record information
4042 * @param htmlSource the source for the HTML library
4043 */
4044 void _recordElementData(DartEntryImpl dartCopy, LibraryElement library, Source librarySource, Source htmlSource) {
4045 dartCopy.setValue(DartEntry.ELEMENT, library);
4046 dartCopy.setValue(DartEntry.IS_LAUNCHABLE, library.entryPoint != null);
4047 dartCopy.setValue(DartEntry.IS_CLIENT, _isClient(library, htmlSource, new Ha shSet<LibraryElement>()));
4048 }
4049
4050 /**
4051 * Record the results produced by performing a [GenerateDartErrorsTask]. If th e results were
4052 * computed from data that is now out-of-date, then the results will not be re corded.
4053 *
4054 * @param task the task that was performed
4055 * @return an entry containing the computed results
4056 * @throws AnalysisException if the results could not be recorded
4057 */
4058 DartEntry _recordGenerateDartErrorsTask(GenerateDartErrorsTask task) {
4059 Source source = task.source;
4060 Source librarySource = task.libraryElement.source;
4061 CaughtException thrownException = task.exception;
4062 DartEntry dartEntry = null;
4063 SourceEntry sourceEntry = _cache.get(source);
4064 if (sourceEntry == null) {
4065 throw new ObsoleteSourceAnalysisException(source);
4066 } else if (sourceEntry is! DartEntry) {
4067 // This shouldn't be possible because we should never have performed the t ask if the source
4068 // didn't represent a Dart file, but check to be safe.
4069 throw new AnalysisException("Internal error: attempting to verify non-Dart file as a Dart file: ${source.fullName}");
4070 }
4071 dartEntry = sourceEntry as DartEntry;
4072 int sourceTime = getModificationStamp(source);
4073 int resultTime = task.modificationTime;
4074 if (sourceTime == resultTime) {
4075 if (dartEntry.modificationTime != sourceTime) {
4076 // The source has changed without the context being notified. Simulate n otification.
4077 _sourceChanged(source);
4078 dartEntry = _getReadableDartEntry(source);
4079 if (dartEntry == null) {
4080 throw new AnalysisException("A Dart file became a non-Dart file: ${sou rce.fullName}");
4081 }
4082 }
4083 DartEntryImpl dartCopy = dartEntry.writableCopy;
4084 if (thrownException == null) {
4085 dartCopy.setValueInLibrary(DartEntry.VERIFICATION_ERRORS, librarySource, task.errors);
4086 ChangeNoticeImpl notice = _getNotice(source);
4087 notice.setErrors(dartCopy.allErrors, dartCopy.getValue(SourceEntry.LINE_ INFO));
4088 } else {
4089 dartCopy.recordVerificationErrorInLibrary(librarySource, thrownException );
4090 }
4091 _cache.put(source, dartCopy);
4092 dartEntry = dartCopy;
4093 } else {
4094 _logInformation2("Generated errors discarded for ${_debuggingString(source )}; sourceTime = ${sourceTime}, resultTime = ${resultTime}, cacheTime = ${dartEn try.modificationTime}", thrownException);
4095 DartEntryImpl dartCopy = dartEntry.writableCopy;
4096 if (thrownException == null || resultTime >= 0) {
4097 //
4098 // The analysis was performed on out-of-date sources. Mark the cache so that the source
4099 // will be re-verified using the up-to-date sources.
4100 //
4101 // dartCopy.setState(DartEntry.VERIFICATION_ERRORS, librarySour ce, CacheState.INVALID);
4102 _removeFromParts(source, dartEntry);
4103 dartCopy.invalidateAllInformation();
4104 dartCopy.modificationTime = sourceTime;
4105 _cache.removedAst(source);
4106 _workManager.add(source, SourcePriority.UNKNOWN);
4107 } else {
4108 //
4109 // We could not determine whether the sources were up-to-date or out-of- date. Mark the
4110 // cache so that we won't attempt to re-verify the source until there's a good chance
4111 // that we'll be able to do so without error.
4112 //
4113 dartCopy.recordVerificationErrorInLibrary(librarySource, thrownException );
4114 }
4115 _cache.put(source, dartCopy);
4116 dartEntry = dartCopy;
4117 }
4118 if (thrownException != null) {
4119 throw new AnalysisException('<rethrow>', thrownException);
4120 }
4121 return dartEntry;
4122 }
4123
4124 /**
4125 * Record the results produced by performing a [GenerateDartHintsTask]. If the results were
4126 * computed from data that is now out-of-date, then the results will not be re corded.
4127 *
4128 * @param task the task that was performed
4129 * @return an entry containing the computed results
4130 * @throws AnalysisException if the results could not be recorded
4131 */
4132 DartEntry _recordGenerateDartHintsTask(GenerateDartHintsTask task) {
4133 Source librarySource = task.libraryElement.source;
4134 CaughtException thrownException = task.exception;
4135 DartEntry libraryEntry = null;
4136 HashMap<Source, TimestampedData<List<AnalysisError>>> hintMap = task.hintMap ;
4137 if (hintMap == null) {
4138 // We don't have any information about which sources to mark as invalid ot her than the library
4139 // source.
4140 SourceEntry sourceEntry = _cache.get(librarySource);
4141 if (sourceEntry == null) {
4142 throw new ObsoleteSourceAnalysisException(librarySource);
4143 } else if (sourceEntry is! DartEntry) {
4144 // This shouldn't be possible because we should never have performed the task if the source
4145 // didn't represent a Dart file, but check to be safe.
4146 throw new AnalysisException("Internal error: attempting to generate hint s for non-Dart file as a Dart file: ${librarySource.fullName}");
4147 }
4148 if (thrownException == null) {
4149 thrownException = new CaughtException(new AnalysisException("GenerateDar tHintsTask returned a null hint map without throwing an exception: ${librarySour ce.fullName}"), null);
4150 }
4151 DartEntryImpl dartCopy = (sourceEntry as DartEntry).writableCopy;
4152 dartCopy.recordHintErrorInLibrary(librarySource, thrownException);
4153 _cache.put(librarySource, dartCopy);
4154 throw new AnalysisException('<rethrow>', thrownException);
4155 }
4156 for (MapEntry<Source, TimestampedData<List<AnalysisError>>> entry in getMapE ntrySet(hintMap)) {
4157 Source unitSource = entry.getKey();
4158 TimestampedData<List<AnalysisError>> results = entry.getValue();
4159 SourceEntry sourceEntry = _cache.get(unitSource);
4160 if (sourceEntry is! DartEntry) {
4161 // This shouldn't be possible because we should never have performed the task if the source
4162 // didn't represent a Dart file, but check to be safe.
4163 throw new AnalysisException("Internal error: attempting to parse non-Dar t file as a Dart file: ${unitSource.fullName}");
4164 }
4165 DartEntry dartEntry = sourceEntry as DartEntry;
4166 if (unitSource == librarySource) {
4167 libraryEntry = dartEntry;
4168 }
4169 int sourceTime = getModificationStamp(unitSource);
4170 int resultTime = results.modificationTime;
4171 if (sourceTime == resultTime) {
4172 if (dartEntry.modificationTime != sourceTime) {
4173 // The source has changed without the context being notified. Simulate notification.
4174 _sourceChanged(unitSource);
4175 dartEntry = _getReadableDartEntry(unitSource);
4176 if (dartEntry == null) {
4177 throw new AnalysisException("A Dart file became a non-Dart file: ${u nitSource.fullName}");
4178 }
4179 }
4180 DartEntryImpl dartCopy = dartEntry.writableCopy;
4181 if (thrownException == null) {
4182 dartCopy.setValueInLibrary(DartEntry.HINTS, librarySource, results.dat a);
4183 ChangeNoticeImpl notice = _getNotice(unitSource);
4184 notice.setErrors(dartCopy.allErrors, dartCopy.getValue(SourceEntry.LIN E_INFO));
4185 } else {
4186 dartCopy.recordHintErrorInLibrary(librarySource, thrownException);
4187 }
4188 _cache.put(unitSource, dartCopy);
4189 dartEntry = dartCopy;
4190 } else {
4191 _logInformation2("Generated hints discarded for ${_debuggingString(unitS ource)}; sourceTime = ${sourceTime}, resultTime = ${resultTime}, cacheTime = ${d artEntry.modificationTime}", thrownException);
4192 if (dartEntry.getStateInLibrary(DartEntry.HINTS, librarySource) == Cache State.IN_PROCESS) {
4193 DartEntryImpl dartCopy = dartEntry.writableCopy;
4194 if (thrownException == null || resultTime >= 0) {
4195 //
4196 // The analysis was performed on out-of-date sources. Mark the cache so that the sources
4197 // will be re-analyzed using the up-to-date sources.
4198 //
4199 // dartCopy.setState(DartEntry.HINTS, librarySource, Ca cheState.INVALID);
4200 _removeFromParts(unitSource, dartEntry);
4201 dartCopy.invalidateAllInformation();
4202 dartCopy.modificationTime = sourceTime;
4203 _cache.removedAst(unitSource);
4204 _workManager.add(unitSource, SourcePriority.UNKNOWN);
4205 } else {
4206 //
4207 // We could not determine whether the sources were up-to-date or out -of-date. Mark the
4208 // cache so that we won't attempt to re-analyze the sources until th ere's a good chance
4209 // that we'll be able to do so without error.
4210 //
4211 dartCopy.recordHintErrorInLibrary(librarySource, thrownException);
4212 }
4213 _cache.put(unitSource, dartCopy);
4214 dartEntry = dartCopy;
4215 }
4216 }
4217 }
4218 if (thrownException != null) {
4219 throw new AnalysisException('<rethrow>', thrownException);
4220 }
4221 return libraryEntry;
4222 }
4223
4224 /**
4225 * Record the results produced by performing a [GetContentTask].
4226 *
4227 * @param task the task that was performed
4228 * @return an entry containing the computed results
4229 * @throws AnalysisException if the results could not be recorded
4230 */
4231 SourceEntry _recordGetContentsTask(GetContentTask task) {
4232 if (!task.isComplete) {
4233 return null;
4234 }
4235 Source source = task.source;
4236 CaughtException thrownException = task.exception;
4237 SourceEntry sourceEntry = null;
4238 sourceEntry = _cache.get(source);
4239 if (sourceEntry == null) {
4240 throw new ObsoleteSourceAnalysisException(source);
4241 }
4242 SourceEntryImpl sourceCopy = sourceEntry.writableCopy;
4243 if (thrownException == null) {
4244 sourceCopy.modificationTime = task.modificationTime;
4245 sourceCopy.setValue(SourceEntry.CONTENT, task.content);
4246 } else {
4247 sourceCopy.recordContentError(thrownException);
4248 _workManager.remove(source);
4249 }
4250 _cache.put(source, sourceCopy);
4251 sourceEntry = sourceCopy;
4252 if (thrownException != null) {
4253 throw new AnalysisException('<rethrow>', thrownException);
4254 }
4255 return sourceEntry;
4256 }
4257
4258 /**
4259 * Record the results produced by performing a [IncrementalAnalysisTask].
4260 *
4261 * @param task the task that was performed
4262 * @return an entry containing the computed results
4263 * @throws AnalysisException if the results could not be recorded
4264 */
4265 DartEntry _recordIncrementalAnalysisTaskResults(IncrementalAnalysisTask task) {
4266 CompilationUnit unit = task.compilationUnit;
4267 if (unit != null) {
4268 ChangeNoticeImpl notice = _getNotice(task.source);
4269 notice.compilationUnit = unit;
4270 _incrementalAnalysisCache = IncrementalAnalysisCache.cacheResult(task.cach e, unit);
4271 }
4272 return null;
4273 }
4274
4275 /**
4276 * Record the results produced by performing a [ParseDartTask]. If the results were computed
4277 * from data that is now out-of-date, then the results will not be recorded.
4278 *
4279 * @param task the task that was performed
4280 * @return an entry containing the computed results
4281 * @throws AnalysisException if the results could not be recorded
4282 */
4283 DartEntry _recordParseDartTaskResults(ParseDartTask task) {
4284 Source source = task.source;
4285 CaughtException thrownException = task.exception;
4286 DartEntry dartEntry = null;
4287 SourceEntry sourceEntry = _cache.get(source);
4288 if (sourceEntry == null) {
4289 throw new ObsoleteSourceAnalysisException(source);
4290 } else if (sourceEntry is! DartEntry) {
4291 // This shouldn't be possible because we should never have performed the t ask if the source
4292 // didn't represent a Dart file, but check to be safe.
4293 throw new AnalysisException("Internal error: attempting to parse non-Dart file as a Dart file: ${source.fullName}");
4294 }
4295 dartEntry = sourceEntry as DartEntry;
4296 int sourceTime = getModificationStamp(source);
4297 int resultTime = task.modificationTime;
4298 if (sourceTime == resultTime) {
4299 if (dartEntry.modificationTime != sourceTime) {
4300 // The source has changed without the context being notified. Simulate n otification.
4301 _sourceChanged(source);
4302 dartEntry = _getReadableDartEntry(source);
4303 if (dartEntry == null) {
4304 throw new AnalysisException("A Dart file became a non-Dart file: ${sou rce.fullName}");
4305 }
4306 }
4307 _removeFromParts(source, dartEntry);
4308 DartEntryImpl dartCopy = dartEntry.writableCopy;
4309 if (thrownException == null) {
4310 if (task.hasNonPartOfDirective) {
4311 dartCopy.setValue(DartEntry.SOURCE_KIND, SourceKind.LIBRARY);
4312 dartCopy.containingLibrary = source;
4313 _workManager.add(source, SourcePriority.LIBRARY);
4314 } else if (task.hasPartOfDirective) {
4315 dartCopy.setValue(DartEntry.SOURCE_KIND, SourceKind.PART);
4316 dartCopy.removeContainingLibrary(source);
4317 _workManager.add(source, SourcePriority.NORMAL_PART);
4318 } else {
4319 // The file contains no directives.
4320 List<Source> containingLibraries = dartCopy.containingLibraries;
4321 if (containingLibraries.length > 1 || (containingLibraries.length == 1 && containingLibraries[0] != source)) {
4322 dartCopy.setValue(DartEntry.SOURCE_KIND, SourceKind.PART);
4323 dartCopy.removeContainingLibrary(source);
4324 _workManager.add(source, SourcePriority.NORMAL_PART);
4325 } else {
4326 dartCopy.setValue(DartEntry.SOURCE_KIND, SourceKind.LIBRARY);
4327 dartCopy.containingLibrary = source;
4328 _workManager.add(source, SourcePriority.LIBRARY);
4329 }
4330 }
4331 List<Source> newParts = task.includedSources;
4332 for (int i = 0; i < newParts.length; i++) {
4333 Source partSource = newParts[i];
4334 DartEntry partEntry = _getReadableDartEntry(partSource);
4335 if (partEntry != null && !identical(partEntry, dartEntry)) {
4336 DartEntryImpl partCopy = partEntry.writableCopy;
4337 // TODO(brianwilkerson) Change the kind of the "part" if it was mark ed as a library
4338 // and it has no directives.
4339 partCopy.addContainingLibrary(source);
4340 _cache.put(partSource, partCopy);
4341 }
4342 }
4343 dartCopy.setValue(DartEntry.PARSED_UNIT, task.compilationUnit);
4344 dartCopy.setValue(DartEntry.PARSE_ERRORS, task.errors);
4345 dartCopy.setValue(DartEntry.EXPORTED_LIBRARIES, task.exportedSources);
4346 dartCopy.setValue(DartEntry.IMPORTED_LIBRARIES, task.importedSources);
4347 dartCopy.setValue(DartEntry.INCLUDED_PARTS, newParts);
4348 _cache.storedAst(source);
4349 ChangeNoticeImpl notice = _getNotice(source);
4350 notice.setErrors(dartCopy.allErrors, task.lineInfo);
4351 // Verify that the incrementally parsed and resolved unit in the increme ntal cache
4352 // is structurally equivalent to the fully parsed unit
4353 _incrementalAnalysisCache = IncrementalAnalysisCache.verifyStructure(_in crementalAnalysisCache, source, task.compilationUnit);
4354 } else {
4355 _removeFromParts(source, dartEntry);
4356 dartCopy.recordParseError(thrownException);
4357 _cache.removedAst(source);
4358 }
4359 _cache.put(source, dartCopy);
4360 dartEntry = dartCopy;
4361 } else {
4362 _logInformation2("Parse results discarded for ${_debuggingString(source)}; sourceTime = ${sourceTime}, resultTime = ${resultTime}, cacheTime = ${dartEntry .modificationTime}", thrownException);
4363 DartEntryImpl dartCopy = dartEntry.writableCopy;
4364 if (thrownException == null || resultTime >= 0) {
4365 //
4366 // The analysis was performed on out-of-date sources. Mark the cache so that the sources
4367 // will be re-analyzed using the up-to-date sources.
4368 //
4369 // dartCopy.recordParseNotInProcess();
4370 _removeFromParts(source, dartEntry);
4371 dartCopy.invalidateAllInformation();
4372 dartCopy.modificationTime = sourceTime;
4373 _cache.removedAst(source);
4374 _workManager.add(source, SourcePriority.UNKNOWN);
4375 } else {
4376 //
4377 // We could not determine whether the sources were up-to-date or out-of- date. Mark the
4378 // cache so that we won't attempt to re-analyze the sources until there' s a good chance
4379 // that we'll be able to do so without error.
4380 //
4381 dartCopy.recordParseError(thrownException);
4382 }
4383 _cache.put(source, dartCopy);
4384 dartEntry = dartCopy;
4385 }
4386 if (thrownException != null) {
4387 throw new AnalysisException('<rethrow>', thrownException);
4388 }
4389 return dartEntry;
4390 }
4391
4392 /**
4393 * Record the results produced by performing a [ParseHtmlTask]. If the results were computed
4394 * from data that is now out-of-date, then the results will not be recorded.
4395 *
4396 * @param task the task that was performed
4397 * @return an entry containing the computed results
4398 * @throws AnalysisException if the results could not be recorded
4399 */
4400 HtmlEntry _recordParseHtmlTaskResults(ParseHtmlTask task) {
4401 Source source = task.source;
4402 CaughtException thrownException = task.exception;
4403 HtmlEntry htmlEntry = null;
4404 SourceEntry sourceEntry = _cache.get(source);
4405 if (sourceEntry == null) {
4406 throw new ObsoleteSourceAnalysisException(source);
4407 } else if (sourceEntry is! HtmlEntry) {
4408 // This shouldn't be possible because we should never have performed the t ask if the source
4409 // didn't represent an HTML file, but check to be safe.
4410 throw new AnalysisException("Internal error: attempting to parse non-HTML file as a HTML file: ${source.fullName}");
4411 }
4412 htmlEntry = sourceEntry as HtmlEntry;
4413 int sourceTime = getModificationStamp(source);
4414 int resultTime = task.modificationTime;
4415 if (sourceTime == resultTime) {
4416 if (htmlEntry.modificationTime != sourceTime) {
4417 // The source has changed without the context being notified. Simulate n otification.
4418 _sourceChanged(source);
4419 htmlEntry = _getReadableHtmlEntry(source);
4420 if (htmlEntry == null) {
4421 throw new AnalysisException("An HTML file became a non-HTML file: ${so urce.fullName}");
4422 }
4423 }
4424 HtmlEntryImpl htmlCopy = (sourceEntry as HtmlEntry).writableCopy;
4425 if (thrownException == null) {
4426 LineInfo lineInfo = task.lineInfo;
4427 ht.HtmlUnit unit = task.htmlUnit;
4428 htmlCopy.setValue(SourceEntry.LINE_INFO, lineInfo);
4429 htmlCopy.setValue(HtmlEntry.PARSED_UNIT, unit);
4430 htmlCopy.setValue(HtmlEntry.PARSE_ERRORS, task.errors);
4431 htmlCopy.setValue(HtmlEntry.REFERENCED_LIBRARIES, task.referencedLibrari es);
4432 _cache.storedAst(source);
4433 ChangeNoticeImpl notice = _getNotice(source);
4434 notice.setErrors(htmlCopy.allErrors, lineInfo);
4435 } else {
4436 htmlCopy.recordParseError(thrownException);
4437 _cache.removedAst(source);
4438 }
4439 _cache.put(source, htmlCopy);
4440 htmlEntry = htmlCopy;
4441 } else {
4442 _logInformation2("Parse results discarded for ${_debuggingString(source)}; sourceTime = ${sourceTime}, resultTime = ${resultTime}, cacheTime = ${htmlEntry .modificationTime}", thrownException);
4443 HtmlEntryImpl htmlCopy = (sourceEntry as HtmlEntry).writableCopy;
4444 if (thrownException == null || resultTime >= 0) {
4445 //
4446 // The analysis was performed on out-of-date sources. Mark the cache so that the sources
4447 // will be re-analyzed using the up-to-date sources.
4448 //
4449 // if (htmlCopy.getState(SourceEntry.LINE_INFO) == CacheState.I N_PROCESS) {
4450 // htmlCopy.setState(SourceEntry.LINE_INFO, CacheState.INVALI D);
4451 // }
4452 // if (htmlCopy.getState(HtmlEntry.PARSED_UNIT) == CacheState.I N_PROCESS) {
4453 // htmlCopy.setState(HtmlEntry.PARSED_UNIT, CacheState.INVALI D);
4454 // }
4455 // if (htmlCopy.getState(HtmlEntry.REFERENCED_LIBRARIES) == Cac heState.IN_PROCESS) {
4456 // htmlCopy.setState(HtmlEntry.REFERENCED_LIBRARIES, CacheSta te.INVALID);
4457 // }
4458 htmlCopy.invalidateAllInformation();
4459 htmlCopy.modificationTime = sourceTime;
4460 _cache.removedAst(source);
4461 } else {
4462 //
4463 // We could not determine whether the sources were up-to-date or out-of- date. Mark the
4464 // cache so that we won't attempt to re-analyze the sources until there' s a good chance
4465 // that we'll be able to do so without error.
4466 //
4467 htmlCopy.recordParseError(thrownException);
4468 }
4469 _cache.put(source, htmlCopy);
4470 htmlEntry = htmlCopy;
4471 }
4472 if (thrownException != null) {
4473 throw new AnalysisException('<rethrow>', thrownException);
4474 }
4475 return htmlEntry;
4476 }
4477
4478 /**
4479 * Record the results produced by performing a [PolymerBuildHtmlTask]. If the results were
4480 * computed from data that is now out-of-date, then the results will not be re corded.
4481 *
4482 * @param task the task that was performed
4483 * @throws AnalysisException if the results could not be recorded
4484 */
4485 HtmlEntry _recordPolymerBuildHtmlTaskResults(PolymerBuildHtmlTask task) {
4486 Source source = task.source;
4487 CaughtException thrownException = task.exception;
4488 HtmlEntry htmlEntry = null;
4489 SourceEntry sourceEntry = _cache.get(source);
4490 if (sourceEntry == null) {
4491 throw new ObsoleteSourceAnalysisException(source);
4492 } else if (sourceEntry is! HtmlEntry) {
4493 // This shouldn't be possible because we should never have performed the t ask if the source
4494 // didn't represent an HTML file, but check to be safe.
4495 throw new AnalysisException("Internal error: attempting to resolve non-HTM L file as an HTML file: ${source.fullName}");
4496 }
4497 htmlEntry = sourceEntry as HtmlEntry;
4498 int sourceTime = getModificationStamp(source);
4499 int resultTime = task.modificationTime;
4500 if (sourceTime == resultTime) {
4501 if (htmlEntry.modificationTime != sourceTime) {
4502 // The source has changed without the context being notified. Simulate n otification.
4503 _sourceChanged(source);
4504 htmlEntry = _getReadableHtmlEntry(source);
4505 if (htmlEntry == null) {
4506 throw new AnalysisException("An HTML file became a non-HTML file: ${so urce.fullName}");
4507 }
4508 }
4509 HtmlEntryImpl htmlCopy = htmlEntry.writableCopy;
4510 if (thrownException == null) {
4511 htmlCopy.setValue(HtmlEntry.POLYMER_BUILD_ERRORS, task.errors);
4512 // notify about errors
4513 ChangeNoticeImpl notice = _getNotice(source);
4514 notice.setErrors(htmlCopy.allErrors, htmlCopy.getValue(SourceEntry.LINE_ INFO));
4515 } else {
4516 htmlCopy.recordResolutionError(thrownException);
4517 }
4518 _cache.put(source, htmlCopy);
4519 htmlEntry = htmlCopy;
4520 } else {
4521 HtmlEntryImpl htmlCopy = htmlEntry.writableCopy;
4522 if (thrownException == null || resultTime >= 0) {
4523 //
4524 // The analysis was performed on out-of-date sources. Mark the cache so that the sources
4525 // will be re-analyzed using the up-to-date sources.
4526 //
4527 htmlCopy.invalidateAllInformation();
4528 htmlCopy.modificationTime = sourceTime;
4529 _cache.removedAst(source);
4530 } else {
4531 //
4532 // We could not determine whether the sources were up-to-date or out-of- date. Mark the
4533 // cache so that we won't attempt to re-analyze the sources until there' s a good chance
4534 // that we'll be able to do so without error.
4535 //
4536 htmlCopy.recordResolutionError(thrownException);
4537 }
4538 _cache.put(source, htmlCopy);
4539 htmlEntry = htmlCopy;
4540 }
4541 if (thrownException != null) {
4542 throw new AnalysisException('<rethrow>', thrownException);
4543 }
4544 return htmlEntry;
4545 }
4546
4547 /**
4548 * Record the results produced by performing a [PolymerResolveHtmlTask]. If th e results were
4549 * computed from data that is now out-of-date, then the results will not be re corded.
4550 *
4551 * @param task the task that was performed
4552 * @throws AnalysisException if the results could not be recorded
4553 */
4554 HtmlEntry _recordPolymerResolveHtmlTaskResults(PolymerResolveHtmlTask task) {
4555 Source source = task.source;
4556 CaughtException thrownException = task.exception;
4557 HtmlEntry htmlEntry = null;
4558 SourceEntry sourceEntry = _cache.get(source);
4559 if (sourceEntry == null) {
4560 throw new ObsoleteSourceAnalysisException(source);
4561 } else if (sourceEntry is! HtmlEntry) {
4562 // This shouldn't be possible because we should never have performed the t ask if the source
4563 // didn't represent an HTML file, but check to be safe.
4564 throw new AnalysisException("Internal error: attempting to resolve non-HTM L file as an HTML file: ${source.fullName}");
4565 }
4566 htmlEntry = sourceEntry as HtmlEntry;
4567 int sourceTime = getModificationStamp(source);
4568 int resultTime = task.modificationTime;
4569 if (sourceTime == resultTime) {
4570 if (htmlEntry.modificationTime != sourceTime) {
4571 // The source has changed without the context being notified. Simulate n otification.
4572 _sourceChanged(source);
4573 htmlEntry = _getReadableHtmlEntry(source);
4574 if (htmlEntry == null) {
4575 throw new AnalysisException("An HTML file became a non-HTML file: ${so urce.fullName}");
4576 }
4577 }
4578 HtmlEntryImpl htmlCopy = htmlEntry.writableCopy;
4579 if (thrownException == null) {
4580 htmlCopy.setValue(HtmlEntry.POLYMER_RESOLUTION_ERRORS, task.errors);
4581 // notify about errors
4582 ChangeNoticeImpl notice = _getNotice(source);
4583 notice.setErrors(htmlCopy.allErrors, htmlCopy.getValue(SourceEntry.LINE_ INFO));
4584 } else {
4585 htmlCopy.recordResolutionError(thrownException);
4586 }
4587 _cache.put(source, htmlCopy);
4588 htmlEntry = htmlCopy;
4589 } else {
4590 HtmlEntryImpl htmlCopy = htmlEntry.writableCopy;
4591 if (thrownException == null || resultTime >= 0) {
4592 //
4593 // The analysis was performed on out-of-date sources. Mark the cache so that the sources
4594 // will be re-analyzed using the up-to-date sources.
4595 //
4596 htmlCopy.invalidateAllInformation();
4597 htmlCopy.modificationTime = sourceTime;
4598 _cache.removedAst(source);
4599 } else {
4600 //
4601 // We could not determine whether the sources were up-to-date or out-of- date. Mark the
4602 // cache so that we won't attempt to re-analyze the sources until there' s a good chance
4603 // that we'll be able to do so without error.
4604 //
4605 htmlCopy.recordResolutionError(thrownException);
4606 }
4607 _cache.put(source, htmlCopy);
4608 htmlEntry = htmlCopy;
4609 }
4610 if (thrownException != null) {
4611 throw new AnalysisException('<rethrow>', thrownException);
4612 }
4613 return htmlEntry;
4614 }
4615
4616 /**
4617 * Record the results produced by performing a [ResolveAngularComponentTemplat eTask]. If the
4618 * results were computed from data that is now out-of-date, then the results w ill not be recorded.
4619 *
4620 * @param task the task that was performed
4621 * @throws AnalysisException if the results could not be recorded
4622 */
4623 HtmlEntry _recordResolveAngularComponentTemplateTaskResults(ResolveAngularComp onentTemplateTask task) {
4624 Source source = task.source;
4625 CaughtException thrownException = task.exception;
4626 HtmlEntry htmlEntry = null;
4627 SourceEntry sourceEntry = _cache.get(source);
4628 if (sourceEntry == null) {
4629 throw new ObsoleteSourceAnalysisException(source);
4630 } else if (sourceEntry is! HtmlEntry) {
4631 // This shouldn't be possible because we should never have performed the t ask if the source
4632 // didn't represent an HTML file, but check to be safe.
4633 throw new AnalysisException("Internal error: attempting to resolve non-HTM L file as an HTML file: ${source.fullName}");
4634 }
4635 htmlEntry = sourceEntry as HtmlEntry;
4636 int sourceTime = getModificationStamp(source);
4637 int resultTime = task.modificationTime;
4638 if (sourceTime == resultTime) {
4639 if (htmlEntry.modificationTime != sourceTime) {
4640 // The source has changed without the context being notified. Simulate n otification.
4641 _sourceChanged(source);
4642 htmlEntry = _getReadableHtmlEntry(source);
4643 if (htmlEntry == null) {
4644 throw new AnalysisException("An HTML file became a non-HTML file: ${so urce.fullName}");
4645 }
4646 }
4647 HtmlEntryImpl htmlCopy = htmlEntry.writableCopy;
4648 if (thrownException == null) {
4649 htmlCopy.setValue(HtmlEntry.ANGULAR_ERRORS, task.resolutionErrors);
4650 // notify about errors
4651 ChangeNoticeImpl notice = _getNotice(source);
4652 notice.htmlUnit = task.resolvedUnit;
4653 notice.setErrors(htmlCopy.allErrors, htmlCopy.getValue(SourceEntry.LINE_ INFO));
4654 } else {
4655 htmlCopy.recordResolutionError(thrownException);
4656 }
4657 _cache.put(source, htmlCopy);
4658 htmlEntry = htmlCopy;
4659 } else {
4660 HtmlEntryImpl htmlCopy = htmlEntry.writableCopy;
4661 if (thrownException == null || resultTime >= 0) {
4662 //
4663 // The analysis was performed on out-of-date sources. Mark the cache so that the sources
4664 // will be re-analyzed using the up-to-date sources.
4665 //
4666 // if (htmlCopy.getState(HtmlEntry.ANGULAR_ERRORS) == CacheStat e.IN_PROCESS) {
4667 // htmlCopy.setState(HtmlEntry.ANGULAR_ERRORS, CacheState.INV ALID);
4668 // }
4669 // if (htmlCopy.getState(HtmlEntry.ELEMENT) == CacheState.IN_PR OCESS) {
4670 // htmlCopy.setState(HtmlEntry.ELEMENT, CacheState.INVALID);
4671 // }
4672 // if (htmlCopy.getState(HtmlEntry.RESOLUTION_ERRORS) == CacheS tate.IN_PROCESS) {
4673 // htmlCopy.setState(HtmlEntry.RESOLUTION_ERRORS, CacheState. INVALID);
4674 // }
4675 htmlCopy.invalidateAllInformation();
4676 htmlCopy.modificationTime = sourceTime;
4677 _cache.removedAst(source);
4678 } else {
4679 //
4680 // We could not determine whether the sources were up-to-date or out-of- date. Mark the
4681 // cache so that we won't attempt to re-analyze the sources until there' s a good chance
4682 // that we'll be able to do so without error.
4683 //
4684 htmlCopy.recordResolutionError(thrownException);
4685 }
4686 _cache.put(source, htmlCopy);
4687 htmlEntry = htmlCopy;
4688 }
4689 if (thrownException != null) {
4690 throw new AnalysisException('<rethrow>', thrownException);
4691 }
4692 return htmlEntry;
4693 }
4694
4695 /**
4696 * Record the results produced by performing a [ResolveAngularEntryHtmlTask]. If the results
4697 * were computed from data that is now out-of-date, then the results will not be recorded.
4698 *
4699 * @param task the task that was performed
4700 * @throws AnalysisException if the results could not be recorded
4701 */
4702 HtmlEntry _recordResolveAngularEntryHtmlTaskResults(ResolveAngularEntryHtmlTas k task) {
4703 Source source = task.source;
4704 CaughtException thrownException = task.exception;
4705 HtmlEntry htmlEntry = null;
4706 SourceEntry sourceEntry = _cache.get(source);
4707 if (sourceEntry == null) {
4708 throw new ObsoleteSourceAnalysisException(source);
4709 } else if (sourceEntry is! HtmlEntry) {
4710 // This shouldn't be possible because we should never have performed the t ask if the source
4711 // didn't represent an HTML file, but check to be safe.
4712 throw new AnalysisException("Internal error: attempting to resolve non-HTM L file as an HTML file: ${source.fullName}");
4713 }
4714 htmlEntry = sourceEntry as HtmlEntry;
4715 int sourceTime = getModificationStamp(source);
4716 int resultTime = task.modificationTime;
4717 if (sourceTime == resultTime) {
4718 if (htmlEntry.modificationTime != sourceTime) {
4719 // The source has changed without the context being notified. Simulate n otification.
4720 _sourceChanged(source);
4721 htmlEntry = _getReadableHtmlEntry(source);
4722 if (htmlEntry == null) {
4723 throw new AnalysisException("An HTML file became a non-HTML file: ${so urce.fullName}");
4724 }
4725 }
4726 HtmlEntryImpl htmlCopy = htmlEntry.writableCopy;
4727 if (thrownException == null) {
4728 htmlCopy.setValue(HtmlEntry.RESOLVED_UNIT, task.resolvedUnit);
4729 _recordAngularEntryPoint(htmlCopy, task);
4730 _cache.storedAst(source);
4731 ChangeNoticeImpl notice = _getNotice(source);
4732 notice.htmlUnit = task.resolvedUnit;
4733 notice.setErrors(htmlCopy.allErrors, htmlCopy.getValue(SourceEntry.LINE_ INFO));
4734 } else {
4735 htmlCopy.recordResolutionError(thrownException);
4736 }
4737 _cache.put(source, htmlCopy);
4738 htmlEntry = htmlCopy;
4739 } else {
4740 HtmlEntryImpl htmlCopy = htmlEntry.writableCopy;
4741 if (thrownException == null || resultTime >= 0) {
4742 //
4743 // The analysis was performed on out-of-date sources. Mark the cache so that the sources
4744 // will be re-analyzed using the up-to-date sources.
4745 //
4746 // if (htmlCopy.getState(HtmlEntry.ANGULAR_ERRORS) == CacheStat e.IN_PROCESS) {
4747 // htmlCopy.setState(HtmlEntry.ANGULAR_ERRORS, CacheState.INV ALID);
4748 // }
4749 // if (htmlCopy.getState(HtmlEntry.ELEMENT) == CacheState.IN_PR OCESS) {
4750 // htmlCopy.setState(HtmlEntry.ELEMENT, CacheState.INVALID);
4751 // }
4752 // if (htmlCopy.getState(HtmlEntry.RESOLUTION_ERRORS) == CacheS tate.IN_PROCESS) {
4753 // htmlCopy.setState(HtmlEntry.RESOLUTION_ERRORS, CacheState. INVALID);
4754 // }
4755 htmlCopy.invalidateAllInformation();
4756 htmlCopy.modificationTime = sourceTime;
4757 _cache.removedAst(source);
4758 } else {
4759 //
4760 // We could not determine whether the sources were up-to-date or out-of- date. Mark the
4761 // cache so that we won't attempt to re-analyze the sources until there' s a good chance
4762 // that we'll be able to do so without error.
4763 //
4764 htmlCopy.recordResolutionError(thrownException);
4765 }
4766 _cache.put(source, htmlCopy);
4767 htmlEntry = htmlCopy;
4768 }
4769 if (thrownException != null) {
4770 throw new AnalysisException('<rethrow>', thrownException);
4771 }
4772 return htmlEntry;
4773 }
4774
4775 /**
4776 * Record the results produced by performing a [ResolveDartUnitTask]. If the r esults were
4777 * computed from data that is now out-of-date, then the results will not be re corded.
4778 *
4779 * @param task the task that was performed
4780 * @return an entry containing the computed results
4781 * @throws AnalysisException if the results could not be recorded
4782 */
4783 DartEntry _recordResolveDartUnitTaskResults(ResolveDartUnitTask task) {
4784 Source unitSource = task.source;
4785 Source librarySource = task.librarySource;
4786 CaughtException thrownException = task.exception;
4787 DartEntry dartEntry = null;
4788 SourceEntry sourceEntry = _cache.get(unitSource);
4789 if (sourceEntry == null) {
4790 throw new ObsoleteSourceAnalysisException(unitSource);
4791 } else if (sourceEntry is! DartEntry) {
4792 // This shouldn't be possible because we should never have performed the t ask if the source
4793 // didn't represent a Dart file, but check to be safe.
4794 throw new AnalysisException("Internal error: attempting to resolve non-Dar t file as a Dart file: ${unitSource.fullName}");
4795 }
4796 dartEntry = sourceEntry as DartEntry;
4797 int sourceTime = getModificationStamp(unitSource);
4798 int resultTime = task.modificationTime;
4799 if (sourceTime == resultTime) {
4800 if (dartEntry.modificationTime != sourceTime) {
4801 // The source has changed without the context being notified. Simulate n otification.
4802 _sourceChanged(unitSource);
4803 dartEntry = _getReadableDartEntry(unitSource);
4804 if (dartEntry == null) {
4805 throw new AnalysisException("A Dart file became a non-Dart file: ${uni tSource.fullName}");
4806 }
4807 }
4808 DartEntryImpl dartCopy = dartEntry.writableCopy;
4809 if (thrownException == null) {
4810 dartCopy.setValueInLibrary(DartEntry.RESOLVED_UNIT, librarySource, task. resolvedUnit);
4811 _cache.storedAst(unitSource);
4812 } else {
4813 dartCopy.recordResolutionErrorInLibrary(librarySource, thrownException);
4814 _cache.removedAst(unitSource);
4815 }
4816 _cache.put(unitSource, dartCopy);
4817 dartEntry = dartCopy;
4818 } else {
4819 _logInformation2("Resolution results discarded for ${_debuggingString(unit Source)}; sourceTime = ${sourceTime}, resultTime = ${resultTime}, cacheTime = ${ dartEntry.modificationTime}", thrownException);
4820 DartEntryImpl dartCopy = dartEntry.writableCopy;
4821 if (thrownException == null || resultTime >= 0) {
4822 //
4823 // The analysis was performed on out-of-date sources. Mark the cache so that the sources
4824 // will be re-analyzed using the up-to-date sources.
4825 //
4826 // if (dartCopy.getState(DartEntry.RESOLVED_UNIT) == CacheState .IN_PROCESS) {
4827 // dartCopy.setState(DartEntry.RESOLVED_UNIT, librarySource, CacheState.INVALID);
4828 // }
4829 _removeFromParts(unitSource, dartEntry);
4830 dartCopy.invalidateAllInformation();
4831 dartCopy.modificationTime = sourceTime;
4832 _cache.removedAst(unitSource);
4833 _workManager.add(unitSource, SourcePriority.UNKNOWN);
4834 } else {
4835 //
4836 // We could not determine whether the sources were up-to-date or out-of- date. Mark the
4837 // cache so that we won't attempt to re-analyze the sources until there' s a good chance
4838 // that we'll be able to do so without error.
4839 //
4840 dartCopy.recordResolutionErrorInLibrary(librarySource, thrownException);
4841 }
4842 _cache.put(unitSource, dartCopy);
4843 dartEntry = dartCopy;
4844 }
4845 if (thrownException != null) {
4846 throw new AnalysisException('<rethrow>', thrownException);
4847 }
4848 return dartEntry;
4849 }
4850
4851 /**
4852 * Record the results produced by performing a [ResolveHtmlTask]. If the resul ts were
4853 * computed from data that is now out-of-date, then the results will not be re corded.
4854 *
4855 * @param task the task that was performed
4856 * @return an entry containing the computed results
4857 * @throws AnalysisException if the results could not be recorded
4858 */
4859 HtmlEntry _recordResolveHtmlTaskResults(ResolveHtmlTask task) {
4860 Source source = task.source;
4861 CaughtException thrownException = task.exception;
4862 HtmlEntry htmlEntry = null;
4863 SourceEntry sourceEntry = _cache.get(source);
4864 if (sourceEntry == null) {
4865 throw new ObsoleteSourceAnalysisException(source);
4866 } else if (sourceEntry is! HtmlEntry) {
4867 // This shouldn't be possible because we should never have performed the t ask if the source
4868 // didn't represent an HTML file, but check to be safe.
4869 throw new AnalysisException("Internal error: attempting to resolve non-HTM L file as an HTML file: ${source.fullName}");
4870 }
4871 htmlEntry = sourceEntry as HtmlEntry;
4872 int sourceTime = getModificationStamp(source);
4873 int resultTime = task.modificationTime;
4874 if (sourceTime == resultTime) {
4875 if (htmlEntry.modificationTime != sourceTime) {
4876 // The source has changed without the context being notified. Simulate n otification.
4877 _sourceChanged(source);
4878 htmlEntry = _getReadableHtmlEntry(source);
4879 if (htmlEntry == null) {
4880 throw new AnalysisException("An HTML file became a non-HTML file: ${so urce.fullName}");
4881 }
4882 }
4883 HtmlEntryImpl htmlCopy = htmlEntry.writableCopy;
4884 if (thrownException == null) {
4885 htmlCopy.setState(HtmlEntry.PARSED_UNIT, CacheState.FLUSHED);
4886 htmlCopy.setValue(HtmlEntry.RESOLVED_UNIT, task.resolvedUnit);
4887 htmlCopy.setValue(HtmlEntry.ELEMENT, task.element);
4888 htmlCopy.setValue(HtmlEntry.RESOLUTION_ERRORS, task.resolutionErrors);
4889 _cache.storedAst(source);
4890 ChangeNoticeImpl notice = _getNotice(source);
4891 notice.htmlUnit = task.resolvedUnit;
4892 notice.setErrors(htmlCopy.allErrors, htmlCopy.getValue(SourceEntry.LINE_ INFO));
4893 } else {
4894 htmlCopy.recordResolutionError(thrownException);
4895 _cache.removedAst(source);
4896 }
4897 _cache.put(source, htmlCopy);
4898 htmlEntry = htmlCopy;
4899 } else {
4900 _logInformation2("Resolution results discarded for ${_debuggingString(sour ce)}; sourceTime = ${sourceTime}, resultTime = ${resultTime}, cacheTime = ${html Entry.modificationTime}", thrownException);
4901 HtmlEntryImpl htmlCopy = htmlEntry.writableCopy;
4902 if (thrownException == null || resultTime >= 0) {
4903 //
4904 // The analysis was performed on out-of-date sources. Mark the cache so that the sources
4905 // will be re-analyzed using the up-to-date sources.
4906 //
4907 // if (htmlCopy.getState(HtmlEntry.ELEMENT) == CacheState.IN_PR OCESS) {
4908 // htmlCopy.setState(HtmlEntry.ELEMENT, CacheState.INVALID);
4909 // }
4910 // if (htmlCopy.getState(HtmlEntry.RESOLUTION_ERRORS) == CacheS tate.IN_PROCESS) {
4911 // htmlCopy.setState(HtmlEntry.RESOLUTION_ERRORS, CacheState. INVALID);
4912 // }
4913 htmlCopy.invalidateAllInformation();
4914 htmlCopy.modificationTime = sourceTime;
4915 _cache.removedAst(source);
4916 } else {
4917 //
4918 // We could not determine whether the sources were up-to-date or out-of- date. Mark the
4919 // cache so that we won't attempt to re-analyze the sources until there' s a good chance
4920 // that we'll be able to do so without error.
4921 //
4922 htmlCopy.recordResolutionError(thrownException);
4923 }
4924 _cache.put(source, htmlCopy);
4925 htmlEntry = htmlCopy;
4926 }
4927 if (thrownException != null) {
4928 throw new AnalysisException('<rethrow>', thrownException);
4929 }
4930 return htmlEntry;
4931 }
4932
4933 /**
4934 * Record the results produced by performing a [ScanDartTask]. If the results were computed
4935 * from data that is now out-of-date, then the results will not be recorded.
4936 *
4937 * @param task the task that was performed
4938 * @return an entry containing the computed results
4939 * @throws AnalysisException if the results could not be recorded
4940 */
4941 DartEntry _recordScanDartTaskResults(ScanDartTask task) {
4942 Source source = task.source;
4943 CaughtException thrownException = task.exception;
4944 DartEntry dartEntry = null;
4945 SourceEntry sourceEntry = _cache.get(source);
4946 if (sourceEntry == null) {
4947 throw new ObsoleteSourceAnalysisException(source);
4948 } else if (sourceEntry is! DartEntry) {
4949 // This shouldn't be possible because we should never have performed the t ask if the source
4950 // didn't represent a Dart file, but check to be safe.
4951 throw new AnalysisException("Internal error: attempting to parse non-Dart file as a Dart file: ${source.fullName}");
4952 }
4953 dartEntry = sourceEntry as DartEntry;
4954 int sourceTime = getModificationStamp(source);
4955 int resultTime = task.modificationTime;
4956 if (sourceTime == resultTime) {
4957 if (dartEntry.modificationTime != sourceTime) {
4958 // The source has changed without the context being notified. Simulate n otification.
4959 _sourceChanged(source);
4960 dartEntry = _getReadableDartEntry(source);
4961 if (dartEntry == null) {
4962 throw new AnalysisException("A Dart file became a non-Dart file: ${sou rce.fullName}");
4963 }
4964 }
4965 DartEntryImpl dartCopy = dartEntry.writableCopy;
4966 if (thrownException == null) {
4967 LineInfo lineInfo = task.lineInfo;
4968 dartCopy.setValue(SourceEntry.LINE_INFO, lineInfo);
4969 dartCopy.setValue(DartEntry.TOKEN_STREAM, task.tokenStream);
4970 dartCopy.setValue(DartEntry.SCAN_ERRORS, task.errors);
4971 _cache.storedAst(source);
4972 ChangeNoticeImpl notice = _getNotice(source);
4973 notice.setErrors(dartEntry.allErrors, lineInfo);
4974 } else {
4975 _removeFromParts(source, dartEntry);
4976 dartCopy.recordScanError(thrownException);
4977 _cache.removedAst(source);
4978 }
4979 _cache.put(source, dartCopy);
4980 dartEntry = dartCopy;
4981 } else {
4982 _logInformation2("Scan results discarded for ${_debuggingString(source)}; sourceTime = ${sourceTime}, resultTime = ${resultTime}, cacheTime = ${dartEntry. modificationTime}", thrownException);
4983 DartEntryImpl dartCopy = dartEntry.writableCopy;
4984 if (thrownException == null || resultTime >= 0) {
4985 //
4986 // The analysis was performed on out-of-date sources. Mark the cache so that the sources
4987 // will be re-analyzed using the up-to-date sources.
4988 //
4989 // dartCopy.recordScanNotInProcess();
4990 _removeFromParts(source, dartEntry);
4991 dartCopy.invalidateAllInformation();
4992 dartCopy.modificationTime = sourceTime;
4993 _cache.removedAst(source);
4994 _workManager.add(source, SourcePriority.UNKNOWN);
4995 } else {
4996 //
4997 // We could not determine whether the sources were up-to-date or out-of- date. Mark the
4998 // cache so that we won't attempt to re-analyze the sources until there' s a good chance
4999 // that we'll be able to do so without error.
5000 //
5001 dartCopy.recordScanError(thrownException);
5002 }
5003 _cache.put(source, dartCopy);
5004 dartEntry = dartCopy;
5005 }
5006 if (thrownException != null) {
5007 throw new AnalysisException('<rethrow>', thrownException);
5008 }
5009 return dartEntry;
5010 }
5011
5012 /**
5013 * Remove the given library from the list of containing libraries for all of t he parts referenced
5014 * by the given entry.
5015 *
5016 * <b>Note:</b> This method must only be invoked while we are synchronized on [cacheLock].
5017 *
5018 * @param librarySource the library to be removed
5019 * @param dartEntry the entry containing the list of included parts
5020 */
5021 void _removeFromParts(Source librarySource, DartEntry dartEntry) {
5022 List<Source> oldParts = dartEntry.getValue(DartEntry.INCLUDED_PARTS);
5023 for (int i = 0; i < oldParts.length; i++) {
5024 Source partSource = oldParts[i];
5025 DartEntry partEntry = _getReadableDartEntry(partSource);
5026 if (partEntry != null && !identical(partEntry, dartEntry)) {
5027 DartEntryImpl partCopy = partEntry.writableCopy;
5028 partCopy.removeContainingLibrary(librarySource);
5029 if (partCopy.containingLibraries.length == 0 && !exists(partSource)) {
5030 _cache.remove(partSource);
5031 } else {
5032 _cache.put(partSource, partCopy);
5033 }
5034 }
5035 }
5036 }
5037
5038 /**
5039 * Remove the given libraries that are keys in the given map from the list of containing libraries
5040 * for each of the parts in the corresponding value.
5041 *
5042 * <b>Note:</b> This method must only be invoked while we are synchronized on [cacheLock].
5043 *
5044 * @param oldPartMap the table containing the parts associated with each libra ry
5045 */
5046 void _removeFromPartsUsingMap(HashMap<Source, List<Source>> oldPartMap) {
5047 for (MapEntry<Source, List<Source>> entry in getMapEntrySet(oldPartMap)) {
5048 Source librarySource = entry.getKey();
5049 List<Source> oldParts = entry.getValue();
5050 for (int i = 0; i < oldParts.length; i++) {
5051 Source partSource = oldParts[i];
5052 if (partSource != librarySource) {
5053 DartEntry partEntry = _getReadableDartEntry(partSource);
5054 if (partEntry != null) {
5055 DartEntryImpl partCopy = partEntry.writableCopy;
5056 partCopy.removeContainingLibrary(librarySource);
5057 if (partCopy.containingLibraries.length == 0 && !exists(partSource)) {
5058 _cache.remove(partSource);
5059 } else {
5060 _cache.put(partSource, partCopy);
5061 }
5062 }
5063 }
5064 }
5065 }
5066 }
5067
5068 /**
5069 * Remove the given source from the priority order if it is in the list.
5070 *
5071 * @param source the source to be removed
5072 */
5073 void _removeFromPriorityOrder(Source source) {
5074 int count = _priorityOrder.length;
5075 List<Source> newOrder = new List<Source>();
5076 for (int i = 0; i < count; i++) {
5077 if (_priorityOrder[i] != source) {
5078 newOrder.add(_priorityOrder[i]);
5079 }
5080 }
5081 if (newOrder.length < count) {
5082 analysisPriorityOrder = newOrder;
5083 }
5084 }
5085
5086 /**
5087 * Create an entry for the newly added source. Return `true` if the new source is a Dart
5088 * file.
5089 *
5090 * <b>Note:</b> This method must only be invoked while we are synchronized on [cacheLock].
5091 *
5092 * @param source the source that has been added
5093 * @return `true` if the new source is a Dart file
5094 */
5095 bool _sourceAvailable(Source source) {
5096 SourceEntry sourceEntry = _cache.get(source);
5097 if (sourceEntry == null) {
5098 sourceEntry = _createSourceEntry(source, true);
5099 } else {
5100 _sourceChanged(source);
5101 sourceEntry = _cache.get(source);
5102 }
5103 if (sourceEntry is HtmlEntry) {
5104 _workManager.add(source, SourcePriority.HTML);
5105 } else if (sourceEntry is DartEntry) {
5106 _workManager.add(source, _computePriority(sourceEntry as DartEntry));
5107 }
5108 return sourceEntry is DartEntry;
5109 }
5110
5111 /**
5112 * <b>Note:</b> This method must only be invoked while we are synchronized on [cacheLock].
5113 *
5114 * @param source the source that has been changed
5115 */
5116 void _sourceChanged(Source source) {
5117 SourceEntry sourceEntry = _cache.get(source);
5118 if (sourceEntry == null || sourceEntry.modificationTime == getModificationSt amp(source)) {
5119 // Either we have removed this source, in which case we don't care that it is changed, or we
5120 // have already invalidated the cache and don't need to invalidate it agai n.
5121 return;
5122 }
5123 if (sourceEntry is HtmlEntry) {
5124 HtmlEntryImpl htmlCopy = sourceEntry.writableCopy;
5125 htmlCopy.modificationTime = getModificationStamp(source);
5126 _invalidateAngularResolution(htmlCopy);
5127 htmlCopy.invalidateAllInformation();
5128 _cache.put(source, htmlCopy);
5129 _cache.removedAst(source);
5130 _workManager.add(source, SourcePriority.HTML);
5131 } else if (sourceEntry is DartEntry) {
5132 List<Source> containingLibraries = getLibrariesContaining(source);
5133 HashSet<Source> librariesToInvalidate = new HashSet<Source>();
5134 for (Source containingLibrary in containingLibraries) {
5135 _computeAllLibrariesDependingOn(containingLibrary, librariesToInvalidate );
5136 }
5137 for (Source library in librariesToInvalidate) {
5138 _invalidateLibraryResolution(library);
5139 }
5140 _removeFromParts(source, _cache.get(source) as DartEntry);
5141 DartEntryImpl dartCopy = (_cache.get(source) as DartEntry).writableCopy;
5142 dartCopy.modificationTime = getModificationStamp(source);
5143 dartCopy.invalidateAllInformation();
5144 _cache.put(source, dartCopy);
5145 _cache.removedAst(source);
5146 _workManager.add(source, SourcePriority.UNKNOWN);
5147 }
5148 }
5149
5150 /**
5151 * <b>Note:</b> This method must only be invoked while we are synchronized on [cacheLock].
5152 *
5153 * @param source the source that has been deleted
5154 */
5155 void _sourceDeleted(Source source) {
5156 SourceEntry sourceEntry = _cache.get(source);
5157 if (sourceEntry is HtmlEntry) {
5158 HtmlEntryImpl htmlCopy = sourceEntry.writableCopy;
5159 _invalidateAngularResolution(htmlCopy);
5160 htmlCopy.recordContentError(new CaughtException(new AnalysisException("Thi s source was marked as being deleted"), null));
5161 _cache.put(source, htmlCopy);
5162 } else if (sourceEntry is DartEntry) {
5163 HashSet<Source> libraries = new HashSet<Source>();
5164 for (Source librarySource in getLibrariesContaining(source)) {
5165 libraries.add(librarySource);
5166 for (Source dependentLibrary in getLibrariesDependingOn(librarySource)) {
5167 libraries.add(dependentLibrary);
5168 }
5169 }
5170 for (Source librarySource in libraries) {
5171 _invalidateLibraryResolution(librarySource);
5172 }
5173 DartEntryImpl dartCopy = sourceEntry.writableCopy;
5174 dartCopy.recordContentError(new CaughtException(new AnalysisException("Thi s source was marked as being deleted"), null));
5175 _cache.put(source, dartCopy);
5176 }
5177 _workManager.remove(source);
5178 _removeFromPriorityOrder(source);
5179 }
5180
5181 /**
5182 * <b>Note:</b> This method must only be invoked while we are synchronized on [cacheLock].
5183 *
5184 * @param source the source that has been removed
5185 */
5186 void _sourceRemoved(Source source) {
5187 SourceEntry sourceEntry = _cache.get(source);
5188 if (sourceEntry is HtmlEntry) {
5189 HtmlEntryImpl htmlCopy = sourceEntry.writableCopy;
5190 _invalidateAngularResolution(htmlCopy);
5191 } else if (sourceEntry is DartEntry) {
5192 HashSet<Source> libraries = new HashSet<Source>();
5193 for (Source librarySource in getLibrariesContaining(source)) {
5194 libraries.add(librarySource);
5195 for (Source dependentLibrary in getLibrariesDependingOn(librarySource)) {
5196 libraries.add(dependentLibrary);
5197 }
5198 }
5199 for (Source librarySource in libraries) {
5200 _invalidateLibraryResolution(librarySource);
5201 }
5202 }
5203 _cache.remove(source);
5204 _workManager.remove(source);
5205 _removeFromPriorityOrder(source);
5206 }
5207
5208 /**
5209 * Check the cache for any invalid entries (entries whose modification time do es not match the
5210 * modification time of the source associated with the entry). Invalid entries will be marked as
5211 * invalid so that the source will be re-analyzed.
5212 *
5213 * <b>Note:</b> This method must only be invoked while we are synchronized on [cacheLock].
5214 *
5215 * @return `true` if at least one entry was invalid
5216 */
5217 bool _validateCacheConsistency() {
5218 int consistencyCheckStart = JavaSystem.nanoTime();
5219 List<Source> changedSources = new List<Source>();
5220 List<Source> missingSources = new List<Source>();
5221 MapIterator<Source, SourceEntry> iterator = _cache.iterator();
5222 while (iterator.moveNext()) {
5223 Source source = iterator.key;
5224 SourceEntry sourceEntry = iterator.value;
5225 int sourceTime = getModificationStamp(source);
5226 if (sourceTime != sourceEntry.modificationTime) {
5227 changedSources.add(source);
5228 }
5229 if (sourceEntry.exception != null) {
5230 if (!exists(source)) {
5231 missingSources.add(source);
5232 }
5233 }
5234 }
5235 int count = changedSources.length;
5236 for (int i = 0; i < count; i++) {
5237 _sourceChanged(changedSources[i]);
5238 }
5239 int consistencyCheckEnd = JavaSystem.nanoTime();
5240 if (changedSources.length > 0 || missingSources.length > 0) {
5241 PrintStringWriter writer = new PrintStringWriter();
5242 writer.print("Consistency check took ");
5243 writer.print((consistencyCheckEnd - consistencyCheckStart) / 1000000.0);
5244 writer.println(" ms and found");
5245 writer.print(" ");
5246 writer.print(changedSources.length);
5247 writer.println(" inconsistent entries");
5248 writer.print(" ");
5249 writer.print(missingSources.length);
5250 writer.println(" missing sources");
5251 for (Source source in missingSources) {
5252 writer.print(" ");
5253 writer.println(source.fullName);
5254 }
5255 _logInformation(writer.toString());
5256 }
5257 return changedSources.length > 0;
5258 }
5259 }
5260
5261 /**
5262 * Instances of the class `AnalysisTaskResultRecorder` are used by an analysis c ontext to
5263 * record the results of a task.
5264 */
5265 class AnalysisContextImpl_AnalysisTaskResultRecorder implements AnalysisTaskVisi tor<SourceEntry> {
5266 final AnalysisContextImpl AnalysisContextImpl_this;
5267
5268 AnalysisContextImpl_AnalysisTaskResultRecorder(this.AnalysisContextImpl_this);
5269
5270 @override
5271 DartEntry visitGenerateDartErrorsTask(GenerateDartErrorsTask task) => Analysis ContextImpl_this._recordGenerateDartErrorsTask(task);
5272
5273 @override
5274 DartEntry visitGenerateDartHintsTask(GenerateDartHintsTask task) => AnalysisCo ntextImpl_this._recordGenerateDartHintsTask(task);
5275
5276 @override
5277 SourceEntry visitGetContentTask(GetContentTask task) => AnalysisContextImpl_th is._recordGetContentsTask(task);
5278
5279 @override
5280 DartEntry visitIncrementalAnalysisTask(IncrementalAnalysisTask task) => Analys isContextImpl_this._recordIncrementalAnalysisTaskResults(task);
5281
5282 @override
5283 DartEntry visitParseDartTask(ParseDartTask task) => AnalysisContextImpl_this._ recordParseDartTaskResults(task);
5284
5285 @override
5286 HtmlEntry visitParseHtmlTask(ParseHtmlTask task) => AnalysisContextImpl_this._ recordParseHtmlTaskResults(task);
5287
5288 @override
5289 HtmlEntry visitPolymerBuildHtmlTask(PolymerBuildHtmlTask task) => AnalysisCont extImpl_this._recordPolymerBuildHtmlTaskResults(task);
5290
5291 @override
5292 HtmlEntry visitPolymerResolveHtmlTask(PolymerResolveHtmlTask task) => Analysis ContextImpl_this._recordPolymerResolveHtmlTaskResults(task);
5293
5294 @override
5295 HtmlEntry visitResolveAngularComponentTemplateTask(ResolveAngularComponentTemp lateTask task) => AnalysisContextImpl_this._recordResolveAngularComponentTemplat eTaskResults(task);
5296
5297 @override
5298 HtmlEntry visitResolveAngularEntryHtmlTask(ResolveAngularEntryHtmlTask task) = > AnalysisContextImpl_this._recordResolveAngularEntryHtmlTaskResults(task);
5299
5300 @override
5301 DartEntry visitResolveDartLibraryCycleTask(ResolveDartLibraryCycleTask task) = > AnalysisContextImpl_this.recordResolveDartLibraryCycleTaskResults(task);
5302
5303 @override
5304 DartEntry visitResolveDartLibraryTask(ResolveDartLibraryTask task) => Analysis ContextImpl_this.recordResolveDartLibraryTaskResults(task);
5305
5306 @override
5307 DartEntry visitResolveDartUnitTask(ResolveDartUnitTask task) => AnalysisContex tImpl_this._recordResolveDartUnitTaskResults(task);
5308
5309 @override
5310 HtmlEntry visitResolveHtmlTask(ResolveHtmlTask task) => AnalysisContextImpl_th is._recordResolveHtmlTaskResults(task);
5311
5312 @override
5313 DartEntry visitScanDartTask(ScanDartTask task) => AnalysisContextImpl_this._re cordScanDartTaskResults(task);
5314 }
5315
5316 class AnalysisContextImpl_ContextRetentionPolicy implements CacheRetentionPolicy {
5317 final AnalysisContextImpl AnalysisContextImpl_this;
5318
5319 AnalysisContextImpl_ContextRetentionPolicy(this.AnalysisContextImpl_this);
5320
5321 @override
5322 RetentionPriority getAstPriority(Source source, SourceEntry sourceEntry) {
5323 int priorityCount = AnalysisContextImpl_this._priorityOrder.length;
5324 for (int i = 0; i < priorityCount; i++) {
5325 if (source == AnalysisContextImpl_this._priorityOrder[i]) {
5326 return RetentionPriority.HIGH;
5327 }
5328 }
5329 if (AnalysisContextImpl_this._neededForResolution != null && AnalysisContext Impl_this._neededForResolution.contains(source)) {
5330 return RetentionPriority.HIGH;
5331 }
5332 if (sourceEntry is DartEntry) {
5333 DartEntry dartEntry = sourceEntry;
5334 if (_astIsNeeded(dartEntry)) {
5335 return RetentionPriority.MEDIUM;
5336 }
5337 }
5338 return RetentionPriority.LOW;
5339 }
5340
5341 bool _astIsNeeded(DartEntry dartEntry) => dartEntry.hasInvalidData(DartEntry.H INTS) || dartEntry.hasInvalidData(DartEntry.VERIFICATION_ERRORS) || dartEntry.ha sInvalidData(DartEntry.RESOLUTION_ERRORS);
5342 }
5343
5344 /**
5345 * Instances of the class `CycleBuilder` are used to construct a list of the lib raries that
5346 * must be resolved together in order to resolve any one of the libraries.
5347 */
5348 class AnalysisContextImpl_CycleBuilder {
5349 final AnalysisContextImpl AnalysisContextImpl_this;
5350
5351 /**
5352 * A table mapping the sources of the defining compilation units of libraries to the
5353 * representation of the library that has the information needed to resolve th e library.
5354 */
5355 HashMap<Source, ResolvableLibrary> _libraryMap = new HashMap<Source, Resolvabl eLibrary>();
5356
5357 /**
5358 * The dependency graph used to compute the libraries in the cycle.
5359 */
5360 DirectedGraph<ResolvableLibrary> _dependencyGraph;
5361
5362 /**
5363 * A list containing the libraries that are ready to be resolved.
5364 */
5365 List<ResolvableLibrary> _librariesInCycle;
5366
5367 /**
5368 * The analysis task that needs to be performed before the cycle of libraries can be resolved,
5369 * or `null` if the libraries are ready to be resolved.
5370 */
5371 AnalysisContextImpl_TaskData _taskData;
5372
5373 /**
5374 * Initialize a newly created cycle builder.
5375 */
5376 AnalysisContextImpl_CycleBuilder(this.AnalysisContextImpl_this) : super();
5377
5378 /**
5379 * Compute a list of the libraries that need to be resolved together in order to resolve the
5380 * given library.
5381 *
5382 * @param librarySource the source of the library to be resolved
5383 * @throws AnalysisException if the core library cannot be found
5384 */
5385 void computeCycleContaining(Source librarySource) {
5386 //
5387 // Create the object representing the library being resolved.
5388 //
5389 ResolvableLibrary targetLibrary = _createLibrary(librarySource);
5390 //
5391 // Compute the set of libraries that need to be resolved together.
5392 //
5393 _dependencyGraph = new DirectedGraph<ResolvableLibrary>();
5394 _computeLibraryDependencies(targetLibrary);
5395 if (_taskData != null) {
5396 return;
5397 }
5398 _librariesInCycle = _dependencyGraph.findCycleContaining(targetLibrary);
5399 //
5400 // Ensure that all of the data needed to resolve them has been computed.
5401 //
5402 _ensureImportsAndExports();
5403 if (_taskData != null) {
5404 // At least one imported library needs to be resolved before the target li brary.
5405 AnalysisTask task = _taskData.task;
5406 if (task is ResolveDartLibraryTask) {
5407 AnalysisContextImpl_this._workManager.addFirst(task.librarySource, Sourc ePriority.LIBRARY);
5408 }
5409 return;
5410 }
5411 _computePartsInCycle(librarySource);
5412 if (_taskData != null) {
5413 // At least one part needs to be parsed.
5414 return;
5415 }
5416 // All of the AST's necessary to perform a resolution of the library cycle h ave been
5417 // gathered, so it is no longer necessary to retain them in the cache.
5418 AnalysisContextImpl_this._neededForResolution = null;
5419 }
5420
5421 /**
5422 * Return a list containing the libraries that are ready to be resolved (assum ing that
5423 * [getTaskData] returns `null`).
5424 *
5425 * @return the libraries that are ready to be resolved
5426 */
5427 List<ResolvableLibrary> get librariesInCycle => _librariesInCycle;
5428
5429 /**
5430 * Return a representation of an analysis task that needs to be performed befo re the cycle of
5431 * libraries can be resolved, or `null` if the libraries are ready to be resol ved.
5432 *
5433 * @return the analysis task that needs to be performed before the cycle of li braries can be
5434 * resolved
5435 */
5436 AnalysisContextImpl_TaskData get taskData => _taskData;
5437
5438 /**
5439 * Recursively traverse the libraries reachable from the given library, creati ng instances of
5440 * the class [Library] to represent them, and record the references in the lib rary
5441 * objects.
5442 *
5443 * @param library the library to be processed to find libraries that have not yet been traversed
5444 * @throws AnalysisException if some portion of the library graph could not be traversed
5445 */
5446 void _computeLibraryDependencies(ResolvableLibrary library) {
5447 Source librarySource = library.librarySource;
5448 DartEntry dartEntry = AnalysisContextImpl_this._getReadableDartEntry(library Source);
5449 List<Source> importedSources = _getSources(librarySource, dartEntry, DartEnt ry.IMPORTED_LIBRARIES);
5450 if (_taskData != null) {
5451 return;
5452 }
5453 List<Source> exportedSources = _getSources(librarySource, dartEntry, DartEnt ry.EXPORTED_LIBRARIES);
5454 if (_taskData != null) {
5455 return;
5456 }
5457 _computeLibraryDependenciesFromDirectives(library, importedSources, exported Sources);
5458 }
5459
5460 /**
5461 * Recursively traverse the libraries reachable from the given library, creati ng instances of
5462 * the class [Library] to represent them, and record the references in the lib rary
5463 * objects.
5464 *
5465 * @param library the library to be processed to find libraries that have not yet been traversed
5466 * @param importedSources an array containing the sources that are imported in to the given
5467 * library
5468 * @param exportedSources an array containing the sources that are exported fr om the given
5469 * library
5470 */
5471 void _computeLibraryDependenciesFromDirectives(ResolvableLibrary library, List <Source> importedSources, List<Source> exportedSources) {
5472 int importCount = importedSources.length;
5473 if (importCount > 0) {
5474 List<ResolvableLibrary> importedLibraries = new List<ResolvableLibrary>();
5475 bool explicitlyImportsCore = false;
5476 for (int i = 0; i < importCount; i++) {
5477 Source importedSource = importedSources[i];
5478 if (importedSource == AnalysisContextImpl_this._coreLibrarySource) {
5479 explicitlyImportsCore = true;
5480 }
5481 ResolvableLibrary importedLibrary = _libraryMap[importedSource];
5482 if (importedLibrary == null) {
5483 importedLibrary = _createLibraryOrNull(importedSource);
5484 if (importedLibrary != null) {
5485 _computeLibraryDependencies(importedLibrary);
5486 if (_taskData != null) {
5487 return;
5488 }
5489 }
5490 }
5491 if (importedLibrary != null) {
5492 importedLibraries.add(importedLibrary);
5493 _dependencyGraph.addEdge(library, importedLibrary);
5494 }
5495 }
5496 library.explicitlyImportsCore = explicitlyImportsCore;
5497 if (!explicitlyImportsCore && AnalysisContextImpl_this._coreLibrarySource != library.librarySource) {
5498 ResolvableLibrary importedLibrary = _libraryMap[AnalysisContextImpl_this ._coreLibrarySource];
5499 if (importedLibrary == null) {
5500 importedLibrary = _createLibraryOrNull(AnalysisContextImpl_this._coreL ibrarySource);
5501 if (importedLibrary != null) {
5502 _computeLibraryDependencies(importedLibrary);
5503 if (_taskData != null) {
5504 return;
5505 }
5506 }
5507 }
5508 if (importedLibrary != null) {
5509 importedLibraries.add(importedLibrary);
5510 _dependencyGraph.addEdge(library, importedLibrary);
5511 }
5512 }
5513 library.importedLibraries = new List.from(importedLibraries);
5514 } else {
5515 library.explicitlyImportsCore = false;
5516 ResolvableLibrary importedLibrary = _libraryMap[AnalysisContextImpl_this._ coreLibrarySource];
5517 if (importedLibrary == null) {
5518 importedLibrary = _createLibraryOrNull(AnalysisContextImpl_this._coreLib rarySource);
5519 if (importedLibrary != null) {
5520 _computeLibraryDependencies(importedLibrary);
5521 if (_taskData != null) {
5522 return;
5523 }
5524 }
5525 }
5526 if (importedLibrary != null) {
5527 _dependencyGraph.addEdge(library, importedLibrary);
5528 library.importedLibraries = <ResolvableLibrary> [importedLibrary];
5529 }
5530 }
5531 int exportCount = exportedSources.length;
5532 if (exportCount > 0) {
5533 List<ResolvableLibrary> exportedLibraries = new List<ResolvableLibrary>();
5534 for (int i = 0; i < exportCount; i++) {
5535 Source exportedSource = exportedSources[i];
5536 ResolvableLibrary exportedLibrary = _libraryMap[exportedSource];
5537 if (exportedLibrary == null) {
5538 exportedLibrary = _createLibraryOrNull(exportedSource);
5539 if (exportedLibrary != null) {
5540 _computeLibraryDependencies(exportedLibrary);
5541 if (_taskData != null) {
5542 return;
5543 }
5544 }
5545 }
5546 if (exportedLibrary != null) {
5547 exportedLibraries.add(exportedLibrary);
5548 _dependencyGraph.addEdge(library, exportedLibrary);
5549 }
5550 }
5551 library.exportedLibraries = new List.from(exportedLibraries);
5552 }
5553 }
5554
5555 /**
5556 * Gather the resolvable AST structures for each of the compilation units in e ach of the
5557 * libraries in the cycle. This is done in two phases: first we ensure that we have cached an
5558 * AST structure for each compilation unit, then we gather them. We split the work this way
5559 * because getting the AST structures can change the state of the cache in suc h a way that we
5560 * would have more work to do if any compilation unit didn't have a resolvable AST structure.
5561 */
5562 void _computePartsInCycle(Source librarySource) {
5563 int count = _librariesInCycle.length;
5564 List<CycleBuilder_LibraryPair> libraryData = new List<CycleBuilder_LibraryPa ir>();
5565 for (int i = 0; i < count; i++) {
5566 ResolvableLibrary library = _librariesInCycle[i];
5567 libraryData.add(new CycleBuilder_LibraryPair(library, _ensurePartsInLibrar y(library)));
5568 }
5569 AnalysisContextImpl_this._neededForResolution = _gatherSources(libraryData);
5570 if (AnalysisContextImpl._TRACE_PERFORM_TASK) {
5571 print(" preserve resolution data for ${AnalysisContextImpl_this._neededFo rResolution.length} sources while resolving ${librarySource.fullName}");
5572 }
5573 if (_taskData != null) {
5574 return;
5575 }
5576 for (int i = 0; i < count; i++) {
5577 _computePartsInLibrary(libraryData[i]);
5578 }
5579 }
5580
5581 /**
5582 * Gather the resolvable compilation units for each of the compilation units i n the specified
5583 * library.
5584 *
5585 * @param libraryPair a holder containing both the library and a list of (sour ce, entry) pairs
5586 * for all of the compilation units in the library
5587 */
5588 void _computePartsInLibrary(CycleBuilder_LibraryPair libraryPair) {
5589 ResolvableLibrary library = libraryPair.library;
5590 List<CycleBuilder_SourceEntryPair> entryPairs = libraryPair.entryPairs;
5591 int count = entryPairs.length;
5592 List<ResolvableCompilationUnit> units = new List<ResolvableCompilationUnit>( count);
5593 for (int i = 0; i < count; i++) {
5594 CycleBuilder_SourceEntryPair entryPair = entryPairs[i];
5595 Source source = entryPair.source;
5596 DartEntryImpl dartCopy = entryPair.entry.writableCopy;
5597 units[i] = new ResolvableCompilationUnit.con2(dartCopy.modificationTime, d artCopy.resolvableCompilationUnit, source);
5598 AnalysisContextImpl_this._cache.put(source, dartCopy);
5599 }
5600 library.resolvableCompilationUnits = units;
5601 }
5602
5603 /**
5604 * Create an object to represent the information about the library defined by the compilation
5605 * unit with the given source.
5606 *
5607 * @param librarySource the source of the library's defining compilation unit
5608 * @return the library object that was created
5609 */
5610 ResolvableLibrary _createLibrary(Source librarySource) {
5611 ResolvableLibrary library = new ResolvableLibrary(librarySource);
5612 SourceEntry sourceEntry = AnalysisContextImpl_this._cache.get(librarySource) ;
5613 if (sourceEntry is DartEntry) {
5614 LibraryElementImpl libraryElement = sourceEntry.getValue(DartEntry.ELEMENT ) as LibraryElementImpl;
5615 if (libraryElement != null) {
5616 library.libraryElement = libraryElement;
5617 }
5618 }
5619 _libraryMap[librarySource] = library;
5620 return library;
5621 }
5622
5623 /**
5624 * Create an object to represent the information about the library defined by the compilation
5625 * unit with the given source.
5626 *
5627 * @param librarySource the source of the library's defining compilation unit
5628 * @return the library object that was created
5629 */
5630 ResolvableLibrary _createLibraryOrNull(Source librarySource) {
5631 ResolvableLibrary library = new ResolvableLibrary(librarySource);
5632 SourceEntry sourceEntry = AnalysisContextImpl_this._cache.get(librarySource) ;
5633 if (sourceEntry is DartEntry) {
5634 LibraryElementImpl libraryElement = sourceEntry.getValue(DartEntry.ELEMENT ) as LibraryElementImpl;
5635 if (libraryElement != null) {
5636 library.libraryElement = libraryElement;
5637 }
5638 }
5639 _libraryMap[librarySource] = library;
5640 return library;
5641 }
5642
5643 /**
5644 * Ensure that the given library has an element model built for it. If another task needs to be
5645 * executed first in order to build the element model, that task is placed in [taskData].
5646 *
5647 * @param library the library which needs an element model.
5648 */
5649 void _ensureElementModel(ResolvableLibrary library) {
5650 Source librarySource = library.librarySource;
5651 DartEntry libraryEntry = AnalysisContextImpl_this._getReadableDartEntry(libr arySource);
5652 if (libraryEntry != null && libraryEntry.getState(DartEntry.PARSED_UNIT) != CacheState.ERROR) {
5653 AnalysisContextImpl_this._workManager.addFirst(librarySource, SourcePriori ty.LIBRARY);
5654 if (_taskData == null) {
5655 _taskData = AnalysisContextImpl_this._createResolveDartLibraryTask(libra rySource, libraryEntry);
5656 }
5657 }
5658 }
5659
5660 /**
5661 * Ensure that all of the libraries that are exported by the given library (bu t are not
5662 * themselves in the cycle) have element models built for them. If another tas k needs to be
5663 * executed first in order to build the element model, that task is placed in [taskData].
5664 *
5665 * @param library the library being tested
5666 */
5667 void _ensureExports(ResolvableLibrary library, HashSet<Source> visitedLibrarie s) {
5668 List<ResolvableLibrary> dependencies = library.exports;
5669 int dependencyCount = dependencies.length;
5670 for (int i = 0; i < dependencyCount; i++) {
5671 ResolvableLibrary dependency = dependencies[i];
5672 if (!_librariesInCycle.contains(dependency) && visitedLibraries.add(depend ency.librarySource)) {
5673 if (dependency.libraryElement == null) {
5674 _ensureElementModel(dependency);
5675 } else {
5676 _ensureExports(dependency, visitedLibraries);
5677 }
5678 if (_taskData != null) {
5679 return;
5680 }
5681 }
5682 }
5683 }
5684
5685 /**
5686 * Ensure that all of the libraries that are exported by the given library (bu t are not
5687 * themselves in the cycle) have element models built for them. If another tas k needs to be
5688 * executed first in order to build the element model, that task is placed in [taskData].
5689 *
5690 * @param library the library being tested
5691 */
5692 void _ensureImports(ResolvableLibrary library) {
5693 List<ResolvableLibrary> dependencies = library.imports;
5694 int dependencyCount = dependencies.length;
5695 for (int i = 0; i < dependencyCount; i++) {
5696 ResolvableLibrary dependency = dependencies[i];
5697 if (!_librariesInCycle.contains(dependency) && dependency.libraryElement = = null) {
5698 _ensureElementModel(dependency);
5699 if (_taskData != null) {
5700 return;
5701 }
5702 }
5703 }
5704 }
5705
5706 /**
5707 * Ensure that all of the libraries that are either imported or exported by li braries in the
5708 * cycle (but are not themselves in the cycle) have element models built for t hem.
5709 */
5710 void _ensureImportsAndExports() {
5711 HashSet<Source> visitedLibraries = new HashSet<Source>();
5712 int libraryCount = _librariesInCycle.length;
5713 for (int i = 0; i < libraryCount; i++) {
5714 ResolvableLibrary library = _librariesInCycle[i];
5715 _ensureImports(library);
5716 if (_taskData != null) {
5717 return;
5718 }
5719 _ensureExports(library, visitedLibraries);
5720 if (_taskData != null) {
5721 return;
5722 }
5723 }
5724 }
5725
5726 /**
5727 * Ensure that there is a resolvable compilation unit available for all of the compilation units
5728 * in the given library.
5729 *
5730 * @param library the library for which resolvable compilation units must be a vailable
5731 * @return a list of (source, entry) pairs for all of the compilation units in the library
5732 */
5733 List<CycleBuilder_SourceEntryPair> _ensurePartsInLibrary(ResolvableLibrary lib rary) {
5734 List<CycleBuilder_SourceEntryPair> pairs = new List<CycleBuilder_SourceEntry Pair>();
5735 Source librarySource = library.librarySource;
5736 DartEntry libraryEntry = AnalysisContextImpl_this._getReadableDartEntry(libr arySource);
5737 if (libraryEntry == null) {
5738 throw new AnalysisException("Cannot find entry for ${librarySource.fullNam e}");
5739 } else if (libraryEntry.getState(DartEntry.PARSED_UNIT) == CacheState.ERROR) {
5740 String message = "Cannot compute parsed unit for ${librarySource.fullName} ";
5741 CaughtException exception = libraryEntry.exception;
5742 if (exception == null) {
5743 throw new AnalysisException(message);
5744 }
5745 throw new AnalysisException(message, new CaughtException(exception, null)) ;
5746 }
5747 _ensureResolvableCompilationUnit(librarySource, libraryEntry);
5748 pairs.add(new CycleBuilder_SourceEntryPair(librarySource, libraryEntry));
5749 List<Source> partSources = _getSources(librarySource, libraryEntry, DartEntr y.INCLUDED_PARTS);
5750 int count = partSources.length;
5751 for (int i = 0; i < count; i++) {
5752 Source partSource = partSources[i];
5753 DartEntry partEntry = AnalysisContextImpl_this._getReadableDartEntry(partS ource);
5754 if (partEntry != null && partEntry.getState(DartEntry.PARSED_UNIT) != Cach eState.ERROR) {
5755 _ensureResolvableCompilationUnit(partSource, partEntry);
5756 pairs.add(new CycleBuilder_SourceEntryPair(partSource, partEntry));
5757 }
5758 }
5759 return pairs;
5760 }
5761
5762 /**
5763 * Ensure that there is a resolvable compilation unit available for the given source.
5764 *
5765 * @param source the source for which a resolvable compilation unit must be av ailable
5766 * @param dartEntry the entry associated with the source
5767 */
5768 void _ensureResolvableCompilationUnit(Source source, DartEntry dartEntry) {
5769 // The entry will be null if the source represents a non-Dart file.
5770 if (dartEntry != null && !dartEntry.hasResolvableCompilationUnit) {
5771 if (_taskData == null) {
5772 _taskData = AnalysisContextImpl_this._createParseDartTask(source, dartEn try);
5773 }
5774 }
5775 }
5776
5777 HashSet<Source> _gatherSources(List<CycleBuilder_LibraryPair> libraryData) {
5778 int libraryCount = libraryData.length;
5779 HashSet<Source> sources = new HashSet<Source>();
5780 for (int i = 0; i < libraryCount; i++) {
5781 List<CycleBuilder_SourceEntryPair> entryPairs = libraryData[i].entryPairs;
5782 int entryCount = entryPairs.length;
5783 for (int j = 0; j < entryCount; j++) {
5784 sources.add(entryPairs[j].source);
5785 }
5786 }
5787 return sources;
5788 }
5789
5790 /**
5791 * Return the sources described by the given descriptor.
5792 *
5793 * @param source the source with which the sources are associated
5794 * @param dartEntry the entry corresponding to the source
5795 * @param descriptor the descriptor indicating which sources are to be returne d
5796 * @return the sources described by the given descriptor
5797 */
5798 List<Source> _getSources(Source source, DartEntry dartEntry, DataDescriptor<Li st<Source>> descriptor) {
5799 if (dartEntry == null) {
5800 return Source.EMPTY_ARRAY;
5801 }
5802 CacheState exportState = dartEntry.getState(descriptor);
5803 if (exportState == CacheState.ERROR) {
5804 return Source.EMPTY_ARRAY;
5805 } else if (exportState != CacheState.VALID) {
5806 if (_taskData == null) {
5807 _taskData = AnalysisContextImpl_this._createParseDartTask(source, dartEn try);
5808 }
5809 return Source.EMPTY_ARRAY;
5810 }
5811 return dartEntry.getValue(descriptor);
5812 }
5813 }
5814
5815 /**
5816 * Instances of the class `TaskData` represent information about the next task t o be
5817 * performed. Each data has an implicit associated source: the source that might need to be
5818 * analyzed. There are essentially three states that can be represented:
5819 * * If [getTask] returns a non-`null` value, then that is the task that should
5820 * be executed to further analyze the associated source.
5821 * * Otherwise, if [isBlocked] returns `true`, then there is no work that can be
5822 * done, but analysis for the associated source is not complete.
5823 * * Otherwise, [getDependentSource] should return a source that needs to be ana lyzed
5824 * before the analysis of the associated source can be completed.
5825 */
5826 class AnalysisContextImpl_TaskData {
5827 /**
5828 * The task that is to be performed.
5829 */
5830 final AnalysisTask task;
5831
5832 /**
5833 * A flag indicating whether the associated source is blocked waiting for its contents to be
5834 * loaded.
5835 */
5836 final bool _blocked;
5837
5838 /**
5839 * Initialize a newly created data holder.
5840 *
5841 * @param task the task that is to be performed
5842 * @param blocked `true` if the associated source is blocked waiting for its c ontents to
5843 * be loaded
5844 */
5845 AnalysisContextImpl_TaskData(this.task, this._blocked);
5846
5847 /**
5848 * Return `true` if the associated source is blocked waiting for its contents to be
5849 * loaded.
5850 *
5851 * @return `true` if the associated source is blocked waiting for its contents to be
5852 * loaded
5853 */
5854 bool get isBlocked => _blocked;
5855
5856 @override
5857 String toString() {
5858 if (task == null) {
5859 return "blocked: ${_blocked}";
5860 }
5861 return task.toString();
5862 }
5863 }
5864
5865 /**
5866 * The interface `AnalysisContextStatistics` defines access to statistics about a single
5867 * [AnalysisContext].
5868 */
5869 abstract class AnalysisContextStatistics {
5870 /**
5871 * Return the statistics for each kind of cached data.
5872 */
5873 List<AnalysisContextStatistics_CacheRow> get cacheRows;
5874
5875 /**
5876 * Return the exceptions that caused some entries to have a state of [CacheSta te#ERROR].
5877 */
5878 List<CaughtException> get exceptions;
5879
5880 /**
5881 * Return information about each of the partitions in the cache.
5882 */
5883 List<AnalysisContextStatistics_PartitionData> get partitionData;
5884
5885 /**
5886 * Return an array containing all of the sources in the cache.
5887 */
5888 List<Source> get sources;
5889 }
5890
5891 /**
5892 * Implementation of the [AnalysisContextStatistics].
5893 */
5894 class AnalysisContextStatisticsImpl implements AnalysisContextStatistics {
5895 Map<String, AnalysisContextStatistics_CacheRow> _dataMap = new HashMap<String, AnalysisContextStatistics_CacheRow>();
5896
5897 List<Source> _sources = new List<Source>();
5898
5899 HashSet<CaughtException> _exceptions = new HashSet<CaughtException>();
5900
5901 List<AnalysisContextStatistics_PartitionData> _partitionData;
5902
5903 void addSource(Source source) {
5904 _sources.add(source);
5905 }
5906
5907 @override
5908 List<AnalysisContextStatistics_CacheRow> get cacheRows {
5909 Iterable<AnalysisContextStatistics_CacheRow> items = _dataMap.values;
5910 return new List.from(items);
5911 }
5912
5913 @override
5914 List<CaughtException> get exceptions => new List.from(_exceptions);
5915
5916 @override
5917 List<AnalysisContextStatistics_PartitionData> get partitionData => _partitionD ata;
5918
5919 @override
5920 List<Source> get sources => new List.from(_sources);
5921
5922 void putCacheItem(SourceEntry dartEntry, DataDescriptor descriptor) {
5923 _internalPutCacheItem(dartEntry, descriptor, dartEntry.getState(descriptor)) ;
5924 }
5925
5926 void putCacheItemInLibrary(DartEntry dartEntry, Source librarySource, DataDesc riptor descriptor) {
5927 _internalPutCacheItem(dartEntry, descriptor, dartEntry.getStateInLibrary(des criptor, librarySource));
5928 }
5929
5930 /**
5931 * Set the partition data returned by this object to the given data.
5932 */
5933 void set partitionData(List<AnalysisContextStatistics_PartitionData> data) {
5934 _partitionData = data;
5935 }
5936
5937 void _internalPutCacheItem(SourceEntry dartEntry, DataDescriptor rowDesc, Cach eState state) {
5938 String rowName = rowDesc.toString();
5939 AnalysisContextStatisticsImpl_CacheRowImpl row = _dataMap[rowName] as Analys isContextStatisticsImpl_CacheRowImpl;
5940 if (row == null) {
5941 row = new AnalysisContextStatisticsImpl_CacheRowImpl(rowName);
5942 _dataMap[rowName] = row;
5943 }
5944 row._incState(state);
5945 if (state == CacheState.ERROR) {
5946 CaughtException exception = dartEntry.exception;
5947 if (exception != null) {
5948 _exceptions.add(exception);
5949 }
5950 }
5951 }
5952 }
5953
5954 class AnalysisContextStatisticsImpl_CacheRowImpl implements AnalysisContextStati stics_CacheRow {
5955 final String name;
5956
5957 int _errorCount = 0;
5958
5959 int _flushedCount = 0;
5960
5961 int _inProcessCount = 0;
5962
5963 int _invalidCount = 0;
5964
5965 int _validCount = 0;
5966
5967 AnalysisContextStatisticsImpl_CacheRowImpl(this.name);
5968
5969 @override
5970 bool operator ==(Object obj) => obj is AnalysisContextStatisticsImpl_CacheRowI mpl && obj.name == name;
5971
5972 @override
5973 int get errorCount => _errorCount;
5974
5975 @override
5976 int get flushedCount => _flushedCount;
5977
5978 @override
5979 int get inProcessCount => _inProcessCount;
5980
5981 @override
5982 int get invalidCount => _invalidCount;
5983
5984 @override
5985 int get validCount => _validCount;
5986
5987 @override
5988 int get hashCode => name.hashCode;
5989
5990 void _incState(CacheState state) {
5991 if (state == CacheState.ERROR) {
5992 _errorCount++;
5993 }
5994 if (state == CacheState.FLUSHED) {
5995 _flushedCount++;
5996 }
5997 if (state == CacheState.IN_PROCESS) {
5998 _inProcessCount++;
5999 }
6000 if (state == CacheState.INVALID) {
6001 _invalidCount++;
6002 }
6003 if (state == CacheState.VALID) {
6004 _validCount++;
6005 }
6006 }
6007 }
6008
6009 class AnalysisContextStatisticsImpl_PartitionDataImpl implements AnalysisContext Statistics_PartitionData {
6010 final int astCount;
6011
6012 final int totalCount;
6013
6014 AnalysisContextStatisticsImpl_PartitionDataImpl(this.astCount, this.totalCount );
6015 }
6016
6017 /**
6018 * Information about single piece of data in the cache.
6019 */
6020 abstract class AnalysisContextStatistics_CacheRow {
6021 /**
6022 * Return the number of entries whose state is [CacheState#ERROR].
6023 */
6024 int get errorCount;
6025
6026 /**
6027 * Return the number of entries whose state is [CacheState#FLUSHED].
6028 */
6029 int get flushedCount;
6030
6031 /**
6032 * Return the number of entries whose state is [CacheState#IN_PROCESS].
6033 */
6034 int get inProcessCount;
6035
6036 /**
6037 * Return the number of entries whose state is [CacheState#INVALID].
6038 */
6039 int get invalidCount;
6040
6041 /**
6042 * Return the name of the data represented by this object.
6043 */
6044 String get name;
6045
6046 /**
6047 * Return the number of entries whose state is [CacheState#VALID].
6048 */
6049 int get validCount;
6050 }
6051
6052 /**
6053 * Information about a single partition in the cache.
6054 */
6055 abstract class AnalysisContextStatistics_PartitionData {
6056 /**
6057 * Return the number of entries in the partition that have an AST structure in one state or
6058 * another.
6059 */
6060 int get astCount;
6061
6062 /**
6063 * Return the total number of entries in the partition.
6064 */
6065 int get totalCount;
6066 }
6067
6068 /**
6069 * Instances of the class `AnalysisDelta` indicate changes to the types of analy sis that
6070 * should be performed.
6071 */
6072 class AnalysisDelta {
6073 /**
6074 * A mapping from source to what type of analysis should be performed on that source.
6075 */
6076 HashMap<Source, AnalysisLevel> _analysisMap = new HashMap<Source, AnalysisLeve l>();
6077
6078 /**
6079 * Return a collection of the sources that have been added. This is equivalent to calling
6080 * [getAnalysisLevels] and collecting all sources that do not have an analysis level of
6081 * [AnalysisLevel#NONE].
6082 *
6083 * @return a collection of the sources
6084 */
6085 Iterable<Source> get addedSources {
6086 List<Source> result = new List<Source>();
6087 for (MapEntry<Source, AnalysisLevel> entry in getMapEntrySet(_analysisMap)) {
6088 if (entry.getValue() != AnalysisLevel.NONE) {
6089 result.add(entry.getKey());
6090 }
6091 }
6092 return result;
6093 }
6094
6095 /**
6096 * Return a mapping of sources to the level of analysis that should be perform ed.
6097 *
6098 * @return the analysis map
6099 */
6100 Map<Source, AnalysisLevel> get analysisLevels => _analysisMap;
6101
6102 /**
6103 * Record that the specified source should be analyzed at the specified level.
6104 *
6105 * @param source the source
6106 * @param level the level at which the given source should be analyzed
6107 */
6108 void setAnalysisLevel(Source source, AnalysisLevel level) {
6109 _analysisMap[source] = level;
6110 }
6111
6112 @override
6113 String toString() {
6114 JavaStringBuilder builder = new JavaStringBuilder();
6115 bool needsSeparator = _appendSources(builder, false, AnalysisLevel.ALL);
6116 needsSeparator = _appendSources(builder, needsSeparator, AnalysisLevel.RESOL VED);
6117 _appendSources(builder, needsSeparator, AnalysisLevel.NONE);
6118 return builder.toString();
6119 }
6120
6121 /**
6122 * Append sources with the given analysis level, prefixed with a label and pos sibly a separator.
6123 *
6124 * @param builder the builder to which the sources are to be appended
6125 * @param needsSeparator `true` if a separator is needed before the label
6126 * @param level the analysis level of the sources to be appended
6127 * @return `true` if future lists of sources will need a separator
6128 */
6129 bool _appendSources(JavaStringBuilder builder, bool needsSeparator, AnalysisLe vel level) {
6130 bool first = true;
6131 for (MapEntry<Source, AnalysisLevel> entry in getMapEntrySet(_analysisMap)) {
6132 if (entry.getValue() == level) {
6133 if (first) {
6134 first = false;
6135 if (needsSeparator) {
6136 builder.append("; ");
6137 }
6138 builder.append(level);
6139 builder.append(" ");
6140 } else {
6141 builder.append(", ");
6142 }
6143 builder.append(entry.getKey().fullName);
6144 }
6145 }
6146 return needsSeparator || !first;
6147 }
6148 }
6149
6150 /**
6151 * The unique instance of the class `AnalysisEngine` serves as the entry point f or the
6152 * functionality provided by the analysis engine.
6153 */
6154 class AnalysisEngine {
6155 /**
6156 * The suffix used for Dart source files.
6157 */
6158 static String SUFFIX_DART = "dart";
6159
6160 /**
6161 * The short suffix used for HTML files.
6162 */
6163 static String SUFFIX_HTM = "htm";
6164
6165 /**
6166 * The long suffix used for HTML files.
6167 */
6168 static String SUFFIX_HTML = "html";
6169
6170 /**
6171 * The unique instance of this class.
6172 */
6173 static AnalysisEngine _UniqueInstance = new AnalysisEngine();
6174
6175 /**
6176 * Return the unique instance of this class.
6177 *
6178 * @return the unique instance of this class
6179 */
6180 static AnalysisEngine get instance => _UniqueInstance;
6181
6182 /**
6183 * Return `true` if the given file name is assumed to contain Dart source code .
6184 *
6185 * @param fileName the name of the file being tested
6186 * @return `true` if the given file name is assumed to contain Dart source cod e
6187 */
6188 static bool isDartFileName(String fileName) {
6189 if (fileName == null) {
6190 return false;
6191 }
6192 return javaStringEqualsIgnoreCase(FileNameUtilities.getExtension(fileName), SUFFIX_DART);
6193 }
6194
6195 /**
6196 * Return `true` if the given file name is assumed to contain HTML.
6197 *
6198 * @param fileName the name of the file being tested
6199 * @return `true` if the given file name is assumed to contain HTML
6200 */
6201 static bool isHtmlFileName(String fileName) {
6202 if (fileName == null) {
6203 return false;
6204 }
6205 String extension = FileNameUtilities.getExtension(fileName);
6206 return javaStringEqualsIgnoreCase(extension, SUFFIX_HTML) || javaStringEqual sIgnoreCase(extension, SUFFIX_HTM);
6207 }
6208
6209 /**
6210 * The logger that should receive information about errors within the analysis engine.
6211 */
6212 Logger _logger = Logger.NULL;
6213
6214 /**
6215 * The partition manager being used to manage the shared partitions.
6216 */
6217 final PartitionManager partitionManager = new PartitionManager();
6218
6219 /**
6220 * Create a new context in which analysis can be performed.
6221 *
6222 * @return the analysis context that was created
6223 */
6224 AnalysisContext createAnalysisContext() {
6225 //
6226 // If instrumentation is ignoring data, return an uninstrumented analysis co ntext.
6227 //
6228 if (Instrumentation.isNullLogger) {
6229 return new AnalysisContextImpl();
6230 }
6231 return new InstrumentedAnalysisContextImpl.con1(new AnalysisContextImpl());
6232 }
6233
6234 /**
6235 * Return the logger that should receive information about errors within the a nalysis engine.
6236 *
6237 * @return the logger that should receive information about errors within the analysis engine
6238 */
6239 Logger get logger => _logger;
6240
6241 /**
6242 * Set the logger that should receive information about errors within the anal ysis engine to the
6243 * given logger.
6244 *
6245 * @param logger the logger that should receive information about errors withi n the analysis
6246 * engine
6247 */
6248 void set logger(Logger logger) {
6249 this._logger = logger == null ? Logger.NULL : logger;
6250 }
6251 }
6252
6253 /**
6254 * The interface `AnalysisErrorInfo` contains the analysis errors and line infor mation for the
6255 * errors.
6256 */
6257 abstract class AnalysisErrorInfo {
6258 /**
6259 * Return the errors that as a result of the analysis, or `null` if there were no errors.
6260 *
6261 * @return the errors as a result of the analysis
6262 */
6263 List<AnalysisError> get errors;
6264
6265 /**
6266 * Return the line information associated with the errors, or `null` if there were no
6267 * errors.
6268 *
6269 * @return the line information associated with the errors
6270 */
6271 LineInfo get lineInfo;
6272 }
6273
6274 /**
6275 * Instances of the class `AnalysisErrorInfoImpl` represent the analysis errors and line info
6276 * associated with a source.
6277 */
6278 class AnalysisErrorInfoImpl implements AnalysisErrorInfo {
6279 /**
6280 * The analysis errors associated with a source, or `null` if there are no err ors.
6281 */
6282 final List<AnalysisError> errors;
6283
6284 /**
6285 * The line information associated with the errors, or `null` if there are no errors.
6286 */
6287 final LineInfo lineInfo;
6288
6289 /**
6290 * Initialize an newly created error info with the errors and line information
6291 *
6292 * @param errors the errors as a result of analysis
6293 * @param lineinfo the line info for the errors
6294 */
6295 AnalysisErrorInfoImpl(this.errors, this.lineInfo);
6296 }
6297
6298 /**
6299 * The enumeration `AnalysisLevel` encodes the different levels at which a sourc e can be
6300 * analyzed.
6301 */
6302 class AnalysisLevel extends Enum<AnalysisLevel> {
6303 /**
6304 * Indicates a source should be fully analyzed.
6305 */
6306 static const AnalysisLevel ALL = const AnalysisLevel('ALL', 0);
6307
6308 /**
6309 * Indicates a source should be resolved and that errors, warnings and hints a re needed.
6310 */
6311 static const AnalysisLevel ERRORS = const AnalysisLevel('ERRORS', 1);
6312
6313 /**
6314 * Indicates a source should be resolved, but that errors, warnings and hints are not needed.
6315 */
6316 static const AnalysisLevel RESOLVED = const AnalysisLevel('RESOLVED', 2);
6317
6318 /**
6319 * Indicates a source is not of interest to the client.
6320 */
6321 static const AnalysisLevel NONE = const AnalysisLevel('NONE', 3);
6322
6323 static const List<AnalysisLevel> values = const [ALL, ERRORS, RESOLVED, NONE];
6324
6325 const AnalysisLevel(String name, int ordinal) : super(name, ordinal);
6326 }
6327
6328 /**
6329 * The interface `AnalysisListener` defines the behavior of objects that are lis tening for
6330 * results being produced by an analysis context.
6331 */
6332 abstract class AnalysisListener {
6333 /**
6334 * Reports that a task is about to be performed by the given context.
6335 *
6336 * @param context the context in which the task is to be performed
6337 * @param taskDescription a human readable description of the task that is abo ut to be performed
6338 */
6339 void aboutToPerformTask(AnalysisContext context, String taskDescription);
6340
6341 /**
6342 * Reports that the errors associated with the given source in the given conte xt has been updated
6343 * to the given errors.
6344 *
6345 * @param context the context in which the new list of errors was produced
6346 * @param source the source containing the errors that were computed
6347 * @param errors the errors that were computed
6348 * @param lineInfo the line information associated with the source
6349 */
6350 void computedErrors(AnalysisContext context, Source source, List<AnalysisError > errors, LineInfo lineInfo);
6351
6352 /**
6353 * Reports that the given source is no longer included in the set of sources t hat are being
6354 * analyzed by the given analysis context.
6355 *
6356 * @param context the context in which the source is being analyzed
6357 * @param source the source that is no longer being analyzed
6358 */
6359 void excludedSource(AnalysisContext context, Source source);
6360
6361 /**
6362 * Reports that the given source is now included in the set of sources that ar e being analyzed by
6363 * the given analysis context.
6364 *
6365 * @param context the context in which the source is being analyzed
6366 * @param source the source that is now being analyzed
6367 */
6368 void includedSource(AnalysisContext context, Source source);
6369
6370 /**
6371 * Reports that the given Dart source was parsed in the given context.
6372 *
6373 * @param context the context in which the source was parsed
6374 * @param source the source that was parsed
6375 * @param unit the result of parsing the source in the given context
6376 */
6377 void parsedDart(AnalysisContext context, Source source, CompilationUnit unit);
6378
6379 /**
6380 * Reports that the given HTML source was parsed in the given context.
6381 *
6382 * @param context the context in which the source was parsed
6383 * @param source the source that was parsed
6384 * @param unit the result of parsing the source in the given context
6385 */
6386 void parsedHtml(AnalysisContext context, Source source, ht.HtmlUnit unit);
6387
6388 /**
6389 * Reports that the given Dart source was resolved in the given context.
6390 *
6391 * @param context the context in which the source was resolved
6392 * @param source the source that was resolved
6393 * @param unit the result of resolving the source in the given context
6394 */
6395 void resolvedDart(AnalysisContext context, Source source, CompilationUnit unit );
6396
6397 /**
6398 * Reports that the given HTML source was resolved in the given context.
6399 *
6400 * @param context the context in which the source was resolved
6401 * @param source the source that was resolved
6402 * @param unit the result of resolving the source in the given context
6403 */
6404 void resolvedHtml(AnalysisContext context, Source source, ht.HtmlUnit unit);
6405 }
6406
6407 /**
6408 * The interface `AnalysisOptions` defines the behavior of objects that provide access to a
6409 * set of analysis options used to control the behavior of an analysis context.
6410 */
6411 abstract class AnalysisOptions {
6412 /**
6413 * Return `true` if analysis is to analyze Angular.
6414 *
6415 * @return `true` if analysis is to analyze Angular
6416 */
6417 bool get analyzeAngular;
6418
6419 /**
6420 * Return `true` if analysis is to parse and analyze function bodies.
6421 *
6422 * @return `true` if analysis is to parse and analyzer function bodies
6423 */
6424 bool get analyzeFunctionBodies;
6425
6426 /**
6427 * Return `true` if analysis is to analyze Polymer.
6428 *
6429 * @return `true` if analysis is to analyze Polymer
6430 */
6431 bool get analyzePolymer;
6432
6433 /**
6434 * Return the maximum number of sources for which AST structures should be kep t in the cache.
6435 *
6436 * @return the maximum number of sources for which AST structures should be ke pt in the cache
6437 */
6438 int get cacheSize;
6439
6440 /**
6441 * Return `true` if analysis is to generate dart2js related hint results.
6442 *
6443 * @return `true` if analysis is to generate dart2js related hint results
6444 */
6445 bool get dart2jsHint;
6446
6447 /**
6448 * Return `true` if analysis is to include the new async support.
6449 *
6450 * @return `true` if analysis is to include the new async support
6451 */
6452 bool get enableAsync;
6453
6454 /**
6455 * Return `true` if analysis is to include the new deferred loading support.
6456 *
6457 * @return `true` if analysis is to include the new deferred loading support
6458 */
6459 bool get enableDeferredLoading;
6460
6461 /**
6462 * Return `true` if analysis is to include the new enum support.
6463 *
6464 * @return `true` if analysis is to include the new enum support
6465 */
6466 bool get enableEnum;
6467
6468 /**
6469 * Return `true` if errors, warnings and hints should be generated for sources in the SDK.
6470 * The default value is `false`.
6471 *
6472 * @return `true` if errors, warnings and hints should be generated for the SD K
6473 */
6474 bool get generateSdkErrors;
6475
6476 /**
6477 * Return `true` if analysis is to generate hint results (e.g. type inference based
6478 * information and pub best practices).
6479 *
6480 * @return `true` if analysis is to generate hint results
6481 */
6482 bool get hint;
6483
6484 /**
6485 * Return `true` if incremental analysis should be used.
6486 *
6487 * @return `true` if incremental analysis should be used
6488 */
6489 bool get incremental;
6490
6491 /**
6492 * Return `true` if analysis is to parse comments.
6493 *
6494 * @return `true` if analysis is to parse comments
6495 */
6496 bool get preserveComments;
6497 }
6498
6499 /**
6500 * Instances of the class `AnalysisOptions` represent a set of analysis options used to
6501 * control the behavior of an analysis context.
6502 */
6503 class AnalysisOptionsImpl implements AnalysisOptions {
6504 /**
6505 * The maximum number of sources for which data should be kept in the cache.
6506 */
6507 static int DEFAULT_CACHE_SIZE = 64;
6508
6509 /**
6510 * The default value for enabling async support.
6511 */
6512 static bool DEFAULT_ENABLE_ASYNC = false;
6513
6514 /**
6515 * The default value for enabling deferred loading.
6516 */
6517 static bool DEFAULT_ENABLE_DEFERRED_LOADING = true;
6518
6519 /**
6520 * The default value for enabling enum support.
6521 */
6522 static bool DEFAULT_ENABLE_ENUM = false;
6523
6524 /**
6525 * A flag indicating whether analysis is to analyze Angular.
6526 */
6527 bool analyzeAngular = true;
6528
6529 /**
6530 * A flag indicating whether analysis is to parse and analyze function bodies.
6531 */
6532 bool analyzeFunctionBodies = true;
6533
6534 /**
6535 * A flag indicating whether analysis is to analyze Polymer.
6536 */
6537 bool analyzePolymer = true;
6538
6539 /**
6540 * The maximum number of sources for which AST structures should be kept in th e cache.
6541 */
6542 int cacheSize = DEFAULT_CACHE_SIZE;
6543
6544 /**
6545 * A flag indicating whether analysis is to generate dart2js related hint resu lts.
6546 */
6547 bool dart2jsHint = true;
6548
6549 /**
6550 * A flag indicating whether analysis is to enable async support.
6551 */
6552 bool enableAsync = DEFAULT_ENABLE_ASYNC;
6553
6554 /**
6555 * A flag indicating whether analysis is to enable deferred loading.
6556 */
6557 bool enableDeferredLoading = DEFAULT_ENABLE_DEFERRED_LOADING;
6558
6559 /**
6560 * A flag indicating whether analysis is to enable enum support.
6561 */
6562 bool enableEnum = DEFAULT_ENABLE_ENUM;
6563
6564 /**
6565 * A flag indicating whether errors, warnings and hints should be generated fo r sources in the
6566 * SDK.
6567 */
6568 bool _generateSdkErrors = false;
6569
6570 /**
6571 * A flag indicating whether analysis is to generate hint results (e.g. type i nference based
6572 * information and pub best practices).
6573 */
6574 bool hint = true;
6575
6576 /**
6577 * A flag indicating whether incremental analysis should be used.
6578 */
6579 bool incremental = false;
6580
6581 /**
6582 * A flag indicating whether analysis is to parse comments.
6583 */
6584 bool preserveComments = true;
6585
6586 /**
6587 * Initialize a newly created set of analysis options to have their default va lues.
6588 */
6589 AnalysisOptionsImpl();
6590
6591 /**
6592 * Initialize a newly created set of analysis options to have the same values as those in the
6593 * given set of analysis options.
6594 *
6595 * @param options the analysis options whose values are being copied
6596 */
6597 AnalysisOptionsImpl.con1(AnalysisOptions options) {
6598 analyzeAngular = options.analyzeAngular;
6599 analyzeFunctionBodies = options.analyzeFunctionBodies;
6600 analyzePolymer = options.analyzePolymer;
6601 cacheSize = options.cacheSize;
6602 dart2jsHint = options.dart2jsHint;
6603 enableAsync = options.enableAsync;
6604 enableDeferredLoading = options.enableDeferredLoading;
6605 enableEnum = options.enableEnum;
6606 _generateSdkErrors = options.generateSdkErrors;
6607 hint = options.hint;
6608 incremental = options.incremental;
6609 preserveComments = options.preserveComments;
6610 }
6611
6612 @override
6613 bool get generateSdkErrors => _generateSdkErrors;
6614
6615 /**
6616 * Set whether errors, warnings and hints should be generated for sources in t he SDK to match the
6617 * given value.
6618 *
6619 * @param generate `true` if errors, warnings and hints should be generated fo r sources in
6620 * the SDK
6621 */
6622 void set generateSdkErrors(bool generate) {
6623 _generateSdkErrors = generate;
6624 }
6625 }
6626
6627 /**
6628 * Instances of the class `AnalysisResult`
6629 */
6630 class AnalysisResult {
6631 /**
6632 * The change notices associated with this result, or `null` if there were no changes and
6633 * there is no more work to be done.
6634 */
6635 final List<ChangeNotice> _notices;
6636
6637 /**
6638 * The number of milliseconds required to determine which task was to be perfo rmed.
6639 */
6640 final int getTime;
6641
6642 /**
6643 * The name of the class of the task that was performed.
6644 */
6645 final String taskClassName;
6646
6647 /**
6648 * The number of milliseconds required to perform the task.
6649 */
6650 final int performTime;
6651
6652 /**
6653 * Initialize a newly created analysis result to have the given values.
6654 *
6655 * @param notices the change notices associated with this result
6656 * @param getTime the number of milliseconds required to determine which task was to be performed
6657 * @param taskClassName the name of the class of the task that was performed
6658 * @param performTime the number of milliseconds required to perform the task
6659 */
6660 AnalysisResult(this._notices, this.getTime, this.taskClassName, this.performTi me);
6661
6662 /**
6663 * Return the change notices associated with this result, or `null` if there w ere no changes
6664 * and there is no more work to be done.
6665 *
6666 * @return the change notices associated with this result
6667 */
6668 List<ChangeNotice> get changeNotices => _notices;
6669
6670 /**
6671 * Return `true` if there is more to be performed after the task that was perf ormed.
6672 *
6673 * @return `true` if there is more to be performed after the task that was per formed
6674 */
6675 bool get hasMoreWork => _notices != null;
6676 }
6677
6678 /**
6679 * The abstract class `AnalysisTask` defines the behavior of objects used to per form an
6680 * analysis task.
6681 */
6682 abstract class AnalysisTask {
6683 /**
6684 * The context in which the task is to be performed.
6685 */
6686 final InternalAnalysisContext context;
6687
6688 /**
6689 * The exception that was thrown while performing this task, or `null` if the task completed
6690 * successfully.
6691 */
6692 CaughtException _thrownException;
6693
6694 /**
6695 * Initialize a newly created task to perform analysis within the given contex t.
6696 *
6697 * @param context the context in which the task is to be performed
6698 */
6699 AnalysisTask(this.context);
6700
6701 /**
6702 * Use the given visitor to visit this task.
6703 *
6704 * @param visitor the visitor that should be used to visit this task
6705 * @return the value returned by the visitor
6706 * @throws AnalysisException if the visitor throws the exception
6707 */
6708 accept(AnalysisTaskVisitor visitor);
6709
6710 /**
6711 * Return the exception that was thrown while performing this task, or `null` if the task
6712 * completed successfully.
6713 *
6714 * @return the exception that was thrown while performing this task
6715 */
6716 CaughtException get exception => _thrownException;
6717
6718 /**
6719 * Perform this analysis task and use the given visitor to visit this task aft er it has completed.
6720 *
6721 * @param visitor the visitor used to visit this task after it has completed
6722 * @return the value returned by the visitor
6723 * @throws AnalysisException if the visitor throws the exception
6724 */
6725 Object perform(AnalysisTaskVisitor visitor) {
6726 try {
6727 _safelyPerform();
6728 } on AnalysisException catch (exception, stackTrace) {
6729 _thrownException = new CaughtException(exception, stackTrace);
6730 AnalysisEngine.instance.logger.logInformation2("Task failed: ${taskDescrip tion}", new CaughtException(exception, stackTrace));
6731 }
6732 return accept(visitor);
6733 }
6734
6735 @override
6736 String toString() => taskDescription;
6737
6738 /**
6739 * Return a textual description of this task.
6740 *
6741 * @return a textual description of this task
6742 */
6743 String get taskDescription;
6744
6745 /**
6746 * Perform this analysis task, protected by an exception handler.
6747 *
6748 * @throws AnalysisException if an exception occurs while performing the task
6749 */
6750 void internalPerform();
6751
6752 /**
6753 * Perform this analysis task, ensuring that all exceptions are wrapped in an
6754 * [AnalysisException].
6755 *
6756 * @throws AnalysisException if any exception occurs while performing the task
6757 */
6758 void _safelyPerform() {
6759 try {
6760 internalPerform();
6761 } on AnalysisException catch (exception) {
6762 throw exception;
6763 } catch (exception, stackTrace) {
6764 throw new AnalysisException("Exception", new CaughtException(exception, st ackTrace));
6765 }
6766 }
6767 }
6768
6769 /**
6770 * The interface `AnalysisTaskVisitor` defines the behavior of objects that can visit tasks.
6771 * While tasks are not structured in any interesting way, this class provides th e ability to
6772 * dispatch to an appropriate method.
6773 */
6774 abstract class AnalysisTaskVisitor<E> {
6775 /**
6776 * Visit a [GenerateDartErrorsTask].
6777 *
6778 * @param task the task to be visited
6779 * @return the result of visiting the task
6780 * @throws AnalysisException if the visitor throws an exception for some reaso n
6781 */
6782 E visitGenerateDartErrorsTask(GenerateDartErrorsTask task);
6783
6784 /**
6785 * Visit a [GenerateDartHintsTask].
6786 *
6787 * @param task the task to be visited
6788 * @return the result of visiting the task
6789 * @throws AnalysisException if the visitor throws an exception for some reaso n
6790 */
6791 E visitGenerateDartHintsTask(GenerateDartHintsTask task);
6792
6793 /**
6794 * Visit a [GetContentTask].
6795 *
6796 * @param task the task to be visited
6797 * @return the result of visiting the task
6798 * @throws AnalysisException if the visitor throws an exception for some reaso n
6799 */
6800 E visitGetContentTask(GetContentTask task);
6801
6802 /**
6803 * Visit an [IncrementalAnalysisTask].
6804 *
6805 * @param task the task to be visited
6806 * @return the result of visiting the task
6807 * @throws AnalysisException if the visitor throws an exception for some reaso n
6808 */
6809 E visitIncrementalAnalysisTask(IncrementalAnalysisTask incrementalAnalysisTask );
6810
6811 /**
6812 * Visit a [ParseDartTask].
6813 *
6814 * @param task the task to be visited
6815 * @return the result of visiting the task
6816 * @throws AnalysisException if the visitor throws an exception for some reaso n
6817 */
6818 E visitParseDartTask(ParseDartTask task);
6819
6820 /**
6821 * Visit a [ParseHtmlTask].
6822 *
6823 * @param task the task to be visited
6824 * @return the result of visiting the task
6825 * @throws AnalysisException if the visitor throws an exception for some reaso n
6826 */
6827 E visitParseHtmlTask(ParseHtmlTask task);
6828
6829 /**
6830 * Visit a [PolymerBuildHtmlTask].
6831 *
6832 * @param task the task to be visited
6833 * @return the result of visiting the task
6834 * @throws AnalysisException if the visitor throws an exception for some reaso n
6835 */
6836 E visitPolymerBuildHtmlTask(PolymerBuildHtmlTask task);
6837
6838 /**
6839 * Visit a [PolymerResolveHtmlTask].
6840 *
6841 * @param task the task to be visited
6842 * @return the result of visiting the task
6843 * @throws AnalysisException if the visitor throws an exception for some reaso n
6844 */
6845 E visitPolymerResolveHtmlTask(PolymerResolveHtmlTask task);
6846
6847 /**
6848 * Visit a [ResolveAngularComponentTemplateTask].
6849 *
6850 * @param task the task to be visited
6851 * @return the result of visiting the task
6852 * @throws AnalysisException if the visitor throws an exception for some reaso n
6853 */
6854 E visitResolveAngularComponentTemplateTask(ResolveAngularComponentTemplateTask task);
6855
6856 /**
6857 * Visit a [ResolveAngularEntryHtmlTask].
6858 *
6859 * @param task the task to be visited
6860 * @return the result of visiting the task
6861 * @throws AnalysisException if the visitor throws an exception for some reaso n
6862 */
6863 E visitResolveAngularEntryHtmlTask(ResolveAngularEntryHtmlTask task);
6864
6865 /**
6866 * Visit a [ResolveDartLibraryCycleTask].
6867 *
6868 * @param task the task to be visited
6869 * @return the result of visiting the task
6870 * @throws AnalysisException if the visitor throws an exception for some reaso n
6871 */
6872 E visitResolveDartLibraryCycleTask(ResolveDartLibraryCycleTask task);
6873
6874 /**
6875 * Visit a [ResolveDartLibraryTask].
6876 *
6877 * @param task the task to be visited
6878 * @return the result of visiting the task
6879 * @throws AnalysisException if the visitor throws an exception for some reaso n
6880 */
6881 E visitResolveDartLibraryTask(ResolveDartLibraryTask task);
6882
6883 /**
6884 * Visit a [ResolveDartUnitTask].
6885 *
6886 * @param task the task to be visited
6887 * @return the result of visiting the task
6888 * @throws AnalysisException if the visitor throws an exception for some reaso n
6889 */
6890 E visitResolveDartUnitTask(ResolveDartUnitTask task);
6891
6892 /**
6893 * Visit a [ResolveHtmlTask].
6894 *
6895 * @param task the task to be visited
6896 * @return the result of visiting the task
6897 * @throws AnalysisException if the visitor throws an exception for some reaso n
6898 */
6899 E visitResolveHtmlTask(ResolveHtmlTask task);
6900
6901 /**
6902 * Visit a [ScanDartTask].
6903 *
6904 * @param task the task to be visited
6905 * @return the result of visiting the task
6906 * @throws AnalysisException if the visitor throws an exception for some reaso n
6907 */
6908 E visitScanDartTask(ScanDartTask task);
6909 }
6910
6911 /**
6912 * An [Expression] with optional [AngularFormatterNode]s.
6913 */
6914 class AngularExpression {
6915 /**
6916 * The [Expression] to apply formatters to.
6917 */
6918 final Expression expression;
6919
6920 /**
6921 * The formatters to apply.
6922 */
6923 final List<AngularFormatterNode> formatters;
6924
6925 AngularExpression(this.expression, this.formatters);
6926
6927 /**
6928 * Return the offset of the character immediately following the last character of this node's
6929 * source range. This is equivalent to `node.getOffset() + node.getLength()`.
6930 *
6931 * @return the offset of the character just past the node's source range
6932 */
6933 int get end {
6934 if (formatters.isEmpty) {
6935 return expression.end;
6936 }
6937 AngularFormatterNode lastFormatter = formatters[formatters.length - 1];
6938 List<AngularFormatterArgument> formatterArguments = lastFormatter.arguments;
6939 if (formatterArguments.isEmpty) {
6940 return lastFormatter.name.end;
6941 }
6942 return formatterArguments[formatterArguments.length - 1].expression.end;
6943 }
6944
6945 /**
6946 * Return Dart [Expression]s this Angular expression consists of.
6947 */
6948 List<Expression> get expressions {
6949 List<Expression> expressions = [];
6950 expressions.add(expression);
6951 for (AngularFormatterNode formatter in formatters) {
6952 expressions.add(formatter.name);
6953 for (AngularFormatterArgument formatterArgument in formatter.arguments) {
6954 expressions.addAll(formatterArgument.subExpressions);
6955 expressions.add(formatterArgument.expression);
6956 }
6957 }
6958 return expressions;
6959 }
6960
6961 /**
6962 * Return the number of characters in the expression's source range.
6963 */
6964 int get length => end - offset;
6965
6966 /**
6967 * Return the offset of the first character in the expression's source range.
6968 */
6969 int get offset => expression.offset;
6970 }
6971
6972 /**
6973 * Angular formatter argument.
6974 */
6975 class AngularFormatterArgument {
6976 /**
6977 * The [TokenType#COLON] token.
6978 */
6979 final Token token;
6980
6981 /**
6982 * The argument expression.
6983 */
6984 final Expression expression;
6985
6986 /**
6987 * The optional sub-[Expression]s.
6988 */
6989 List<Expression> subExpressions = Expression.EMPTY_ARRAY;
6990
6991 AngularFormatterArgument(this.token, this.expression);
6992 }
6993
6994 /**
6995 * Angular formatter node.
6996 */
6997 class AngularFormatterNode {
6998 /**
6999 * The [TokenType#BAR] token.
7000 */
7001 final Token token;
7002
7003 /**
7004 * The name of the formatter.
7005 */
7006 final SimpleIdentifier name;
7007
7008 /**
7009 * The arguments for this formatter.
7010 */
7011 final List<AngularFormatterArgument> arguments;
7012
7013 AngularFormatterNode(this.token, this.name, this.arguments);
7014 }
7015
7016 /**
7017 * Instances of the class [AngularHtmlUnitResolver] resolve Angular specific exp ressions.
7018 */
7019 class AngularHtmlUnitResolver extends ht.RecursiveXmlVisitor<Object> {
7020 static String _NG_APP = "ng-app";
7021
7022 /**
7023 * Checks if given [Element] is an artificial local variable and returns corre sponding
7024 * [AngularElement], or `null` otherwise.
7025 */
7026 static AngularElement getAngularElement(Element element) {
7027 // may be artificial local variable, replace with AngularElement
7028 if (element is LocalVariableElement) {
7029 LocalVariableElement local = element;
7030 List<ToolkitObjectElement> toolkitObjects = local.toolkitObjects;
7031 if (toolkitObjects.length == 1 && toolkitObjects[0] is AngularElement) {
7032 return toolkitObjects[0] as AngularElement;
7033 }
7034 }
7035 // not a special Element
7036 return null;
7037 }
7038
7039 /**
7040 * @return `true` if the given [HtmlUnit] has <code>ng-app</code> annotation.
7041 */
7042 static bool hasAngularAnnotation(ht.HtmlUnit htmlUnit) {
7043 try {
7044 htmlUnit.accept(new RecursiveXmlVisitor_AngularHtmlUnitResolver_hasAngular Annotation());
7045 } on AngularHtmlUnitResolver_FoundAppError catch (e) {
7046 return true;
7047 }
7048 return false;
7049 }
7050
7051 static SimpleIdentifier _createIdentifier(String name, int offset) {
7052 StringToken token = _createStringToken(name, offset);
7053 return new SimpleIdentifier(token);
7054 }
7055
7056 /**
7057 * Adds [AngularElement] declared by the given top-level [Element].
7058 *
7059 * @param angularElements the list to fill with top-level [AngularElement]s
7060 * @param classElement the [ClassElement] to get [AngularElement]s from
7061 */
7062 static void _addAngularElementsFromClass(Set<AngularElement> angularElements, ClassElement classElement) {
7063 for (ToolkitObjectElement toolkitObject in classElement.toolkitObjects) {
7064 if (toolkitObject is AngularElement) {
7065 angularElements.add(toolkitObject);
7066 }
7067 }
7068 }
7069
7070 /**
7071 * Returns the array of all top-level Angular elements that could be used in t his library.
7072 *
7073 * @param libraryElement the [LibraryElement] to analyze
7074 * @return the array of all top-level Angular elements that could be used in t his library
7075 */
7076 static void _addAngularElementsFromLibrary(Set<AngularElement> angularElements , LibraryElement library, Set<LibraryElement> visited) {
7077 if (library == null) {
7078 return;
7079 }
7080 if (!visited.add(library)) {
7081 return;
7082 }
7083 // add Angular elements from current library
7084 for (CompilationUnitElement unit in library.units) {
7085 angularElements.addAll(unit.angularViews);
7086 for (ClassElement type in unit.types) {
7087 _addAngularElementsFromClass(angularElements, type);
7088 }
7089 }
7090 // handle imports
7091 for (ImportElement importElement in library.imports) {
7092 LibraryElement importedLibrary = importElement.importedLibrary;
7093 _addAngularElementsFromLibrary(angularElements, importedLibrary, visited);
7094 }
7095 }
7096
7097 static StringToken _createStringToken(String name, int offset) => new StringTo ken(TokenType.IDENTIFIER, name, offset);
7098
7099 /**
7100 * Returns the array of all top-level Angular elements that could be used in t his library.
7101 *
7102 * @param libraryElement the [LibraryElement] to analyze
7103 * @return the array of all top-level Angular elements that could be used in t his library
7104 */
7105 static List<AngularElement> _getAngularElements(Set<LibraryElement> libraries, LibraryElement libraryElement) {
7106 Set<AngularElement> angularElements = new Set();
7107 _addAngularElementsFromLibrary(angularElements, libraryElement, libraries);
7108 return new List.from(angularElements);
7109 }
7110
7111 /**
7112 * Returns the external Dart [CompilationUnit] referenced by the given [HtmlUn it].
7113 */
7114 static CompilationUnit _getDartUnit(AnalysisContext context, ht.HtmlUnit unit) {
7115 for (HtmlScriptElement script in unit.element.scripts) {
7116 if (script is ExternalHtmlScriptElement) {
7117 Source scriptSource = script.scriptSource;
7118 if (scriptSource != null) {
7119 return context.resolveCompilationUnit2(scriptSource, scriptSource);
7120 }
7121 }
7122 }
7123 return null;
7124 }
7125
7126 static Set<Source> _getLibrarySources(Set<LibraryElement> libraries) {
7127 Set<Source> sources = new Set();
7128 for (LibraryElement library in libraries) {
7129 sources.add(library.source);
7130 }
7131 return sources;
7132 }
7133
7134 final InternalAnalysisContext _context;
7135
7136 TypeProvider _typeProvider;
7137
7138 AngularHtmlUnitResolver_FilteringAnalysisErrorListener _errorListener;
7139
7140 final Source _source;
7141
7142 final LineInfo _lineInfo;
7143
7144 final ht.HtmlUnit _unit;
7145
7146 List<AngularElement> _angularElements;
7147
7148 List<NgProcessor> _processors = [];
7149
7150 LibraryElementImpl _libraryElement;
7151
7152 CompilationUnitElementImpl _unitElement;
7153
7154 FunctionElementImpl _functionElement;
7155
7156 ResolverVisitor _resolver;
7157
7158 bool _isAngular = false;
7159
7160 List<LocalVariableElementImpl> _definedVariables = [];
7161
7162 Set<LibraryElement> _injectedLibraries = new Set();
7163
7164 Scope _topNameScope;
7165
7166 Scope _nameScope;
7167
7168 AngularHtmlUnitResolver(this._context, AnalysisErrorListener errorListener, th is._source, this._lineInfo, this._unit) {
7169 this._typeProvider = _context.typeProvider;
7170 this._errorListener = new AngularHtmlUnitResolver_FilteringAnalysisErrorList ener(errorListener);
7171 }
7172
7173 /**
7174 * The [AngularApplication] for the Web application with this entry point, may be
7175 * `null` if not an entry point.
7176 */
7177 AngularApplication calculateAngularApplication() {
7178 // check if Angular at all
7179 if (!hasAngularAnnotation(_unit)) {
7180 return null;
7181 }
7182 // prepare resolved Dart unit
7183 CompilationUnit dartUnit = _getDartUnit(_context, _unit);
7184 if (dartUnit == null) {
7185 return null;
7186 }
7187 // prepare accessible Angular elements
7188 LibraryElement libraryElement = dartUnit.element.library;
7189 Set<LibraryElement> libraries = new Set();
7190 List<AngularElement> angularElements = _getAngularElements(libraries, librar yElement);
7191 // resolve AngularComponentElement template URIs
7192 // TODO(scheglov) resolve to HtmlElement to allow F3 ?
7193 Set<Source> angularElementsSources = new Set();
7194 for (AngularElement angularElement in angularElements) {
7195 if (angularElement is AngularHasTemplateElement) {
7196 AngularHasTemplateElement hasTemplate = angularElement;
7197 angularElementsSources.add(angularElement.source);
7198 String templateUri = hasTemplate.templateUri;
7199 if (templateUri == null) {
7200 continue;
7201 }
7202 try {
7203 Source templateSource = _context.sourceFactory.forUri2(_source.resolve RelativeUri(parseUriWithException(templateUri)));
7204 if (!_context.exists(templateSource)) {
7205 templateSource = _context.sourceFactory.resolveUri(_source, "package :${templateUri}");
7206 if (!_context.exists(templateSource)) {
7207 _errorListener.onError(new AnalysisError.con2(angularElement.sourc e, hasTemplate.templateUriOffset, templateUri.length, AngularCode.URI_DOES_NOT_E XIST, [templateUri]));
7208 continue;
7209 }
7210 }
7211 if (!AnalysisEngine.isHtmlFileName(templateUri)) {
7212 continue;
7213 }
7214 if (hasTemplate is AngularComponentElementImpl) {
7215 hasTemplate.templateSource = templateSource;
7216 }
7217 if (hasTemplate is AngularViewElementImpl) {
7218 hasTemplate.templateSource = templateSource;
7219 }
7220 } on URISyntaxException catch (exception) {
7221 _errorListener.onError(new AnalysisError.con2(angularElement.source, h asTemplate.templateUriOffset, templateUri.length, AngularCode.INVALID_URI, [temp lateUri]));
7222 }
7223 }
7224 }
7225 // create AngularApplication
7226 AngularApplication application = new AngularApplication(_source, _getLibrary Sources(libraries), angularElements, new List.from(angularElementsSources));
7227 // set AngularApplication for each AngularElement
7228 for (AngularElement angularElement in angularElements) {
7229 (angularElement as AngularElementImpl).application = application;
7230 }
7231 // done
7232 return application;
7233 }
7234
7235 /**
7236 * Resolves [source] as an [AngularComponentElement] template file.
7237 *
7238 * @param application the Angular application we are resolving for
7239 * @param component the [AngularComponentElement] to resolve template for, not `null`
7240 */
7241 void resolveComponentTemplate(AngularApplication application, AngularComponent Element component) {
7242 _isAngular = true;
7243 _resolveInternal(application.elements, component);
7244 }
7245
7246 /**
7247 * Resolves [source] as an Angular application entry point.
7248 */
7249 void resolveEntryPoint(AngularApplication application) {
7250 _resolveInternal(application.elements, null);
7251 }
7252
7253 @override
7254 Object visitXmlAttributeNode(ht.XmlAttributeNode node) {
7255 _parseEmbeddedExpressionsInAttribute(node);
7256 _resolveExpressions(node.expressions);
7257 return super.visitXmlAttributeNode(node);
7258 }
7259
7260 @override
7261 Object visitXmlTagNode(ht.XmlTagNode node) {
7262 bool wasAngular = _isAngular;
7263 try {
7264 // new Angular context
7265 if (node.getAttribute(_NG_APP) != null) {
7266 _isAngular = true;
7267 _visitModelDirectives(node);
7268 }
7269 // not Angular
7270 if (!_isAngular) {
7271 return super.visitXmlTagNode(node);
7272 }
7273 // process node in separate name scope
7274 _pushNameScope();
7275 try {
7276 _parseEmbeddedExpressionsInTag(node);
7277 // apply processors
7278 for (NgProcessor processor in _processors) {
7279 if (processor.canApply(node)) {
7280 processor.apply(this, node);
7281 }
7282 }
7283 // resolve expressions
7284 _resolveExpressions(node.expressions);
7285 // process children
7286 return super.visitXmlTagNode(node);
7287 } finally {
7288 _popNameScope();
7289 }
7290 } finally {
7291 _isAngular = wasAngular;
7292 }
7293 }
7294
7295 /**
7296 * Creates new [LocalVariableElementImpl] with given type and identifier.
7297 *
7298 * @param type the [Type] of the variable
7299 * @param identifier the identifier to create variable for
7300 * @return the new [LocalVariableElementImpl]
7301 */
7302 LocalVariableElementImpl _createLocalVariableFromIdentifier(DartType type, Sim pleIdentifier identifier) {
7303 LocalVariableElementImpl variable = new LocalVariableElementImpl.forNode(ide ntifier);
7304 _definedVariables.add(variable);
7305 variable.type = type;
7306 return variable;
7307 }
7308
7309 /**
7310 * Creates new [LocalVariableElementImpl] with given name and type.
7311 *
7312 * @param type the [Type] of the variable
7313 * @param name the name of the variable
7314 * @return the new [LocalVariableElementImpl]
7315 */
7316 LocalVariableElementImpl _createLocalVariableWithName(DartType type, String na me) {
7317 SimpleIdentifier identifier = _createIdentifier(name, 0);
7318 return _createLocalVariableFromIdentifier(type, identifier);
7319 }
7320
7321 /**
7322 * Declares the given [LocalVariableElementImpl] in the [topNameScope].
7323 */
7324 void _defineTopVariable(LocalVariableElementImpl variable) {
7325 _recordDefinedVariable(variable);
7326 _topNameScope.define(variable);
7327 _recordTypeLibraryInjected(variable);
7328 }
7329
7330 /**
7331 * Declares the given [LocalVariableElementImpl] in the current [nameScope].
7332 */
7333 void _defineVariable(LocalVariableElementImpl variable) {
7334 _recordDefinedVariable(variable);
7335 _nameScope.define(variable);
7336 _recordTypeLibraryInjected(variable);
7337 }
7338
7339 /**
7340 * @return the [AngularElement] with the given name, maybe `null`.
7341 */
7342 AngularElement _findAngularElement(String name) {
7343 for (AngularElement element in _angularElements) {
7344 if (name == element.name) {
7345 return element;
7346 }
7347 }
7348 return null;
7349 }
7350
7351 /**
7352 * @return the [TypeProvider] of the [AnalysisContext].
7353 */
7354 TypeProvider get typeProvider => _typeProvider;
7355
7356 /**
7357 * Parses given [String] as an [AngularExpression] at the given offset.
7358 */
7359 AngularExpression _parseAngularExpression(String contents, int startIndex, int endIndex, int offset) {
7360 Token token = _scanDart(contents, startIndex, endIndex, offset);
7361 return _parseAngularExpressionInToken(token);
7362 }
7363
7364 AngularExpression _parseAngularExpressionInToken(Token token) {
7365 List<Token> tokens = _splitAtBar(token);
7366 Expression mainExpression = _parseDartExpressionInToken(tokens[0]);
7367 // parse formatters
7368 List<AngularFormatterNode> formatters = [];
7369 for (int i = 1; i < tokens.length; i++) {
7370 Token formatterToken = tokens[i];
7371 Token barToken = formatterToken;
7372 formatterToken = formatterToken.next;
7373 // parse name
7374 Expression nameExpression = _parseDartExpressionInToken(formatterToken);
7375 if (nameExpression is! SimpleIdentifier) {
7376 _reportErrorForNode(AngularCode.INVALID_FORMATTER_NAME, nameExpression, []);
7377 continue;
7378 }
7379 SimpleIdentifier name = nameExpression as SimpleIdentifier;
7380 formatterToken = name.endToken.next;
7381 // parse arguments
7382 List<AngularFormatterArgument> arguments = [];
7383 while (formatterToken.type != TokenType.EOF) {
7384 // skip ":"
7385 Token colonToken = formatterToken;
7386 if (colonToken.type == TokenType.COLON) {
7387 formatterToken = formatterToken.next;
7388 } else {
7389 _reportErrorForToken(AngularCode.MISSING_FORMATTER_COLON, colonToken, []);
7390 }
7391 // parse argument
7392 Expression argument = _parseDartExpressionInToken(formatterToken);
7393 arguments.add(new AngularFormatterArgument(colonToken, argument));
7394 // next token
7395 formatterToken = argument.endToken.next;
7396 }
7397 formatters.add(new AngularFormatterNode(barToken, name, arguments));
7398 }
7399 // done
7400 return new AngularExpression(mainExpression, formatters);
7401 }
7402
7403 /**
7404 * Parses given [String] as an [Expression] at the given offset.
7405 */
7406 Expression _parseDartExpression(String contents, int startIndex, int endIndex, int offset) {
7407 Token token = _scanDart(contents, startIndex, endIndex, offset);
7408 return _parseDartExpressionInToken(token);
7409 }
7410
7411 Expression _parseDartExpressionInToken(Token token) {
7412 Parser parser = new Parser(_source, _errorListener);
7413 return parser.parseExpression(token);
7414 }
7415
7416 void _popNameScope() {
7417 _nameScope = _resolver.popNameScope();
7418 }
7419
7420 void _pushNameScope() {
7421 _nameScope = _resolver.pushNameScope();
7422 }
7423
7424 /**
7425 * Reports given [ErrorCode] at the given [AstNode].
7426 */
7427 void _reportErrorForNode(ErrorCode errorCode, AstNode node, List<Object> argum ents) {
7428 _reportErrorForOffset(errorCode, node.offset, node.length, arguments);
7429 }
7430
7431 /**
7432 * Reports given [ErrorCode] at the given position.
7433 */
7434 void _reportErrorForOffset(ErrorCode errorCode, int offset, int length, List<O bject> arguments) {
7435 _errorListener.onError(new AnalysisError.con2(_source, offset, length, error Code, arguments));
7436 }
7437
7438 /**
7439 * Reports given [ErrorCode] at the given [Token].
7440 */
7441 void _reportErrorForToken(ErrorCode errorCode, Token token, List<Object> argum ents) {
7442 _reportErrorForOffset(errorCode, token.offset, token.length, arguments);
7443 }
7444
7445 void _resolveExpression(AngularExpression angularExpression) {
7446 List<Expression> dartExpressions = angularExpression.expressions;
7447 for (Expression dartExpression in dartExpressions) {
7448 _resolveNode(dartExpression);
7449 }
7450 }
7451
7452 /**
7453 * Resolves given [AstNode] using [resolver].
7454 */
7455 void _resolveNode(AstNode node) {
7456 node.accept(_resolver);
7457 }
7458
7459 Token _scanDart(String contents, int startIndex, int endIndex, int offset) => ht.HtmlParser.scanDartSource(_source, _lineInfo, contents.substring(startIndex, endIndex), offset + startIndex, _errorListener);
7460
7461 /**
7462 * Puts into [libraryElement] an artificial [LibraryElementImpl] for this HTML
7463 * [Source].
7464 */
7465 void _createLibraryElement() {
7466 // create CompilationUnitElementImpl
7467 String unitName = _source.shortName;
7468 _unitElement = new CompilationUnitElementImpl(unitName);
7469 _unitElement.source = _source;
7470 // create LibraryElementImpl
7471 _libraryElement = new LibraryElementImpl.forNode(_context, null);
7472 _libraryElement.definingCompilationUnit = _unitElement;
7473 _libraryElement.angularHtml = true;
7474 _injectedLibraries.add(_libraryElement);
7475 // create FunctionElementImpl
7476 _functionElement = new FunctionElementImpl.forOffset(0);
7477 _unitElement.functions = <FunctionElement> [_functionElement];
7478 }
7479
7480 /**
7481 * Creates new [NgProcessor] for the given [AngularElement], maybe `null` if n ot
7482 * supported.
7483 */
7484 NgProcessor _createProcessor(AngularElement element) {
7485 if (element is AngularComponentElement) {
7486 AngularComponentElement component = element;
7487 return new NgComponentElementProcessor(component);
7488 }
7489 if (element is AngularControllerElement) {
7490 AngularControllerElement controller = element;
7491 return new NgControllerElementProcessor(controller);
7492 }
7493 if (element is AngularDecoratorElement) {
7494 AngularDecoratorElement directive = element;
7495 return new NgDecoratorElementProcessor(directive);
7496 }
7497 return null;
7498 }
7499
7500 /**
7501 * Puts into [resolver] an [ResolverVisitor] to resolve [Expression]s in
7502 * [source].
7503 */
7504 void _createResolver() {
7505 InheritanceManager inheritanceManager = new InheritanceManager(_libraryEleme nt);
7506 _resolver = new ResolverVisitor.con2(_libraryElement, _source, _typeProvider , inheritanceManager, _errorListener);
7507 _topNameScope = _resolver.pushNameScope();
7508 // add Scope variables - no type, no location, just to avoid warnings
7509 {
7510 DartType type = _typeProvider.dynamicType;
7511 _topNameScope.define(_createLocalVariableWithName(type, "\$id"));
7512 _topNameScope.define(_createLocalVariableWithName(type, "\$parent"));
7513 _topNameScope.define(_createLocalVariableWithName(type, "\$root"));
7514 }
7515 }
7516
7517 /**
7518 * Defines variable for the given [AngularElement] with type of the enclosing
7519 * [ClassElement].
7520 */
7521 void _defineTopVariable_forClassElement(AngularElement element) {
7522 ClassElement classElement = element.enclosingElement as ClassElement;
7523 InterfaceType type = classElement.type;
7524 LocalVariableElementImpl variable = _createLocalVariableWithName(type, eleme nt.name);
7525 _defineTopVariable(variable);
7526 variable.toolkitObjects = <AngularElement> [element];
7527 }
7528
7529 /**
7530 * Defines variable for the given [AngularScopePropertyElement].
7531 */
7532 void _defineTopVariable_forScopeProperty(AngularScopePropertyElement element) {
7533 DartType type = element.type;
7534 LocalVariableElementImpl variable = _createLocalVariableWithName(type, eleme nt.name);
7535 _defineTopVariable(variable);
7536 variable.toolkitObjects = <AngularElement> [element];
7537 }
7538
7539 /**
7540 * Parse the value of the given token for embedded expressions, and add any em bedded expressions
7541 * that are found to the given list of expressions.
7542 *
7543 * @param expressions the list to which embedded expressions are to be added
7544 * @param token the token whose value is to be parsed
7545 */
7546 void _parseEmbeddedExpressions(List<AngularMoustacheXmlExpression> expressions , ht.Token token) {
7547 // prepare Token information
7548 String lexeme = token.lexeme;
7549 int offset = token.offset;
7550 // find expressions between {{ and }}
7551 int startIndex = StringUtilities.indexOf2(lexeme, 0, AngularMoustacheXmlExpr ession.OPENING_DELIMITER_CHAR, AngularMoustacheXmlExpression.OPENING_DELIMITER_C HAR);
7552 while (startIndex >= 0) {
7553 int endIndex = StringUtilities.indexOf2(lexeme, startIndex + AngularMousta cheXmlExpression.OPENING_DELIMITER_LENGTH, AngularMoustacheXmlExpression.CLOSING _DELIMITER_CHAR, AngularMoustacheXmlExpression.CLOSING_DELIMITER_CHAR);
7554 if (endIndex < 0) {
7555 // TODO(brianwilkerson) Should we report this error or will it be report ed by something else?
7556 return;
7557 } else if (startIndex + AngularMoustacheXmlExpression.OPENING_DELIMITER_LE NGTH < endIndex) {
7558 startIndex += AngularMoustacheXmlExpression.OPENING_DELIMITER_LENGTH;
7559 AngularExpression expression = _parseAngularExpression(lexeme, startInde x, endIndex, offset);
7560 expressions.add(new AngularMoustacheXmlExpression(startIndex, endIndex, expression));
7561 }
7562 startIndex = StringUtilities.indexOf2(lexeme, endIndex + AngularMoustacheX mlExpression.CLOSING_DELIMITER_LENGTH, AngularMoustacheXmlExpression.OPENING_DEL IMITER_CHAR, AngularMoustacheXmlExpression.OPENING_DELIMITER_CHAR);
7563 }
7564 }
7565
7566 void _parseEmbeddedExpressionsInAttribute(ht.XmlAttributeNode node) {
7567 List<AngularMoustacheXmlExpression> expressions = [];
7568 _parseEmbeddedExpressions(expressions, node.valueToken);
7569 if (!expressions.isEmpty) {
7570 node.expressions = new List.from(expressions);
7571 }
7572 }
7573
7574 void _parseEmbeddedExpressionsInTag(ht.XmlTagNode node) {
7575 List<AngularMoustacheXmlExpression> expressions = [];
7576 ht.Token token = node.attributeEnd;
7577 ht.Token endToken = node.endToken;
7578 bool inChild = false;
7579 while (!identical(token, endToken)) {
7580 for (ht.XmlTagNode child in node.tagNodes) {
7581 if (identical(token, child.beginToken)) {
7582 inChild = true;
7583 break;
7584 }
7585 if (identical(token, child.endToken)) {
7586 inChild = false;
7587 break;
7588 }
7589 }
7590 if (!inChild && token.type == ht.TokenType.TEXT) {
7591 _parseEmbeddedExpressions(expressions, token);
7592 }
7593 token = token.next;
7594 }
7595 node.expressions = new List.from(expressions);
7596 }
7597
7598 void _recordDefinedVariable(LocalVariableElementImpl variable) {
7599 _definedVariables.add(variable);
7600 _functionElement.localVariables = new List.from(_definedVariables);
7601 }
7602
7603 /**
7604 * When we inject variable, we give access to the library of its type.
7605 */
7606 void _recordTypeLibraryInjected(LocalVariableElementImpl variable) {
7607 LibraryElement typeLibrary = variable.type.element.library;
7608 _injectedLibraries.add(typeLibrary);
7609 }
7610
7611 void _resolveExpressions(List<ht.XmlExpression> expressions) {
7612 for (ht.XmlExpression xmlExpression in expressions) {
7613 if (xmlExpression is AngularXmlExpression) {
7614 AngularXmlExpression angularXmlExpression = xmlExpression;
7615 _resolveXmlExpression(angularXmlExpression);
7616 }
7617 }
7618 }
7619
7620 /**
7621 * Resolves Angular specific expressions and elements in the [source].
7622 *
7623 * @param angularElements the [AngularElement]s accessible in the component's library, not
7624 * `null`
7625 * @param component the [AngularComponentElement] to resolve template for, may be
7626 * `null` if not a component template
7627 */
7628 void _resolveInternal(List<AngularElement> angularElements, AngularComponentEl ement component) {
7629 this._angularElements = angularElements;
7630 // add built-in processors
7631 _processors.add(NgModelProcessor.INSTANCE);
7632 // _processors.add(NgRepeatProcessor.INSTANCE);
7633 // add element's libraries
7634 for (AngularElement angularElement in angularElements) {
7635 _injectedLibraries.add(angularElement.library);
7636 }
7637 // prepare Dart library
7638 _createLibraryElement();
7639 (_unit.element as HtmlElementImpl).angularCompilationUnit = _unitElement;
7640 // prepare Dart resolver
7641 _createResolver();
7642 // maybe resolving component template
7643 if (component != null) {
7644 _defineTopVariable_forClassElement(component);
7645 for (AngularScopePropertyElement scopeProperty in component.scopePropertie s) {
7646 _defineTopVariable_forScopeProperty(scopeProperty);
7647 }
7648 }
7649 // add processors
7650 for (AngularElement angularElement in angularElements) {
7651 NgProcessor processor = _createProcessor(angularElement);
7652 if (processor != null) {
7653 _processors.add(processor);
7654 }
7655 }
7656 // define formatters
7657 for (AngularElement angularElement in angularElements) {
7658 if (angularElement is AngularFormatterElement) {
7659 _defineTopVariable_forClassElement(angularElement);
7660 }
7661 }
7662 // run this HTML visitor
7663 _unit.accept(this);
7664 // simulate imports for injects
7665 {
7666 List<ImportElement> imports = [];
7667 for (LibraryElement injectedLibrary in _injectedLibraries) {
7668 ImportElementImpl importElement = new ImportElementImpl(-1);
7669 importElement.importedLibrary = injectedLibrary;
7670 imports.add(importElement);
7671 }
7672 _libraryElement.imports = new List.from(imports);
7673 }
7674 }
7675
7676 void _resolveXmlExpression(AngularXmlExpression angularXmlExpression) {
7677 AngularExpression angularExpression = angularXmlExpression.expression;
7678 _resolveExpression(angularExpression);
7679 }
7680
7681 List<Token> _splitAtBar(Token token) {
7682 List<Token> tokens = [];
7683 tokens.add(token);
7684 while (token.type != TokenType.EOF) {
7685 if (token.type == TokenType.BAR) {
7686 tokens.add(token);
7687 Token eofToken = new Token(TokenType.EOF, 0);
7688 token.previous.setNext(eofToken);
7689 }
7690 token = token.next;
7691 }
7692 return tokens;
7693 }
7694
7695 /**
7696 * The "ng-model" directive is special, it contributes to the top-level name s cope. These models
7697 * can be used before actual "ng-model" attribute in HTML. So, we need to defi ne them once we
7698 * found [NG_APP] context.
7699 */
7700 void _visitModelDirectives(ht.XmlTagNode appNode) {
7701 appNode.accept(new RecursiveXmlVisitor_AngularHtmlUnitResolver_visitModelDir ectives(this));
7702 }
7703 }
7704
7705 class AngularHtmlUnitResolver_FilteringAnalysisErrorListener implements Analysis ErrorListener {
7706 final AnalysisErrorListener _listener;
7707
7708 AngularHtmlUnitResolver_FilteringAnalysisErrorListener(this._listener);
7709
7710 @override
7711 void onError(AnalysisError error) {
7712 ErrorCode errorCode = error.errorCode;
7713 if (identical(errorCode, StaticWarningCode.UNDEFINED_GETTER) || identical(er rorCode, StaticWarningCode.UNDEFINED_IDENTIFIER) || identical(errorCode, StaticT ypeWarningCode.UNDEFINED_GETTER)) {
7714 return;
7715 }
7716 _listener.onError(error);
7717 }
7718 }
7719
7720 class AngularHtmlUnitResolver_FoundAppError extends Error {
7721 }
7722
7723 /**
7724 * Implementation of [AngularXmlExpression] for an [AngularExpression] enclosed between
7725 * <code>{{</code> and <code>}}</code>.
7726 */
7727 class AngularMoustacheXmlExpression extends AngularXmlExpression {
7728 static int OPENING_DELIMITER_CHAR = 0x7B;
7729
7730 static int CLOSING_DELIMITER_CHAR = 0x7D;
7731
7732 static String OPENING_DELIMITER = "{{";
7733
7734 static String CLOSING_DELIMITER = "}}";
7735
7736 static int OPENING_DELIMITER_LENGTH = OPENING_DELIMITER.length;
7737
7738 static int CLOSING_DELIMITER_LENGTH = CLOSING_DELIMITER.length;
7739
7740 /**
7741 * The offset of the first character of the opening delimiter.
7742 */
7743 final int _openingOffset;
7744
7745 /**
7746 * The offset of the first character of the closing delimiter.
7747 */
7748 final int _closingOffset;
7749
7750 AngularMoustacheXmlExpression(this._openingOffset, this._closingOffset, Angula rExpression expression) : super(expression);
7751
7752 @override
7753 int get end => _closingOffset + CLOSING_DELIMITER_LENGTH;
7754
7755 @override
7756 int get length => _closingOffset + CLOSING_DELIMITER_LENGTH - _openingOffset;
7757
7758 @override
7759 int get offset => _openingOffset;
7760 }
7761
7762 /**
7763 * Implementation of [AngularXmlExpression] for an [AngularExpression] embedded without
7764 * any wrapping characters.
7765 */
7766 class AngularRawXmlExpression extends AngularXmlExpression {
7767 AngularRawXmlExpression(AngularExpression expression) : super(expression);
7768
7769 @override
7770 int get end => expression.end;
7771
7772 @override
7773 int get length => expression.length;
7774
7775 @override
7776 int get offset => expression.offset;
7777 }
7778
7779 /**
7780 * Abstract Angular specific [XmlExpression].
7781 */
7782 abstract class AngularXmlExpression extends ht.XmlExpression {
7783 /**
7784 * The expression that is enclosed between the delimiters.
7785 */
7786 final AngularExpression expression;
7787
7788 AngularXmlExpression(this.expression);
7789
7790 @override
7791 ht.XmlExpression_Reference getReference(int offset) {
7792 // main expression
7793 ht.XmlExpression_Reference reference = _getReferenceAtNode(expression.expres sion, offset);
7794 if (reference != null) {
7795 return reference;
7796 }
7797 // formatters
7798 for (AngularFormatterNode formatter in expression.formatters) {
7799 // formatter name
7800 reference = _getReferenceAtNode(formatter.name, offset);
7801 if (reference != null) {
7802 return reference;
7803 }
7804 // formatter arguments
7805 for (AngularFormatterArgument formatterArgument in formatter.arguments) {
7806 reference = _getReferenceAtNode(formatterArgument.expression, offset);
7807 if (reference != null) {
7808 return reference;
7809 }
7810 }
7811 }
7812 return null;
7813 }
7814
7815 /**
7816 * If the given [AstNode] has an [Element] at the given offset, then returns
7817 * [Reference] with this [Element].
7818 */
7819 ht.XmlExpression_Reference _getReferenceAtNode(AstNode root, int offset) {
7820 AstNode node = new NodeLocator.con1(offset).searchWithin(root);
7821 if (node != null) {
7822 Element element = ElementLocator.locate(node);
7823 return new ht.XmlExpression_Reference(element, node.offset, node.length);
7824 }
7825 return null;
7826 }
7827 }
7828
7829 /**
7830 * Instances of the class `CachePartition` implement a single partition in an LR U cache of
7831 * information related to analysis.
7832 */
7833 abstract class CachePartition {
7834 /**
7835 * A table mapping the sources known to the context to the information known a bout the source.
7836 */
7837 HashMap<Source, SourceEntry> _sourceMap = new HashMap<Source, SourceEntry>();
7838
7839 /**
7840 * The maximum number of sources for which AST structures should be kept in th e cache.
7841 */
7842 int _maxCacheSize = 0;
7843
7844 /**
7845 * The policy used to determine which pieces of data to remove from the cache.
7846 */
7847 final CacheRetentionPolicy _retentionPolicy;
7848
7849 /**
7850 * A list containing the most recently accessed sources with the most recently used at the end of
7851 * the list. When more sources are added than the maximum allowed then the lea st recently used
7852 * source will be removed and will have it's cached AST structure flushed.
7853 */
7854 List<Source> _recentlyUsed;
7855
7856 /**
7857 * Initialize a newly created cache to maintain at most the given number of AS T structures in the
7858 * cache.
7859 *
7860 * @param maxCacheSize the maximum number of sources for which AST structures should be kept in
7861 * the cache
7862 * @param retentionPolicy the policy used to determine which pieces of data to remove from the
7863 * cache
7864 */
7865 CachePartition(int maxCacheSize, this._retentionPolicy) {
7866 this._maxCacheSize = maxCacheSize;
7867 _recentlyUsed = new List<Source>();
7868 }
7869
7870 /**
7871 * Record that the AST associated with the given source was just read from the cache.
7872 *
7873 * @param source the source whose AST was accessed
7874 */
7875 void accessedAst(Source source) {
7876 if (_recentlyUsed.remove(source)) {
7877 _recentlyUsed.add(source);
7878 return;
7879 }
7880 while (_recentlyUsed.length >= _maxCacheSize) {
7881 if (!_flushAstFromCache()) {
7882 break;
7883 }
7884 }
7885 _recentlyUsed.add(source);
7886 }
7887
7888 /**
7889 * Return `true` if the given source is contained in this partition.
7890 *
7891 * @param source the source being tested
7892 * @return `true` if the source is contained in this partition
7893 */
7894 bool contains(Source source);
7895
7896 /**
7897 * Return the entry associated with the given source.
7898 *
7899 * @param source the source whose entry is to be returned
7900 * @return the entry associated with the given source
7901 */
7902 SourceEntry get(Source source) => _sourceMap[source];
7903
7904 /**
7905 * Return the number of entries in this partition that have an AST associated with them.
7906 *
7907 * @return the number of entries in this partition that have an AST associated with them
7908 */
7909 int get astSize {
7910 int astSize = 0;
7911 int count = _recentlyUsed.length;
7912 for (int i = 0; i < count; i++) {
7913 Source source = _recentlyUsed[i];
7914 SourceEntry sourceEntry = _sourceMap[source];
7915 if (sourceEntry is DartEntry) {
7916 if (sourceEntry.anyParsedCompilationUnit != null) {
7917 astSize++;
7918 }
7919 } else if (sourceEntry is HtmlEntry) {
7920 if (sourceEntry.anyParsedUnit != null) {
7921 astSize++;
7922 }
7923 }
7924 }
7925 return astSize;
7926 }
7927
7928 /**
7929 * Return a table mapping the sources known to the context to the information known about the
7930 * source.
7931 *
7932 * <b>Note:</b> This method is only visible for use by [AnalysisCache] and sho uld not be
7933 * used for any other purpose.
7934 *
7935 * @return a table mapping the sources known to the context to the information known about the
7936 * source
7937 */
7938 Map<Source, SourceEntry> get map => _sourceMap;
7939
7940 /**
7941 * Return an iterator returning all of the map entries mapping sources to cach e entries.
7942 *
7943 * @return an iterator returning all of the map entries mapping sources to cac he entries
7944 */
7945 MapIterator<Source, SourceEntry> iterator() => new SingleMapIterator<Source, S ourceEntry>(_sourceMap);
7946
7947 /**
7948 * Associate the given entry with the given source.
7949 *
7950 * @param source the source with which the entry is to be associated
7951 * @param entry the entry to be associated with the source
7952 */
7953 void put(Source source, SourceEntry entry) {
7954 (entry as SourceEntryImpl).fixExceptionState();
7955 _sourceMap[source] = entry;
7956 }
7957
7958 /**
7959 * Remove all information related to the given source from this cache.
7960 *
7961 * @param source the source to be removed
7962 */
7963 void remove(Source source) {
7964 _recentlyUsed.remove(source);
7965 _sourceMap.remove(source);
7966 }
7967
7968 /**
7969 * Record that the AST associated with the given source was just removed from the cache.
7970 *
7971 * @param source the source whose AST was removed
7972 */
7973 void removedAst(Source source) {
7974 _recentlyUsed.remove(source);
7975 }
7976
7977 /**
7978 * Set the maximum size of the cache to the given size.
7979 *
7980 * @param size the maximum number of sources for which AST structures should b e kept in the cache
7981 */
7982 void set maxCacheSize(int size) {
7983 _maxCacheSize = size;
7984 while (_recentlyUsed.length > _maxCacheSize) {
7985 if (!_flushAstFromCache()) {
7986 break;
7987 }
7988 }
7989 }
7990
7991 /**
7992 * Return the number of sources that are mapped to cache entries.
7993 *
7994 * @return the number of sources that are mapped to cache entries
7995 */
7996 int size() => _sourceMap.length;
7997
7998 /**
7999 * Record that the AST associated with the given source was just stored to the cache.
8000 *
8001 * @param source the source whose AST was stored
8002 */
8003 void storedAst(Source source) {
8004 if (_recentlyUsed.contains(source)) {
8005 return;
8006 }
8007 while (_recentlyUsed.length >= _maxCacheSize) {
8008 if (!_flushAstFromCache()) {
8009 break;
8010 }
8011 }
8012 _recentlyUsed.add(source);
8013 }
8014
8015 /**
8016 * Attempt to flush one AST structure from the cache.
8017 *
8018 * @return `true` if a structure was flushed
8019 */
8020 bool _flushAstFromCache() {
8021 Source removedSource = _removeAstToFlush();
8022 if (removedSource == null) {
8023 return false;
8024 }
8025 SourceEntry sourceEntry = _sourceMap[removedSource];
8026 if (sourceEntry is HtmlEntry) {
8027 HtmlEntryImpl htmlCopy = sourceEntry.writableCopy;
8028 htmlCopy.flushAstStructures();
8029 _sourceMap[removedSource] = htmlCopy;
8030 } else if (sourceEntry is DartEntry) {
8031 DartEntryImpl dartCopy = sourceEntry.writableCopy;
8032 dartCopy.flushAstStructures();
8033 _sourceMap[removedSource] = dartCopy;
8034 }
8035 return true;
8036 }
8037
8038 /**
8039 * Remove and return one source from the list of recently used sources whose A ST structure can be
8040 * flushed from the cache. The source that will be returned will be the source that has been
8041 * unreferenced for the longest period of time but that is not a priority for analysis.
8042 *
8043 * @return the source that was removed
8044 */
8045 Source _removeAstToFlush() {
8046 int sourceToRemove = -1;
8047 for (int i = 0; i < _recentlyUsed.length; i++) {
8048 Source source = _recentlyUsed[i];
8049 RetentionPriority priority = _retentionPolicy.getAstPriority(source, _sour ceMap[source]);
8050 if (priority == RetentionPriority.LOW) {
8051 return _recentlyUsed.removeAt(i);
8052 } else if (priority == RetentionPriority.MEDIUM && sourceToRemove < 0) {
8053 sourceToRemove = i;
8054 }
8055 }
8056 if (sourceToRemove < 0) {
8057 // This happens if the retention policy returns a priority of HIGH for all of the sources that
8058 // have been recently used. This is the case, for example, when the list o f priority sources
8059 // is bigger than the current cache size.
8060 return null;
8061 }
8062 return _recentlyUsed.removeAt(sourceToRemove);
8063 }
8064 }
8065
8066 /**
8067 * Instances of the class `CacheRetentionPolicy` define the behavior of objects that determine
8068 * how important it is for data to be retained in the analysis cache.
8069 */
8070 abstract class CacheRetentionPolicy {
8071 /**
8072 * Return the priority of retaining the AST structure for the given source.
8073 *
8074 * @param source the source whose AST structure is being considered for remova l
8075 * @param sourceEntry the entry representing the source
8076 * @return the priority of retaining the AST structure for the given source
8077 */
8078 RetentionPriority getAstPriority(Source source, SourceEntry sourceEntry);
8079 }
8080
8081 /**
8082 * The enumeration `CacheState` defines the possible states of cached data.
8083 */
8084 class CacheState extends Enum<CacheState> {
8085 /**
8086 * The data is not in the cache and the last time an attempt was made to compu te the data an
8087 * exception occurred, making it pointless to attempt.
8088 *
8089 * Valid Transitions:
8090 * * [INVALID] if a source was modified that might cause the data to be comput able
8091 */
8092 static const CacheState ERROR = const CacheState('ERROR', 0);
8093
8094 /**
8095 * The data is not in the cache because it was flushed from the cache in order to control memory
8096 * usage. If the data is recomputed, results do not need to be reported.
8097 *
8098 * Valid Transitions:
8099 * * [IN_PROCESS] if the data is being recomputed
8100 * * [INVALID] if a source was modified that causes the data to need to be rec omputed
8101 */
8102 static const CacheState FLUSHED = const CacheState('FLUSHED', 1);
8103
8104 /**
8105 * The data might or might not be in the cache but is in the process of being recomputed.
8106 *
8107 * Valid Transitions:
8108 * * [ERROR] if an exception occurred while trying to compute the data
8109 * * [VALID] if the data was successfully computed and stored in the cache
8110 */
8111 static const CacheState IN_PROCESS = const CacheState('IN_PROCESS', 2);
8112
8113 /**
8114 * The data is not in the cache and needs to be recomputed so that results can be reported.
8115 *
8116 * Valid Transitions:
8117 * * [IN_PROCESS] if an attempt is being made to recompute the data
8118 */
8119 static const CacheState INVALID = const CacheState('INVALID', 3);
8120
8121 /**
8122 * The data is in the cache and up-to-date.
8123 *
8124 * Valid Transitions:
8125 * * [FLUSHED] if the data is removed in order to manage memory usage
8126 * * [INVALID] if a source was modified in such a way as to invalidate the pre vious data
8127 */
8128 static const CacheState VALID = const CacheState('VALID', 4);
8129
8130 static const List<CacheState> values = const [ERROR, FLUSHED, IN_PROCESS, INVA LID, VALID];
8131
8132 const CacheState(String name, int ordinal) : super(name, ordinal);
8133 }
8134
8135 /**
8136 * The interface `ChangeNotice` defines the behavior of objects that represent a change to the
8137 * analysis results associated with a given source.
8138 */
8139 abstract class ChangeNotice implements AnalysisErrorInfo {
8140 /**
8141 * Return the fully resolved AST that changed as a result of the analysis, or `null` if the
8142 * AST was not changed.
8143 *
8144 * @return the fully resolved AST that changed as a result of the analysis
8145 */
8146 CompilationUnit get compilationUnit;
8147
8148 /**
8149 * Return the fully resolved HTML that changed as a result of the analysis, or `null` if the
8150 * HTML was not changed.
8151 *
8152 * @return the fully resolved HTML that changed as a result of the analysis
8153 */
8154 ht.HtmlUnit get htmlUnit;
8155
8156 /**
8157 * Return the source for which the result is being reported.
8158 *
8159 * @return the source for which the result is being reported
8160 */
8161 Source get source;
8162 }
8163
8164 /**
8165 * Instances of the class `ChangeNoticeImpl` represent a change to the analysis results
8166 * associated with a given source.
8167 */
8168 class ChangeNoticeImpl implements ChangeNotice {
8169 /**
8170 * The source for which the result is being reported.
8171 */
8172 final Source source;
8173
8174 /**
8175 * The fully resolved AST that changed as a result of the analysis, or `null` if the AST was
8176 * not changed.
8177 */
8178 CompilationUnit compilationUnit;
8179
8180 /**
8181 * The fully resolved HTML that changed as a result of the analysis, or `null` if the HTML
8182 * was not changed.
8183 */
8184 ht.HtmlUnit htmlUnit;
8185
8186 /**
8187 * The errors that changed as a result of the analysis, or `null` if errors we re not
8188 * changed.
8189 */
8190 List<AnalysisError> _errors;
8191
8192 /**
8193 * The line information associated with the source, or `null` if errors were n ot changed.
8194 */
8195 LineInfo _lineInfo;
8196
8197 /**
8198 * An empty array of change notices.
8199 */
8200 static List<ChangeNoticeImpl> EMPTY_ARRAY = new List<ChangeNoticeImpl>(0);
8201
8202 /**
8203 * Initialize a newly created notice associated with the given source.
8204 *
8205 * @param source the source for which the change is being reported
8206 */
8207 ChangeNoticeImpl(this.source);
8208
8209 @override
8210 List<AnalysisError> get errors => _errors;
8211
8212 @override
8213 LineInfo get lineInfo => _lineInfo;
8214
8215 /**
8216 * Set the errors that changed as a result of the analysis to the given errors and set the line
8217 * information to the given line information.
8218 *
8219 * @param errors the errors that changed as a result of the analysis
8220 * @param lineInfo the line information associated with the source
8221 */
8222 void setErrors(List<AnalysisError> errors, LineInfo lineInfo) {
8223 this._errors = errors;
8224 this._lineInfo = lineInfo;
8225 if (lineInfo == null) {
8226 AnalysisEngine.instance.logger.logInformation2("No line info: ${source}", new JavaException());
8227 }
8228 }
8229
8230 @override
8231 String toString() => "Changes for ${source.fullName}";
8232 }
8233
8234 /**
8235 * Instances of the class `ChangeSet` indicate which sources have been added, ch anged,
8236 * removed, or deleted. In the case of a changed source, there are multiple ways of indicating the
8237 * nature of the change.
8238 *
8239 * No source should be added to the change set more than once, either with the s ame or a different
8240 * kind of change. It does not make sense, for example, for a source to be both added and removed,
8241 * and it is redundant for a source to be marked as changed in its entirety and changed in some
8242 * specific range.
8243 */
8244 class ChangeSet {
8245 /**
8246 * A list containing the sources that have been added.
8247 */
8248 final List<Source> addedSources = new List<Source>();
8249
8250 /**
8251 * A list containing the sources that have been changed.
8252 */
8253 final List<Source> changedSources = new List<Source>();
8254
8255 /**
8256 * A table mapping the sources whose content has been changed to the current c ontent of those
8257 * sources.
8258 */
8259 HashMap<Source, String> _changedContent = new HashMap<Source, String>();
8260
8261 /**
8262 * A table mapping the sources whose content has been changed within a single range to the current
8263 * content of those sources and information about the affected range.
8264 */
8265 final HashMap<Source, ChangeSet_ContentChange> changedRanges = new HashMap<Sou rce, ChangeSet_ContentChange>();
8266
8267 /**
8268 * A list containing the sources that have been removed.
8269 */
8270 final List<Source> removedSources = new List<Source>();
8271
8272 /**
8273 * A list containing the source containers specifying additional sources that have been removed.
8274 */
8275 final List<SourceContainer> removedContainers = new List<SourceContainer>();
8276
8277 /**
8278 * A list containing the sources that have been deleted.
8279 */
8280 final List<Source> deletedSources = new List<Source>();
8281
8282 /**
8283 * Record that the specified source has been added and that its content is the default contents of
8284 * the source.
8285 *
8286 * @param source the source that was added
8287 */
8288 void addedSource(Source source) {
8289 addedSources.add(source);
8290 }
8291
8292 /**
8293 * Record that the specified source has been changed and that its content is t he given contents.
8294 *
8295 * @param source the source that was changed
8296 * @param contents the new contents of the source, or `null` if the default co ntents of the
8297 * source are to be used
8298 */
8299 void changedContent(Source source, String contents) {
8300 _changedContent[source] = contents;
8301 }
8302
8303 /**
8304 * Record that the specified source has been changed and that its content is t he given contents.
8305 *
8306 * @param source the source that was changed
8307 * @param contents the new contents of the source
8308 * @param offset the offset into the current contents
8309 * @param oldLength the number of characters in the original contents that wer e replaced
8310 * @param newLength the number of characters in the replacement text
8311 */
8312 void changedRange(Source source, String contents, int offset, int oldLength, i nt newLength) {
8313 changedRanges[source] = new ChangeSet_ContentChange(contents, offset, oldLen gth, newLength);
8314 }
8315
8316 /**
8317 * Record that the specified source has been changed. If the content of the so urce was previously
8318 * overridden, this has no effect (the content remains overridden). To cancel (or change) the
8319 * override, use [changedContent] instead.
8320 *
8321 * @param source the source that was changed
8322 */
8323 void changedSource(Source source) {
8324 changedSources.add(source);
8325 }
8326
8327 /**
8328 * Record that the specified source has been deleted.
8329 *
8330 * @param source the source that was deleted
8331 */
8332 void deletedSource(Source source) {
8333 deletedSources.add(source);
8334 }
8335
8336 /**
8337 * Return a table mapping the sources whose content has been changed to the cu rrent content of
8338 * those sources.
8339 *
8340 * @return a table mapping the sources whose content has been changed to the c urrent content of
8341 * those sources
8342 */
8343 Map<Source, String> get changedContents => _changedContent;
8344
8345 /**
8346 * Return `true` if this change set does not contain any changes.
8347 *
8348 * @return `true` if this change set does not contain any changes
8349 */
8350 bool get isEmpty => addedSources.isEmpty && changedSources.isEmpty && _changed Content.isEmpty && changedRanges.isEmpty && removedSources.isEmpty && removedCon tainers.isEmpty && deletedSources.isEmpty;
8351
8352 /**
8353 * Record that the specified source container has been removed.
8354 *
8355 * @param container the source container that was removed
8356 */
8357 void removedContainer(SourceContainer container) {
8358 if (container != null) {
8359 removedContainers.add(container);
8360 }
8361 }
8362
8363 /**
8364 * Record that the specified source has been removed.
8365 *
8366 * @param source the source that was removed
8367 */
8368 void removedSource(Source source) {
8369 if (source != null) {
8370 removedSources.add(source);
8371 }
8372 }
8373
8374 @override
8375 String toString() {
8376 JavaStringBuilder builder = new JavaStringBuilder();
8377 bool needsSeparator = _appendSources(builder, addedSources, false, "addedSou rces");
8378 needsSeparator = _appendSources(builder, changedSources, needsSeparator, "ch angedSources");
8379 needsSeparator = _appendSources2(builder, _changedContent, needsSeparator, " changedContent");
8380 needsSeparator = _appendSources2(builder, changedRanges, needsSeparator, "ch angedRanges");
8381 needsSeparator = _appendSources(builder, deletedSources, needsSeparator, "de letedSources");
8382 needsSeparator = _appendSources(builder, removedSources, needsSeparator, "re movedSources");
8383 int count = removedContainers.length;
8384 if (count > 0) {
8385 if (removedSources.isEmpty) {
8386 if (needsSeparator) {
8387 builder.append("; ");
8388 }
8389 builder.append("removed: from ");
8390 builder.append(count);
8391 builder.append(" containers");
8392 } else {
8393 builder.append(", and more from ");
8394 builder.append(count);
8395 builder.append(" containers");
8396 }
8397 }
8398 return builder.toString();
8399 }
8400
8401 /**
8402 * Append the given sources to the given builder, prefixed with the given labe l and possibly a
8403 * separator.
8404 *
8405 * @param builder the builder to which the sources are to be appended
8406 * @param sources the sources to be appended
8407 * @param needsSeparator `true` if a separator is needed before the label
8408 * @param label the label used to prefix the sources
8409 * @return `true` if future lists of sources will need a separator
8410 */
8411 bool _appendSources(JavaStringBuilder builder, List<Source> sources, bool need sSeparator, String label) {
8412 if (sources.isEmpty) {
8413 return needsSeparator;
8414 }
8415 if (needsSeparator) {
8416 builder.append("; ");
8417 }
8418 builder.append(label);
8419 String prefix = " ";
8420 for (Source source in sources) {
8421 builder.append(prefix);
8422 builder.append(source.fullName);
8423 prefix = ", ";
8424 }
8425 return true;
8426 }
8427
8428 /**
8429 * Append the given sources to the given builder, prefixed with the given labe l and possibly a
8430 * separator.
8431 *
8432 * @param builder the builder to which the sources are to be appended
8433 * @param sources the sources to be appended
8434 * @param needsSeparator `true` if a separator is needed before the label
8435 * @param label the label used to prefix the sources
8436 * @return `true` if future lists of sources will need a separator
8437 */
8438 bool _appendSources2(JavaStringBuilder builder, HashMap<Source, dynamic> sourc es, bool needsSeparator, String label) {
8439 if (sources.isEmpty) {
8440 return needsSeparator;
8441 }
8442 if (needsSeparator) {
8443 builder.append("; ");
8444 }
8445 builder.append(label);
8446 String prefix = " ";
8447 for (Source source in sources.keys.toSet()) {
8448 builder.append(prefix);
8449 builder.append(source.fullName);
8450 prefix = ", ";
8451 }
8452 return true;
8453 }
8454 }
8455
8456 /**
8457 * Instances of the class `ContentChange` represent a change to the content of a source.
8458 */
8459 class ChangeSet_ContentChange {
8460 /**
8461 * The new contents of the source.
8462 */
8463 final String contents;
8464
8465 /**
8466 * The offset into the current contents.
8467 */
8468 final int offset;
8469
8470 /**
8471 * The number of characters in the original contents that were replaced
8472 */
8473 final int oldLength;
8474
8475 /**
8476 * The number of characters in the replacement text.
8477 */
8478 final int newLength;
8479
8480 /**
8481 * Initialize a newly created change object to represent a change to the conte nt of a source.
8482 *
8483 * @param contents the new contents of the source
8484 * @param offset the offset into the current contents
8485 * @param oldLength the number of characters in the original contents that wer e replaced
8486 * @param newLength the number of characters in the replacement text
8487 */
8488 ChangeSet_ContentChange(this.contents, this.offset, this.oldLength, this.newLe ngth);
8489 }
8490
8491 /**
8492 * Instances of the class `LibraryPair` hold a library and a list of the (source , entry)
8493 * pairs for compilation units in the library.
8494 */
8495 class CycleBuilder_LibraryPair {
8496 /**
8497 * The library containing the compilation units.
8498 */
8499 ResolvableLibrary library;
8500
8501 /**
8502 * The (source, entry) pairs representing the compilation units in the library .
8503 */
8504 List<CycleBuilder_SourceEntryPair> entryPairs;
8505
8506 /**
8507 * Initialize a newly created pair.
8508 *
8509 * @param library the library containing the compilation units
8510 * @param entryPairs the (source, entry) pairs representing the compilation un its in the
8511 * library
8512 */
8513 CycleBuilder_LibraryPair(ResolvableLibrary library, List<CycleBuilder_SourceEn tryPair> entryPairs) {
8514 this.library = library;
8515 this.entryPairs = entryPairs;
8516 }
8517 }
8518
8519 /**
8520 * Instances of the class `SourceEntryPair` hold a source and the cache entry as sociated
8521 * with that source. They are used to reduce the number of times an entry must b e looked up in
8522 * the [cache].
8523 */
8524 class CycleBuilder_SourceEntryPair {
8525 /**
8526 * The source associated with the entry.
8527 */
8528 Source source;
8529
8530 /**
8531 * The entry associated with the source.
8532 */
8533 DartEntry entry;
8534
8535 /**
8536 * Initialize a newly created pair.
8537 *
8538 * @param source the source associated with the entry
8539 * @param entry the entry associated with the source
8540 */
8541 CycleBuilder_SourceEntryPair(Source source, DartEntry entry) {
8542 this.source = source;
8543 this.entry = entry;
8544 }
8545 }
8546
8547 /**
8548 * The interface `DartEntry` defines the behavior of objects that maintain the i nformation
8549 * cached by an analysis context about an individual Dart file.
8550 */
8551 abstract class DartEntry implements SourceEntry {
8552 /**
8553 * The data descriptor representing the errors reported during Angular resolut ion.
8554 */
8555 static final DataDescriptor<List<AnalysisError>> ANGULAR_ERRORS = new DataDesc riptor<List<AnalysisError>>("DartEntry.ANGULAR_ERRORS");
8556
8557 /**
8558 * The data descriptor representing the list of libraries that contain this co mpilation unit.
8559 */
8560 static final DataDescriptor<List<Source>> CONTAINING_LIBRARIES = new DataDescr iptor<List<Source>>("DartEntry.CONTAINING_LIBRARIES");
8561
8562 /**
8563 * The data descriptor representing the library element for the library. This data is only
8564 * available for Dart files that are the defining compilation unit of a librar y.
8565 */
8566 static final DataDescriptor<LibraryElement> ELEMENT = new DataDescriptor<Libra ryElement>("DartEntry.ELEMENT");
8567
8568 /**
8569 * The data descriptor representing the list of exported libraries. This data is only available
8570 * for Dart files that are the defining compilation unit of a library.
8571 */
8572 static final DataDescriptor<List<Source>> EXPORTED_LIBRARIES = new DataDescrip tor<List<Source>>("DartEntry.EXPORTED_LIBRARIES");
8573
8574 /**
8575 * The data descriptor representing the hints resulting from auditing the sour ce.
8576 */
8577 static final DataDescriptor<List<AnalysisError>> HINTS = new DataDescriptor<Li st<AnalysisError>>("DartEntry.HINTS");
8578
8579 /**
8580 * The data descriptor representing the list of imported libraries. This data is only available
8581 * for Dart files that are the defining compilation unit of a library.
8582 */
8583 static final DataDescriptor<List<Source>> IMPORTED_LIBRARIES = new DataDescrip tor<List<Source>>("DartEntry.IMPORTED_LIBRARIES");
8584
8585 /**
8586 * The data descriptor representing the list of included parts. This data is o nly available for
8587 * Dart files that are the defining compilation unit of a library.
8588 */
8589 static final DataDescriptor<List<Source>> INCLUDED_PARTS = new DataDescriptor< List<Source>>("DartEntry.INCLUDED_PARTS");
8590
8591 /**
8592 * The data descriptor representing the client flag. This data is only availab le for Dart files
8593 * that are the defining compilation unit of a library.
8594 */
8595 static final DataDescriptor<bool> IS_CLIENT = new DataDescriptor<bool>("DartEn try.IS_CLIENT");
8596
8597 /**
8598 * The data descriptor representing the launchable flag. This data is only ava ilable for Dart
8599 * files that are the defining compilation unit of a library.
8600 */
8601 static final DataDescriptor<bool> IS_LAUNCHABLE = new DataDescriptor<bool>("Da rtEntry.IS_LAUNCHABLE");
8602
8603 /**
8604 * The data descriptor representing the errors resulting from parsing the sour ce.
8605 */
8606 static final DataDescriptor<List<AnalysisError>> PARSE_ERRORS = new DataDescri ptor<List<AnalysisError>>("DartEntry.PARSE_ERRORS");
8607
8608 /**
8609 * The data descriptor representing the parsed AST structure.
8610 */
8611 static final DataDescriptor<CompilationUnit> PARSED_UNIT = new DataDescriptor< CompilationUnit>("DartEntry.PARSED_UNIT");
8612
8613 /**
8614 * The data descriptor representing the public namespace of the library. This data is only
8615 * available for Dart files that are the defining compilation unit of a librar y.
8616 */
8617 static final DataDescriptor<Namespace> PUBLIC_NAMESPACE = new DataDescriptor<N amespace>("DartEntry.PUBLIC_NAMESPACE");
8618
8619 /**
8620 * The data descriptor representing the errors resulting from resolving the so urce.
8621 */
8622 static final DataDescriptor<List<AnalysisError>> RESOLUTION_ERRORS = new DataD escriptor<List<AnalysisError>>("DartEntry.RESOLUTION_ERRORS");
8623
8624 /**
8625 * The data descriptor representing the resolved AST structure.
8626 */
8627 static final DataDescriptor<CompilationUnit> RESOLVED_UNIT = new DataDescripto r<CompilationUnit>("DartEntry.RESOLVED_UNIT");
8628
8629 /**
8630 * The data descriptor representing the token stream.
8631 */
8632 static final DataDescriptor<List<AnalysisError>> SCAN_ERRORS = new DataDescrip tor<List<AnalysisError>>("DartEntry.SCAN_ERRORS");
8633
8634 /**
8635 * The data descriptor representing the source kind.
8636 */
8637 static final DataDescriptor<SourceKind> SOURCE_KIND = new DataDescriptor<Sourc eKind>("DartEntry.SOURCE_KIND");
8638
8639 /**
8640 * The data descriptor representing the token stream.
8641 */
8642 static final DataDescriptor<Token> TOKEN_STREAM = new DataDescriptor<Token>("D artEntry.TOKEN_STREAM");
8643
8644 /**
8645 * The data descriptor representing the errors resulting from verifying the so urce.
8646 */
8647 static final DataDescriptor<List<AnalysisError>> VERIFICATION_ERRORS = new Dat aDescriptor<List<AnalysisError>>("DartEntry.VERIFICATION_ERRORS");
8648
8649 /**
8650 * Return all of the errors associated with the compilation unit that are curr ently cached.
8651 *
8652 * @return all of the errors associated with the compilation unit
8653 */
8654 List<AnalysisError> get allErrors;
8655
8656 /**
8657 * Return a valid parsed compilation unit, either an unresolved AST structure or the result of
8658 * resolving the AST structure in the context of some library, or `null` if th ere is no
8659 * parsed compilation unit available.
8660 *
8661 * @return a valid parsed compilation unit
8662 */
8663 CompilationUnit get anyParsedCompilationUnit;
8664
8665 /**
8666 * Return the result of resolving the compilation unit as part of any library, or `null` if
8667 * there is no cached resolved compilation unit.
8668 *
8669 * @return any resolved compilation unit
8670 */
8671 CompilationUnit get anyResolvedCompilationUnit;
8672
8673 /**
8674 * Return the state of the data represented by the given descriptor in the con text of the given
8675 * library.
8676 *
8677 * @param descriptor the descriptor representing the data whose state is to be returned
8678 * @param librarySource the source of the defining compilation unit of the lib rary that is the
8679 * context for the data
8680 * @return the value of the data represented by the given descriptor and libra ry
8681 */
8682 CacheState getStateInLibrary(DataDescriptor descriptor, Source librarySource);
8683
8684 /**
8685 * Return the value of the data represented by the given descriptor in the con text of the given
8686 * library, or `null` if the data represented by the descriptor is not in the cache.
8687 *
8688 * @param descriptor the descriptor representing which data is to be returned
8689 * @param librarySource the source of the defining compilation unit of the lib rary that is the
8690 * context for the data
8691 * @return the value of the data represented by the given descriptor and libra ry
8692 */
8693 Object getValueInLibrary(DataDescriptor descriptor, Source librarySource);
8694
8695 @override
8696 DartEntryImpl get writableCopy;
8697
8698 /**
8699 * Return `true` if the data represented by the given descriptor is marked as being invalid.
8700 * If the descriptor represents library-specific data then this method will re turn `true` if
8701 * the data associated with any library it marked as invalid.
8702 *
8703 * @param descriptor the descriptor representing which data is being tested
8704 * @return `true` if the data is marked as being invalid
8705 */
8706 bool hasInvalidData(DataDescriptor descriptor);
8707
8708 /**
8709 * Return `true` if this entry has an AST structure that can be resolved (even if it needs
8710 * to be copied).
8711 *
8712 * @return `true` if the method [DartEntryImpl#getResolvableCompilationUnit] w ill
8713 * return a non-`null` result
8714 */
8715 bool get hasResolvableCompilationUnit;
8716
8717 /**
8718 * Return `true` if this data is safe to use in refactoring.
8719 */
8720 bool get isRefactoringSafe;
8721 }
8722
8723 /**
8724 * Instances of the class `DartEntryImpl` implement a [DartEntry].
8725 */
8726 class DartEntryImpl extends SourceEntryImpl implements DartEntry {
8727 /**
8728 * The state of the cached token stream.
8729 */
8730 CacheState _tokenStreamState = CacheState.INVALID;
8731
8732 /**
8733 * The head of the token stream, or `null` if the token stream is not currentl y cached.
8734 */
8735 Token _tokenStream;
8736
8737 /**
8738 * The state of the cached scan errors.
8739 */
8740 CacheState _scanErrorsState = CacheState.INVALID;
8741
8742 /**
8743 * The errors produced while scanning the compilation unit, or an empty array if the errors are
8744 * not currently cached.
8745 */
8746 List<AnalysisError> _scanErrors = AnalysisError.NO_ERRORS;
8747
8748 /**
8749 * The state of the cached source kind.
8750 */
8751 CacheState _sourceKindState = CacheState.INVALID;
8752
8753 /**
8754 * The kind of this source.
8755 */
8756 SourceKind _sourceKind = SourceKind.UNKNOWN;
8757
8758 /**
8759 * The state of the cached parsed compilation unit.
8760 */
8761 CacheState _parsedUnitState = CacheState.INVALID;
8762
8763 /**
8764 * A flag indicating whether the parsed AST structure has been accessed since it was set. This is
8765 * used to determine whether the structure needs to be copied before it is res olved.
8766 */
8767 bool _parsedUnitAccessed = false;
8768
8769 /**
8770 * The parsed compilation unit, or `null` if the parsed compilation unit is no t currently
8771 * cached.
8772 */
8773 CompilationUnit _parsedUnit;
8774
8775 /**
8776 * The state of the cached parse errors.
8777 */
8778 CacheState _parseErrorsState = CacheState.INVALID;
8779
8780 /**
8781 * The errors produced while parsing the compilation unit, or an empty array i f the errors are not
8782 * currently cached.
8783 */
8784 List<AnalysisError> _parseErrors = AnalysisError.NO_ERRORS;
8785
8786 /**
8787 * The state of the cached list of imported libraries.
8788 */
8789 CacheState _importedLibrariesState = CacheState.INVALID;
8790
8791 /**
8792 * The list of libraries imported by the library, or an empty array if the lis t is not currently
8793 * cached. The list will be empty if the Dart file is a part rather than a lib rary.
8794 */
8795 List<Source> _importedLibraries = Source.EMPTY_ARRAY;
8796
8797 /**
8798 * The state of the cached list of exported libraries.
8799 */
8800 CacheState _exportedLibrariesState = CacheState.INVALID;
8801
8802 /**
8803 * The list of libraries exported by the library, or an empty array if the lis t is not currently
8804 * cached. The list will be empty if the Dart file is a part rather than a lib rary.
8805 */
8806 List<Source> _exportedLibraries = Source.EMPTY_ARRAY;
8807
8808 /**
8809 * The state of the cached list of included parts.
8810 */
8811 CacheState _includedPartsState = CacheState.INVALID;
8812
8813 /**
8814 * The list of parts included in the library, or an empty array if the list is not currently
8815 * cached. The list will be empty if the Dart file is a part rather than a lib rary.
8816 */
8817 List<Source> _includedParts = Source.EMPTY_ARRAY;
8818
8819 /**
8820 * The list of libraries that contain this compilation unit. The list will be empty if there are
8821 * no known libraries that contain this compilation unit.
8822 */
8823 List<Source> _containingLibraries = new List<Source>();
8824
8825 /**
8826 * The information known as a result of resolving this compilation unit as par t of the library
8827 * that contains this unit. This field will never be `null`.
8828 */
8829 DartEntryImpl_ResolutionState _resolutionState = new DartEntryImpl_ResolutionS tate();
8830
8831 /**
8832 * The state of the cached library element.
8833 */
8834 CacheState _elementState = CacheState.INVALID;
8835
8836 /**
8837 * The element representing the library, or `null` if the element is not curre ntly cached.
8838 */
8839 LibraryElement _element;
8840
8841 /**
8842 * The state of the cached public namespace.
8843 */
8844 CacheState _publicNamespaceState = CacheState.INVALID;
8845
8846 /**
8847 * The public namespace of the library, or `null` if the namespace is not curr ently cached.
8848 */
8849 Namespace _publicNamespace;
8850
8851 /**
8852 * The state of the cached client/ server flag.
8853 */
8854 CacheState _clientServerState = CacheState.INVALID;
8855
8856 /**
8857 * The state of the cached launchable flag.
8858 */
8859 CacheState _launchableState = CacheState.INVALID;
8860
8861 /**
8862 * The error produced while performing Angular resolution, or an empty array i f there are no
8863 * errors if the error are not currently cached.
8864 */
8865 List<AnalysisError> _angularErrors = AnalysisError.NO_ERRORS;
8866
8867 /**
8868 * The index of the flag indicating whether this library is launchable (whethe r the file has a
8869 * main method).
8870 */
8871 static int _LAUNCHABLE_INDEX = 1;
8872
8873 /**
8874 * The index of the flag indicating whether the library is client code (whethe r the library
8875 * depends on the html library). If the library is not "client code", then it is referred to as
8876 * "server code".
8877 */
8878 static int _CLIENT_CODE_INDEX = 2;
8879
8880 /**
8881 * Add the given library to the list of libraries that contain this part. This method should only
8882 * be invoked on entries that represent a part.
8883 *
8884 * @param librarySource the source of the library to be added
8885 */
8886 void addContainingLibrary(Source librarySource) {
8887 _containingLibraries.add(librarySource);
8888 }
8889
8890 /**
8891 * Flush any AST structures being maintained by this entry.
8892 */
8893 void flushAstStructures() {
8894 if (_tokenStreamState == CacheState.VALID) {
8895 _tokenStreamState = CacheState.FLUSHED;
8896 _tokenStream = null;
8897 }
8898 if (_parsedUnitState == CacheState.VALID) {
8899 _parsedUnitState = CacheState.FLUSHED;
8900 _parsedUnitAccessed = false;
8901 _parsedUnit = null;
8902 }
8903 _resolutionState.flushAstStructures();
8904 }
8905
8906 @override
8907 List<AnalysisError> get allErrors {
8908 List<AnalysisError> errors = new List<AnalysisError>();
8909 ListUtilities.addAll(errors, _scanErrors);
8910 ListUtilities.addAll(errors, _parseErrors);
8911 DartEntryImpl_ResolutionState state = _resolutionState;
8912 while (state != null) {
8913 ListUtilities.addAll(errors, state._buildElementErrors);
8914 ListUtilities.addAll(errors, state._resolutionErrors);
8915 ListUtilities.addAll(errors, state._verificationErrors);
8916 ListUtilities.addAll(errors, state._hints);
8917 state = state._nextState;
8918 }
8919 ListUtilities.addAll(errors, _angularErrors);
8920 if (errors.length == 0) {
8921 return AnalysisError.NO_ERRORS;
8922 }
8923 return new List.from(errors);
8924 }
8925
8926 @override
8927 CompilationUnit get anyParsedCompilationUnit {
8928 if (_parsedUnitState == CacheState.VALID) {
8929 _parsedUnitAccessed = true;
8930 return _parsedUnit;
8931 }
8932 DartEntryImpl_ResolutionState state = _resolutionState;
8933 while (state != null) {
8934 if (state._builtUnitState == CacheState.VALID) {
8935 return state._builtUnit;
8936 }
8937 state = state._nextState;
8938 }
8939 ;
8940 return anyResolvedCompilationUnit;
8941 }
8942
8943 @override
8944 CompilationUnit get anyResolvedCompilationUnit {
8945 DartEntryImpl_ResolutionState state = _resolutionState;
8946 while (state != null) {
8947 if (state._resolvedUnitState == CacheState.VALID) {
8948 return state._resolvedUnit;
8949 }
8950 state = state._nextState;
8951 }
8952 ;
8953 return null;
8954 }
8955
8956 /**
8957 * Return a list containing the libraries that are known to contain this part.
8958 *
8959 * @return a list containing the libraries that are known to contain this part
8960 */
8961 List<Source> get containingLibraries => _containingLibraries;
8962
8963 @override
8964 SourceKind get kind => _sourceKind;
8965
8966 /**
8967 * Answer an array of library sources containing the receiver's source.
8968 */
8969 List<Source> get librariesContaining {
8970 DartEntryImpl_ResolutionState state = _resolutionState;
8971 List<Source> result = new List<Source>();
8972 while (state != null) {
8973 if (state._librarySource != null) {
8974 result.add(state._librarySource);
8975 }
8976 state = state._nextState;
8977 }
8978 return new List.from(result);
8979 }
8980
8981 /**
8982 * Return a compilation unit that has not been accessed by any other client an d can therefore
8983 * safely be modified by the reconciler, or `null` if the source has not been parsed.
8984 *
8985 * @return a compilation unit that can be modified by the reconciler
8986 */
8987 CompilationUnit get resolvableCompilationUnit {
8988 if (_parsedUnitState == CacheState.VALID) {
8989 if (_parsedUnitAccessed) {
8990 return _parsedUnit.accept(new AstCloner()) as CompilationUnit;
8991 }
8992 CompilationUnit unit = _parsedUnit;
8993 _parsedUnitState = CacheState.FLUSHED;
8994 _parsedUnitAccessed = false;
8995 _parsedUnit = null;
8996 return unit;
8997 }
8998 DartEntryImpl_ResolutionState state = _resolutionState;
8999 while (state != null) {
9000 if (state._builtUnitState == CacheState.VALID) {
9001 // TODO(brianwilkerson) We're cloning the structure to remove any previo us resolution data,
9002 // but I'm not sure that's necessary.
9003 return state._builtUnit.accept(new AstCloner()) as CompilationUnit;
9004 }
9005 if (state._resolvedUnitState == CacheState.VALID) {
9006 return state._resolvedUnit.accept(new AstCloner()) as CompilationUnit;
9007 }
9008 state = state._nextState;
9009 }
9010 ;
9011 return null;
9012 }
9013
9014 @override
9015 CacheState getState(DataDescriptor descriptor) {
9016 if (identical(descriptor, DartEntry.ELEMENT)) {
9017 return _elementState;
9018 } else if (identical(descriptor, DartEntry.EXPORTED_LIBRARIES)) {
9019 return _exportedLibrariesState;
9020 } else if (identical(descriptor, DartEntry.IMPORTED_LIBRARIES)) {
9021 return _importedLibrariesState;
9022 } else if (identical(descriptor, DartEntry.INCLUDED_PARTS)) {
9023 return _includedPartsState;
9024 } else if (identical(descriptor, DartEntry.IS_CLIENT)) {
9025 return _clientServerState;
9026 } else if (identical(descriptor, DartEntry.IS_LAUNCHABLE)) {
9027 return _launchableState;
9028 } else if (identical(descriptor, DartEntry.PARSE_ERRORS)) {
9029 return _parseErrorsState;
9030 } else if (identical(descriptor, DartEntry.PARSED_UNIT)) {
9031 return _parsedUnitState;
9032 } else if (identical(descriptor, DartEntry.PUBLIC_NAMESPACE)) {
9033 return _publicNamespaceState;
9034 } else if (identical(descriptor, DartEntry.SCAN_ERRORS)) {
9035 return _scanErrorsState;
9036 } else if (identical(descriptor, DartEntry.SOURCE_KIND)) {
9037 return _sourceKindState;
9038 } else if (identical(descriptor, DartEntry.TOKEN_STREAM)) {
9039 return _tokenStreamState;
9040 } else {
9041 return super.getState(descriptor);
9042 }
9043 }
9044
9045 @override
9046 CacheState getStateInLibrary(DataDescriptor descriptor, Source librarySource) {
9047 DartEntryImpl_ResolutionState state = _resolutionState;
9048 while (state != null) {
9049 if (librarySource == state._librarySource) {
9050 if (identical(descriptor, DartEntry.RESOLUTION_ERRORS)) {
9051 return state._resolutionErrorsState;
9052 } else if (identical(descriptor, DartEntry.RESOLVED_UNIT)) {
9053 return state._resolvedUnitState;
9054 } else if (identical(descriptor, DartEntry.VERIFICATION_ERRORS)) {
9055 return state._verificationErrorsState;
9056 } else if (identical(descriptor, DartEntry.HINTS)) {
9057 return state._hintsState;
9058 } else {
9059 throw new IllegalArgumentException("Invalid descriptor: ${descriptor}" );
9060 }
9061 }
9062 state = state._nextState;
9063 }
9064 ;
9065 if (identical(descriptor, DartEntry.RESOLUTION_ERRORS) || identical(descript or, DartEntry.RESOLVED_UNIT) || identical(descriptor, DartEntry.VERIFICATION_ERR ORS) || identical(descriptor, DartEntry.HINTS)) {
9066 return CacheState.INVALID;
9067 } else {
9068 throw new IllegalArgumentException("Invalid descriptor: ${descriptor}");
9069 }
9070 }
9071
9072 @override
9073 Object getValue(DataDescriptor descriptor) {
9074 if (identical(descriptor, DartEntry.ANGULAR_ERRORS)) {
9075 return _angularErrors;
9076 } else if (identical(descriptor, DartEntry.CONTAINING_LIBRARIES)) {
9077 return new List.from(_containingLibraries);
9078 } else if (identical(descriptor, DartEntry.ELEMENT)) {
9079 return _element;
9080 } else if (identical(descriptor, DartEntry.EXPORTED_LIBRARIES)) {
9081 return _exportedLibraries;
9082 } else if (identical(descriptor, DartEntry.IMPORTED_LIBRARIES)) {
9083 return _importedLibraries;
9084 } else if (identical(descriptor, DartEntry.INCLUDED_PARTS)) {
9085 return _includedParts;
9086 } else if (identical(descriptor, DartEntry.IS_CLIENT)) {
9087 return getFlag(_CLIENT_CODE_INDEX);
9088 } else if (identical(descriptor, DartEntry.IS_LAUNCHABLE)) {
9089 return getFlag(_LAUNCHABLE_INDEX);
9090 } else if (identical(descriptor, DartEntry.PARSE_ERRORS)) {
9091 return _parseErrors;
9092 } else if (identical(descriptor, DartEntry.PARSED_UNIT)) {
9093 _parsedUnitAccessed = true;
9094 return _parsedUnit;
9095 } else if (identical(descriptor, DartEntry.PUBLIC_NAMESPACE)) {
9096 return _publicNamespace;
9097 } else if (identical(descriptor, DartEntry.SCAN_ERRORS)) {
9098 return _scanErrors;
9099 } else if (identical(descriptor, DartEntry.SOURCE_KIND)) {
9100 return _sourceKind;
9101 } else if (identical(descriptor, DartEntry.TOKEN_STREAM)) {
9102 return _tokenStream;
9103 }
9104 return super.getValue(descriptor);
9105 }
9106
9107 @override
9108 Object getValueInLibrary(DataDescriptor descriptor, Source librarySource) {
9109 DartEntryImpl_ResolutionState state = _resolutionState;
9110 while (state != null) {
9111 if (librarySource == state._librarySource) {
9112 if (identical(descriptor, DartEntry.RESOLUTION_ERRORS)) {
9113 return state._resolutionErrors;
9114 } else if (identical(descriptor, DartEntry.RESOLVED_UNIT)) {
9115 return state._resolvedUnit;
9116 } else if (identical(descriptor, DartEntry.VERIFICATION_ERRORS)) {
9117 return state._verificationErrors;
9118 } else if (identical(descriptor, DartEntry.HINTS)) {
9119 return state._hints;
9120 } else {
9121 throw new IllegalArgumentException("Invalid descriptor: ${descriptor}" );
9122 }
9123 }
9124 state = state._nextState;
9125 }
9126 ;
9127 if (identical(descriptor, DartEntry.RESOLUTION_ERRORS) || identical(descript or, DartEntry.VERIFICATION_ERRORS) || identical(descriptor, DartEntry.HINTS)) {
9128 return AnalysisError.NO_ERRORS;
9129 } else if (identical(descriptor, DartEntry.RESOLVED_UNIT)) {
9130 return null;
9131 } else {
9132 throw new IllegalArgumentException("Invalid descriptor: ${descriptor}");
9133 }
9134 }
9135
9136 @override
9137 DartEntryImpl get writableCopy {
9138 DartEntryImpl copy = new DartEntryImpl();
9139 copy.copyFrom(this);
9140 return copy;
9141 }
9142
9143 @override
9144 bool hasInvalidData(DataDescriptor descriptor) {
9145 if (identical(descriptor, DartEntry.ELEMENT)) {
9146 return _elementState == CacheState.INVALID;
9147 } else if (identical(descriptor, DartEntry.EXPORTED_LIBRARIES)) {
9148 return _exportedLibrariesState == CacheState.INVALID;
9149 } else if (identical(descriptor, DartEntry.IMPORTED_LIBRARIES)) {
9150 return _importedLibrariesState == CacheState.INVALID;
9151 } else if (identical(descriptor, DartEntry.INCLUDED_PARTS)) {
9152 return _includedPartsState == CacheState.INVALID;
9153 } else if (identical(descriptor, DartEntry.IS_CLIENT)) {
9154 return _clientServerState == CacheState.INVALID;
9155 } else if (identical(descriptor, DartEntry.IS_LAUNCHABLE)) {
9156 return _launchableState == CacheState.INVALID;
9157 } else if (identical(descriptor, DartEntry.PARSE_ERRORS)) {
9158 return _parseErrorsState == CacheState.INVALID;
9159 } else if (identical(descriptor, DartEntry.PARSED_UNIT)) {
9160 return _parsedUnitState == CacheState.INVALID;
9161 } else if (identical(descriptor, DartEntry.PUBLIC_NAMESPACE)) {
9162 return _publicNamespaceState == CacheState.INVALID;
9163 } else if (identical(descriptor, DartEntry.SCAN_ERRORS)) {
9164 return _scanErrorsState == CacheState.INVALID;
9165 } else if (identical(descriptor, DartEntry.SOURCE_KIND)) {
9166 return _sourceKindState == CacheState.INVALID;
9167 } else if (identical(descriptor, DartEntry.TOKEN_STREAM)) {
9168 return _tokenStreamState == CacheState.INVALID;
9169 } else if (identical(descriptor, DartEntry.RESOLUTION_ERRORS) || identical(d escriptor, DartEntry.RESOLVED_UNIT) || identical(descriptor, DartEntry.VERIFICAT ION_ERRORS) || identical(descriptor, DartEntry.HINTS)) {
9170 DartEntryImpl_ResolutionState state = _resolutionState;
9171 while (state != null) {
9172 if (identical(descriptor, DartEntry.RESOLUTION_ERRORS)) {
9173 return state._resolutionErrorsState == CacheState.INVALID;
9174 } else if (identical(descriptor, DartEntry.RESOLVED_UNIT)) {
9175 return state._resolvedUnitState == CacheState.INVALID;
9176 } else if (identical(descriptor, DartEntry.VERIFICATION_ERRORS)) {
9177 return state._verificationErrorsState == CacheState.INVALID;
9178 } else if (identical(descriptor, DartEntry.HINTS)) {
9179 return state._hintsState == CacheState.INVALID;
9180 }
9181 }
9182 return false;
9183 } else {
9184 return super.getState(descriptor) == CacheState.INVALID;
9185 }
9186 }
9187
9188 @override
9189 bool get hasResolvableCompilationUnit {
9190 if (_parsedUnitState == CacheState.VALID) {
9191 return true;
9192 }
9193 DartEntryImpl_ResolutionState state = _resolutionState;
9194 while (state != null) {
9195 if (state._builtUnitState == CacheState.VALID || state._resolvedUnitState == CacheState.VALID) {
9196 return true;
9197 }
9198 state = state._nextState;
9199 }
9200 ;
9201 return false;
9202 }
9203
9204 @override
9205 void invalidateAllInformation() {
9206 super.invalidateAllInformation();
9207 _scanErrors = AnalysisError.NO_ERRORS;
9208 _scanErrorsState = CacheState.INVALID;
9209 _tokenStream = null;
9210 _tokenStreamState = CacheState.INVALID;
9211 _sourceKind = SourceKind.UNKNOWN;
9212 _sourceKindState = CacheState.INVALID;
9213 _parseErrors = AnalysisError.NO_ERRORS;
9214 _parseErrorsState = CacheState.INVALID;
9215 _parsedUnit = null;
9216 _parsedUnitAccessed = false;
9217 _parsedUnitState = CacheState.INVALID;
9218 _discardCachedResolutionInformation(true);
9219 }
9220
9221 /**
9222 * Invalidate all of the resolution information associated with the compilatio n unit.
9223 *
9224 * @param invalidateUris true if the cached results of converting URIs to sour ce files should also
9225 * be invalidated.
9226 */
9227 void invalidateAllResolutionInformation(bool invalidateUris) {
9228 if (_parsedUnitState == CacheState.FLUSHED) {
9229 DartEntryImpl_ResolutionState state = _resolutionState;
9230 while (state != null) {
9231 if (state._builtUnitState == CacheState.VALID) {
9232 _parsedUnit = state._builtUnit;
9233 _parsedUnitAccessed = true;
9234 _parsedUnitState = CacheState.VALID;
9235 break;
9236 } else if (state._resolvedUnitState == CacheState.VALID) {
9237 _parsedUnit = state._resolvedUnit;
9238 _parsedUnitAccessed = true;
9239 _parsedUnitState = CacheState.VALID;
9240 break;
9241 }
9242 state = state._nextState;
9243 }
9244 }
9245 _discardCachedResolutionInformation(invalidateUris);
9246 }
9247
9248 @override
9249 bool get isRefactoringSafe {
9250 DartEntryImpl_ResolutionState state = _resolutionState;
9251 while (state != null) {
9252 CacheState resolvedState = state._resolvedUnitState;
9253 if (resolvedState != CacheState.VALID && resolvedState != CacheState.FLUSH ED) {
9254 return false;
9255 }
9256 state = state._nextState;
9257 }
9258 return true;
9259 }
9260
9261 /**
9262 * Record that an error occurred while attempting to build the element model f or the source
9263 * represented by this entry. This will set the state of all resolution-based information as being
9264 * in error, but will not change the state of any parse results.
9265 *
9266 * @param librarySource the source of the library in which the element model w as being built
9267 * @param exception the exception that shows where the error occurred
9268 */
9269 void recordBuildElementErrorInLibrary(Source librarySource, CaughtException ex ception) {
9270 this.exception = exception;
9271 _element = null;
9272 _elementState = CacheState.ERROR;
9273 clearFlags([_LAUNCHABLE_INDEX, _CLIENT_CODE_INDEX]);
9274 _clientServerState = CacheState.ERROR;
9275 _launchableState = CacheState.ERROR;
9276 DartEntryImpl_ResolutionState state = _getOrCreateResolutionState(librarySou rce);
9277 state.recordBuildElementError();
9278 }
9279
9280 /**
9281 * Record that an in-process model build has stopped without recording results because the results
9282 * were invalidated before they could be recorded.
9283 */
9284 void recordBuildElementNotInProcess() {
9285 if (_elementState == CacheState.IN_PROCESS) {
9286 _elementState = CacheState.INVALID;
9287 }
9288 if (_clientServerState == CacheState.IN_PROCESS) {
9289 _clientServerState = CacheState.INVALID;
9290 }
9291 if (_launchableState == CacheState.IN_PROCESS) {
9292 _launchableState = CacheState.INVALID;
9293 }
9294 }
9295
9296 @override
9297 void recordContentError(CaughtException exception) {
9298 super.recordContentError(exception);
9299 recordScanError(exception);
9300 }
9301
9302 /**
9303 * Record that an error occurred while attempting to generate hints for the so urce represented by
9304 * this entry. This will set the state of all verification information as bein g in error.
9305 *
9306 * @param librarySource the source of the library in which hints were being ge nerated
9307 * @param exception the exception that shows where the error occurred
9308 */
9309 void recordHintErrorInLibrary(Source librarySource, CaughtException exception) {
9310 this.exception = exception;
9311 DartEntryImpl_ResolutionState state = _getOrCreateResolutionState(librarySou rce);
9312 state.recordHintError();
9313 }
9314
9315 /**
9316 * Record that an error occurred while attempting to scan or parse the entry r epresented by this
9317 * entry. This will set the state of all information, including any resolution -based information,
9318 * as being in error.
9319 *
9320 * @param exception the exception that shows where the error occurred
9321 */
9322 void recordParseError(CaughtException exception) {
9323 _sourceKind = SourceKind.UNKNOWN;
9324 _sourceKindState = CacheState.ERROR;
9325 _parseErrors = AnalysisError.NO_ERRORS;
9326 _parseErrorsState = CacheState.ERROR;
9327 _parsedUnit = null;
9328 _parsedUnitAccessed = false;
9329 _parsedUnitState = CacheState.ERROR;
9330 _exportedLibraries = Source.EMPTY_ARRAY;
9331 _exportedLibrariesState = CacheState.ERROR;
9332 _importedLibraries = Source.EMPTY_ARRAY;
9333 _importedLibrariesState = CacheState.ERROR;
9334 _includedParts = Source.EMPTY_ARRAY;
9335 _includedPartsState = CacheState.ERROR;
9336 recordResolutionError(exception);
9337 }
9338
9339 /**
9340 * Record that the parse-related information for the associated source is abou t to be computed by
9341 * the current thread.
9342 */
9343 void recordParseInProcess() {
9344 if (_sourceKindState != CacheState.VALID) {
9345 _sourceKindState = CacheState.IN_PROCESS;
9346 }
9347 if (_parseErrorsState != CacheState.VALID) {
9348 _parseErrorsState = CacheState.IN_PROCESS;
9349 }
9350 if (_parsedUnitState != CacheState.VALID) {
9351 _parsedUnitState = CacheState.IN_PROCESS;
9352 }
9353 if (_exportedLibrariesState != CacheState.VALID) {
9354 _exportedLibrariesState = CacheState.IN_PROCESS;
9355 }
9356 if (_importedLibrariesState != CacheState.VALID) {
9357 _importedLibrariesState = CacheState.IN_PROCESS;
9358 }
9359 if (_includedPartsState != CacheState.VALID) {
9360 _includedPartsState = CacheState.IN_PROCESS;
9361 }
9362 }
9363
9364 /**
9365 * Record that an in-process parse has stopped without recording results becau se the results were
9366 * invalidated before they could be recorded.
9367 */
9368 void recordParseNotInProcess() {
9369 if (getState(SourceEntry.LINE_INFO) == CacheState.IN_PROCESS) {
9370 setState(SourceEntry.LINE_INFO, CacheState.INVALID);
9371 }
9372 if (_sourceKindState == CacheState.IN_PROCESS) {
9373 _sourceKindState = CacheState.INVALID;
9374 }
9375 if (_parseErrorsState == CacheState.IN_PROCESS) {
9376 _parseErrorsState = CacheState.INVALID;
9377 }
9378 if (_parsedUnitState == CacheState.IN_PROCESS) {
9379 _parsedUnitState = CacheState.INVALID;
9380 }
9381 if (_exportedLibrariesState == CacheState.IN_PROCESS) {
9382 _exportedLibrariesState = CacheState.INVALID;
9383 }
9384 if (_importedLibrariesState == CacheState.IN_PROCESS) {
9385 _importedLibrariesState = CacheState.INVALID;
9386 }
9387 if (_includedPartsState == CacheState.IN_PROCESS) {
9388 _includedPartsState = CacheState.INVALID;
9389 }
9390 }
9391
9392 /**
9393 * Record that an error occurred while attempting to resolve the source repres ented by this entry.
9394 * This will set the state of all resolution-based information as being in err or, but will not
9395 * change the state of any parse results.
9396 *
9397 * @param exception the exception that shows where the error occurred
9398 */
9399 void recordResolutionError(CaughtException exception) {
9400 this.exception = exception;
9401 _element = null;
9402 _elementState = CacheState.ERROR;
9403 clearFlags([_LAUNCHABLE_INDEX, _CLIENT_CODE_INDEX]);
9404 _clientServerState = CacheState.ERROR;
9405 _launchableState = CacheState.ERROR;
9406 _publicNamespace = null;
9407 _publicNamespaceState = CacheState.ERROR;
9408 _resolutionState.recordResolutionErrorsInAllLibraries();
9409 }
9410
9411 /**
9412 * Record that an error occurred while attempting to resolve the source repres ented by this entry.
9413 * This will set the state of all resolution-based information as being in err or, but will not
9414 * change the state of any parse results.
9415 *
9416 * @param librarySource the source of the library in which resolution was bein g performed
9417 * @param exception the exception that shows where the error occurred
9418 */
9419 void recordResolutionErrorInLibrary(Source librarySource, CaughtException exce ption) {
9420 this.exception = exception;
9421 _element = null;
9422 _elementState = CacheState.ERROR;
9423 clearFlags([_LAUNCHABLE_INDEX, _CLIENT_CODE_INDEX]);
9424 _clientServerState = CacheState.ERROR;
9425 _launchableState = CacheState.ERROR;
9426 _publicNamespace = null;
9427 _publicNamespaceState = CacheState.ERROR;
9428 DartEntryImpl_ResolutionState state = _getOrCreateResolutionState(librarySou rce);
9429 state.recordResolutionError();
9430 }
9431
9432 /**
9433 * Record that an in-process resolution has stopped without recording results because the results
9434 * were invalidated before they could be recorded.
9435 */
9436 void recordResolutionNotInProcess() {
9437 if (_elementState == CacheState.IN_PROCESS) {
9438 _elementState = CacheState.INVALID;
9439 }
9440 if (_clientServerState == CacheState.IN_PROCESS) {
9441 _clientServerState = CacheState.INVALID;
9442 }
9443 if (_launchableState == CacheState.IN_PROCESS) {
9444 _launchableState = CacheState.INVALID;
9445 }
9446 // TODO(brianwilkerson) Remove the code above this line after resolution and element building
9447 // are separated.
9448 if (_publicNamespaceState == CacheState.IN_PROCESS) {
9449 _publicNamespaceState = CacheState.INVALID;
9450 }
9451 _resolutionState.recordResolutionNotInProcess();
9452 }
9453
9454 /**
9455 * Record that an error occurred while attempting to scan or parse the entry r epresented by this
9456 * entry. This will set the state of all information, including any resolution -based information,
9457 * as being in error.
9458 *
9459 * @param exception the exception that shows where the error occurred
9460 */
9461 @override
9462 void recordScanError(CaughtException exception) {
9463 super.recordScanError(exception);
9464 _scanErrors = AnalysisError.NO_ERRORS;
9465 _scanErrorsState = CacheState.ERROR;
9466 _tokenStream = null;
9467 _tokenStreamState = CacheState.ERROR;
9468 recordParseError(exception);
9469 }
9470
9471 /**
9472 * Record that the scan-related information for the associated source is about to be computed by
9473 * the current thread.
9474 */
9475 void recordScanInProcess() {
9476 if (getState(SourceEntry.LINE_INFO) != CacheState.VALID) {
9477 setState(SourceEntry.LINE_INFO, CacheState.IN_PROCESS);
9478 }
9479 if (_scanErrorsState != CacheState.VALID) {
9480 _scanErrorsState = CacheState.IN_PROCESS;
9481 }
9482 if (_tokenStreamState != CacheState.VALID) {
9483 _tokenStreamState = CacheState.IN_PROCESS;
9484 }
9485 }
9486
9487 /**
9488 * Record that an in-process scan has stopped without recording results becaus e the results were
9489 * invalidated before they could be recorded.
9490 */
9491 void recordScanNotInProcess() {
9492 if (getState(SourceEntry.LINE_INFO) == CacheState.IN_PROCESS) {
9493 setState(SourceEntry.LINE_INFO, CacheState.INVALID);
9494 }
9495 if (_scanErrorsState == CacheState.IN_PROCESS) {
9496 _scanErrorsState = CacheState.INVALID;
9497 }
9498 if (_tokenStreamState == CacheState.IN_PROCESS) {
9499 _tokenStreamState = CacheState.INVALID;
9500 }
9501 }
9502
9503 /**
9504 * Record that an error occurred while attempting to generate errors and warni ngs for the source
9505 * represented by this entry. This will set the state of all verification info rmation as being in
9506 * error.
9507 *
9508 * @param librarySource the source of the library in which verification was be ing performed
9509 * @param exception the exception that shows where the error occurred
9510 */
9511 void recordVerificationErrorInLibrary(Source librarySource, CaughtException ex ception) {
9512 this.exception = exception;
9513 DartEntryImpl_ResolutionState state = _getOrCreateResolutionState(librarySou rce);
9514 state.recordVerificationError();
9515 }
9516
9517 /**
9518 * Remove the given library from the list of libraries that contain this part. This method should
9519 * only be invoked on entries that represent a part.
9520 *
9521 * @param librarySource the source of the library to be removed
9522 */
9523 void removeContainingLibrary(Source librarySource) {
9524 _containingLibraries.remove(librarySource);
9525 }
9526
9527 /**
9528 * Remove any resolution information associated with this compilation unit bei ng part of the given
9529 * library, presumably because it is no longer part of the library.
9530 *
9531 * @param librarySource the source of the defining compilation unit of the lib rary that used to
9532 * contain this part but no longer does
9533 */
9534 void removeResolution(Source librarySource) {
9535 if (librarySource != null) {
9536 if (librarySource == _resolutionState._librarySource) {
9537 if (_resolutionState._nextState == null) {
9538 _resolutionState.invalidateAllResolutionInformation();
9539 } else {
9540 _resolutionState = _resolutionState._nextState;
9541 }
9542 } else {
9543 DartEntryImpl_ResolutionState priorState = _resolutionState;
9544 DartEntryImpl_ResolutionState state = _resolutionState._nextState;
9545 while (state != null) {
9546 if (librarySource == state._librarySource) {
9547 priorState._nextState = state._nextState;
9548 break;
9549 }
9550 priorState = state;
9551 state = state._nextState;
9552 }
9553 }
9554 }
9555 }
9556
9557 /**
9558 * Set the list of libraries that contain this compilation unit to contain onl y the given source.
9559 * This method should only be invoked on entries that represent a library.
9560 *
9561 * @param librarySource the source of the single library that the list should contain
9562 */
9563 void set containingLibrary(Source librarySource) {
9564 _containingLibraries.clear();
9565 _containingLibraries.add(librarySource);
9566 }
9567
9568 @override
9569 void setState(DataDescriptor descriptor, CacheState state) {
9570 if (identical(descriptor, DartEntry.ELEMENT)) {
9571 _element = updatedValue(state, _element, null);
9572 _elementState = state;
9573 } else if (identical(descriptor, DartEntry.EXPORTED_LIBRARIES)) {
9574 _exportedLibraries = updatedValue(state, _exportedLibraries, Source.EMPTY_ ARRAY);
9575 _exportedLibrariesState = state;
9576 } else if (identical(descriptor, DartEntry.IMPORTED_LIBRARIES)) {
9577 _importedLibraries = updatedValue(state, _importedLibraries, Source.EMPTY_ ARRAY);
9578 _importedLibrariesState = state;
9579 } else if (identical(descriptor, DartEntry.INCLUDED_PARTS)) {
9580 _includedParts = updatedValue(state, _includedParts, Source.EMPTY_ARRAY);
9581 _includedPartsState = state;
9582 } else if (identical(descriptor, DartEntry.IS_CLIENT)) {
9583 _updateValueOfFlag(_CLIENT_CODE_INDEX, state);
9584 _clientServerState = state;
9585 } else if (identical(descriptor, DartEntry.IS_LAUNCHABLE)) {
9586 _updateValueOfFlag(_LAUNCHABLE_INDEX, state);
9587 _launchableState = state;
9588 } else if (identical(descriptor, DartEntry.PARSE_ERRORS)) {
9589 _parseErrors = updatedValue(state, _parseErrors, AnalysisError.NO_ERRORS);
9590 _parseErrorsState = state;
9591 } else if (identical(descriptor, DartEntry.PARSED_UNIT)) {
9592 CompilationUnit newUnit = updatedValue(state, _parsedUnit, null);
9593 if (!identical(newUnit, _parsedUnit)) {
9594 _parsedUnitAccessed = false;
9595 }
9596 _parsedUnit = newUnit;
9597 _parsedUnitState = state;
9598 } else if (identical(descriptor, DartEntry.PUBLIC_NAMESPACE)) {
9599 _publicNamespace = updatedValue(state, _publicNamespace, null);
9600 _publicNamespaceState = state;
9601 } else if (identical(descriptor, DartEntry.SCAN_ERRORS)) {
9602 _scanErrors = updatedValue(state, _scanErrors, AnalysisError.NO_ERRORS);
9603 _scanErrorsState = state;
9604 } else if (identical(descriptor, DartEntry.SOURCE_KIND)) {
9605 _sourceKind = updatedValue(state, _sourceKind, SourceKind.UNKNOWN);
9606 _sourceKindState = state;
9607 } else if (identical(descriptor, DartEntry.TOKEN_STREAM)) {
9608 _tokenStream = updatedValue(state, _tokenStream, null);
9609 _tokenStreamState = state;
9610 } else {
9611 super.setState(descriptor, state);
9612 }
9613 }
9614
9615 /**
9616 * Set the state of the data represented by the given descriptor in the contex t of the given
9617 * library to the given state.
9618 *
9619 * @param descriptor the descriptor representing the data whose state is to be set
9620 * @param librarySource the source of the defining compilation unit of the lib rary that is the
9621 * context for the data
9622 * @param cacheState the new state of the data represented by the given descri ptor
9623 */
9624 void setStateInLibrary(DataDescriptor descriptor, Source librarySource, CacheS tate cacheState) {
9625 DartEntryImpl_ResolutionState state = _getOrCreateResolutionState(librarySou rce);
9626 if (identical(descriptor, DartEntry.RESOLUTION_ERRORS)) {
9627 state._resolutionErrors = updatedValue(cacheState, state._resolutionErrors , AnalysisError.NO_ERRORS);
9628 state._resolutionErrorsState = cacheState;
9629 } else if (identical(descriptor, DartEntry.RESOLVED_UNIT)) {
9630 state._resolvedUnit = updatedValue(cacheState, state._resolvedUnit, null);
9631 state._resolvedUnitState = cacheState;
9632 } else if (identical(descriptor, DartEntry.VERIFICATION_ERRORS)) {
9633 state._verificationErrors = updatedValue(cacheState, state._verificationEr rors, AnalysisError.NO_ERRORS);
9634 state._verificationErrorsState = cacheState;
9635 } else if (identical(descriptor, DartEntry.HINTS)) {
9636 state._hints = updatedValue(cacheState, state._hints, AnalysisError.NO_ERR ORS);
9637 state._hintsState = cacheState;
9638 } else {
9639 throw new IllegalArgumentException("Invalid descriptor: ${descriptor}");
9640 }
9641 }
9642
9643 @override
9644 void setValue(DataDescriptor descriptor, Object value) {
9645 if (identical(descriptor, DartEntry.ANGULAR_ERRORS)) {
9646 _angularErrors = value == null ? AnalysisError.NO_ERRORS : (value as List< AnalysisError>);
9647 } else if (identical(descriptor, DartEntry.ELEMENT)) {
9648 _element = value as LibraryElement;
9649 _elementState = CacheState.VALID;
9650 } else if (identical(descriptor, DartEntry.EXPORTED_LIBRARIES)) {
9651 _exportedLibraries = value == null ? Source.EMPTY_ARRAY : (value as List<S ource>);
9652 _exportedLibrariesState = CacheState.VALID;
9653 } else if (identical(descriptor, DartEntry.IMPORTED_LIBRARIES)) {
9654 _importedLibraries = value == null ? Source.EMPTY_ARRAY : (value as List<S ource>);
9655 _importedLibrariesState = CacheState.VALID;
9656 } else if (identical(descriptor, DartEntry.INCLUDED_PARTS)) {
9657 _includedParts = value == null ? Source.EMPTY_ARRAY : (value as List<Sourc e>);
9658 _includedPartsState = CacheState.VALID;
9659 } else if (identical(descriptor, DartEntry.IS_CLIENT)) {
9660 setFlag(_CLIENT_CODE_INDEX, value as bool);
9661 _clientServerState = CacheState.VALID;
9662 } else if (identical(descriptor, DartEntry.IS_LAUNCHABLE)) {
9663 setFlag(_LAUNCHABLE_INDEX, value as bool);
9664 _launchableState = CacheState.VALID;
9665 } else if (identical(descriptor, DartEntry.PARSE_ERRORS)) {
9666 _parseErrors = value == null ? AnalysisError.NO_ERRORS : (value as List<An alysisError>);
9667 _parseErrorsState = CacheState.VALID;
9668 } else if (identical(descriptor, DartEntry.PARSED_UNIT)) {
9669 _parsedUnit = value as CompilationUnit;
9670 _parsedUnitAccessed = false;
9671 _parsedUnitState = CacheState.VALID;
9672 } else if (identical(descriptor, DartEntry.PUBLIC_NAMESPACE)) {
9673 _publicNamespace = value as Namespace;
9674 _publicNamespaceState = CacheState.VALID;
9675 } else if (identical(descriptor, DartEntry.SCAN_ERRORS)) {
9676 _scanErrors = value == null ? AnalysisError.NO_ERRORS : (value as List<Ana lysisError>);
9677 _scanErrorsState = CacheState.VALID;
9678 } else if (identical(descriptor, DartEntry.SOURCE_KIND)) {
9679 _sourceKind = value as SourceKind;
9680 _sourceKindState = CacheState.VALID;
9681 } else if (identical(descriptor, DartEntry.TOKEN_STREAM)) {
9682 _tokenStream = value as Token;
9683 _tokenStreamState = CacheState.VALID;
9684 } else {
9685 super.setValue(descriptor, value);
9686 }
9687 }
9688
9689 /**
9690 * Set the value of the data represented by the given descriptor in the contex t of the given
9691 * library to the given value, and set the state of that data to [CacheState#V ALID].
9692 *
9693 * @param descriptor the descriptor representing which data is to have its val ue set
9694 * @param librarySource the source of the defining compilation unit of the lib rary that is the
9695 * context for the data
9696 * @param value the new value of the data represented by the given descriptor and library
9697 */
9698 void setValueInLibrary(DataDescriptor descriptor, Source librarySource, Object value) {
9699 DartEntryImpl_ResolutionState state = _getOrCreateResolutionState(librarySou rce);
9700 if (identical(descriptor, DartEntry.RESOLUTION_ERRORS)) {
9701 state._resolutionErrors = value == null ? AnalysisError.NO_ERRORS : (value as List<AnalysisError>);
9702 state._resolutionErrorsState = CacheState.VALID;
9703 } else if (identical(descriptor, DartEntry.RESOLVED_UNIT)) {
9704 state._resolvedUnit = value as CompilationUnit;
9705 state._resolvedUnitState = CacheState.VALID;
9706 } else if (identical(descriptor, DartEntry.VERIFICATION_ERRORS)) {
9707 state._verificationErrors = value == null ? AnalysisError.NO_ERRORS : (val ue as List<AnalysisError>);
9708 state._verificationErrorsState = CacheState.VALID;
9709 } else if (identical(descriptor, DartEntry.HINTS)) {
9710 state._hints = value == null ? AnalysisError.NO_ERRORS : (value as List<An alysisError>);
9711 state._hintsState = CacheState.VALID;
9712 }
9713 }
9714
9715 @override
9716 void copyFrom(SourceEntryImpl entry) {
9717 super.copyFrom(entry);
9718 DartEntryImpl other = entry as DartEntryImpl;
9719 _scanErrorsState = other._scanErrorsState;
9720 _scanErrors = other._scanErrors;
9721 _tokenStreamState = other._tokenStreamState;
9722 _tokenStream = other._tokenStream;
9723 _sourceKindState = other._sourceKindState;
9724 _sourceKind = other._sourceKind;
9725 _parsedUnitState = other._parsedUnitState;
9726 _parsedUnit = other._parsedUnit;
9727 _parsedUnitAccessed = other._parsedUnitAccessed;
9728 _parseErrorsState = other._parseErrorsState;
9729 _parseErrors = other._parseErrors;
9730 _includedPartsState = other._includedPartsState;
9731 _includedParts = other._includedParts;
9732 _exportedLibrariesState = other._exportedLibrariesState;
9733 _exportedLibraries = other._exportedLibraries;
9734 _importedLibrariesState = other._importedLibrariesState;
9735 _importedLibraries = other._importedLibraries;
9736 _containingLibraries = new List<Source>.from(other._containingLibraries);
9737 _resolutionState.copyFrom(other._resolutionState);
9738 _elementState = other._elementState;
9739 _element = other._element;
9740 _publicNamespaceState = other._publicNamespaceState;
9741 _publicNamespace = other._publicNamespace;
9742 _clientServerState = other._clientServerState;
9743 _launchableState = other._launchableState;
9744 _angularErrors = other._angularErrors;
9745 }
9746
9747 @override
9748 bool get hasErrorState => super.hasErrorState || _scanErrorsState == CacheStat e.ERROR || _tokenStreamState == CacheState.ERROR || _sourceKindState == CacheSta te.ERROR || _parsedUnitState == CacheState.ERROR || _parseErrorsState == CacheSt ate.ERROR || _importedLibrariesState == CacheState.ERROR || _exportedLibrariesSt ate == CacheState.ERROR || _includedPartsState == CacheState.ERROR || _elementSt ate == CacheState.ERROR || _publicNamespaceState == CacheState.ERROR || _clientS erverState == CacheState.ERROR || _launchableState == CacheState.ERROR || _resol utionState.hasErrorState;
9749
9750 @override
9751 bool writeDiffOn(JavaStringBuilder builder, SourceEntry oldEntry) {
9752 bool needsSeparator = super.writeDiffOn(builder, oldEntry);
9753 if (oldEntry is! DartEntryImpl) {
9754 if (needsSeparator) {
9755 builder.append("; ");
9756 }
9757 builder.append("entry type changed; was ${oldEntry.runtimeType.toString()} ");
9758 return true;
9759 }
9760 needsSeparator = writeStateDiffOn(builder, needsSeparator, oldEntry, DartEnt ry.TOKEN_STREAM, "tokenStream");
9761 needsSeparator = writeStateDiffOn(builder, needsSeparator, oldEntry, DartEnt ry.SCAN_ERRORS, "scanErrors");
9762 needsSeparator = writeStateDiffOn(builder, needsSeparator, oldEntry, DartEnt ry.SOURCE_KIND, "sourceKind");
9763 needsSeparator = writeStateDiffOn(builder, needsSeparator, oldEntry, DartEnt ry.PARSED_UNIT, "parsedUnit");
9764 needsSeparator = writeStateDiffOn(builder, needsSeparator, oldEntry, DartEnt ry.PARSE_ERRORS, "parseErrors");
9765 needsSeparator = writeStateDiffOn(builder, needsSeparator, oldEntry, DartEnt ry.IMPORTED_LIBRARIES, "importedLibraries");
9766 needsSeparator = writeStateDiffOn(builder, needsSeparator, oldEntry, DartEnt ry.EXPORTED_LIBRARIES, "exportedLibraries");
9767 needsSeparator = writeStateDiffOn(builder, needsSeparator, oldEntry, DartEnt ry.INCLUDED_PARTS, "includedParts");
9768 needsSeparator = writeStateDiffOn(builder, needsSeparator, oldEntry, DartEnt ry.ELEMENT, "element");
9769 needsSeparator = writeStateDiffOn(builder, needsSeparator, oldEntry, DartEnt ry.PUBLIC_NAMESPACE, "publicNamespace");
9770 needsSeparator = writeStateDiffOn(builder, needsSeparator, oldEntry, DartEnt ry.IS_CLIENT, "clientServer");
9771 needsSeparator = writeStateDiffOn(builder, needsSeparator, oldEntry, DartEnt ry.IS_LAUNCHABLE, "launchable");
9772 // TODO(brianwilkerson) Add better support for containingLibraries. It would be nice to be able
9773 // to report on size-preserving changes.
9774 int oldLibraryCount = (oldEntry as DartEntryImpl)._containingLibraries.lengt h;
9775 int libraryCount = _containingLibraries.length;
9776 if (oldLibraryCount != libraryCount) {
9777 if (needsSeparator) {
9778 builder.append("; ");
9779 }
9780 builder.append("containingLibraryCount = ");
9781 builder.append(oldLibraryCount);
9782 builder.append(" -> ");
9783 builder.append(libraryCount);
9784 needsSeparator = true;
9785 }
9786 //
9787 // Report change to the per-library state.
9788 //
9789 HashMap<Source, DartEntryImpl_ResolutionState> oldStateMap = new HashMap<Sou rce, DartEntryImpl_ResolutionState>();
9790 DartEntryImpl_ResolutionState state = (oldEntry as DartEntryImpl)._resolutio nState;
9791 while (state != null) {
9792 Source librarySource = state._librarySource;
9793 if (librarySource != null) {
9794 oldStateMap[librarySource] = state;
9795 }
9796 state = state._nextState;
9797 }
9798 state = _resolutionState;
9799 while (state != null) {
9800 Source librarySource = state._librarySource;
9801 if (librarySource != null) {
9802 DartEntryImpl_ResolutionState oldState = oldStateMap.remove(librarySourc e);
9803 if (oldState == null) {
9804 if (needsSeparator) {
9805 builder.append("; ");
9806 }
9807 builder.append("added resolution for ");
9808 builder.append(librarySource.fullName);
9809 needsSeparator = true;
9810 } else {
9811 needsSeparator = oldState.writeDiffOn(builder, needsSeparator, oldEntr y as DartEntry);
9812 }
9813 }
9814 state = state._nextState;
9815 }
9816 for (Source librarySource in oldStateMap.keys.toSet()) {
9817 if (needsSeparator) {
9818 builder.append("; ");
9819 }
9820 builder.append("removed resolution for ");
9821 builder.append(librarySource.fullName);
9822 needsSeparator = true;
9823 }
9824 return needsSeparator;
9825 }
9826
9827 @override
9828 void writeOn(JavaStringBuilder builder) {
9829 builder.append("Dart: ");
9830 super.writeOn(builder);
9831 builder.append("; tokenStream = ");
9832 builder.append(_tokenStreamState);
9833 builder.append("; scanErrors = ");
9834 builder.append(_scanErrorsState);
9835 builder.append("; sourceKind = ");
9836 builder.append(_sourceKindState);
9837 builder.append("; parsedUnit = ");
9838 builder.append(_parsedUnitState);
9839 builder.append(" (");
9840 builder.append(_parsedUnitAccessed ? "T" : "F");
9841 builder.append("); parseErrors = ");
9842 builder.append(_parseErrorsState);
9843 builder.append("; exportedLibraries = ");
9844 builder.append(_exportedLibrariesState);
9845 builder.append("; importedLibraries = ");
9846 builder.append(_importedLibrariesState);
9847 builder.append("; includedParts = ");
9848 builder.append(_includedPartsState);
9849 builder.append("; element = ");
9850 builder.append(_elementState);
9851 builder.append("; publicNamespace = ");
9852 builder.append(_publicNamespaceState);
9853 builder.append("; clientServer = ");
9854 builder.append(_clientServerState);
9855 builder.append("; launchable = ");
9856 builder.append(_launchableState);
9857 // builder.append("; angularElements = ");
9858 _resolutionState.writeOn(builder);
9859 }
9860
9861 /**
9862 * Invalidate all of the resolution information associated with the compilatio n unit.
9863 *
9864 * @param invalidateUris true if the cached results of converting URIs to sour ce files should also
9865 * be invalidated.
9866 */
9867 void _discardCachedResolutionInformation(bool invalidateUris) {
9868 _element = null;
9869 _elementState = CacheState.INVALID;
9870 clearFlags([_LAUNCHABLE_INDEX, _CLIENT_CODE_INDEX]);
9871 _clientServerState = CacheState.INVALID;
9872 _launchableState = CacheState.INVALID;
9873 _publicNamespace = null;
9874 _publicNamespaceState = CacheState.INVALID;
9875 _resolutionState.invalidateAllResolutionInformation();
9876 if (invalidateUris) {
9877 _importedLibraries = Source.EMPTY_ARRAY;
9878 _importedLibrariesState = CacheState.INVALID;
9879 _exportedLibraries = Source.EMPTY_ARRAY;
9880 _exportedLibrariesState = CacheState.INVALID;
9881 _includedParts = Source.EMPTY_ARRAY;
9882 _includedPartsState = CacheState.INVALID;
9883 }
9884 }
9885
9886 /**
9887 * Return a resolution state for the specified library, creating one as necess ary.
9888 *
9889 * @param librarySource the library source (not `null`)
9890 * @return the resolution state (not `null`)
9891 */
9892 DartEntryImpl_ResolutionState _getOrCreateResolutionState(Source librarySource ) {
9893 DartEntryImpl_ResolutionState state = _resolutionState;
9894 if (state._librarySource == null) {
9895 state._librarySource = librarySource;
9896 return state;
9897 }
9898 while (state._librarySource != librarySource) {
9899 if (state._nextState == null) {
9900 DartEntryImpl_ResolutionState newState = new DartEntryImpl_ResolutionSta te();
9901 newState._librarySource = librarySource;
9902 state._nextState = newState;
9903 return newState;
9904 }
9905 state = state._nextState;
9906 }
9907 return state;
9908 }
9909
9910 /**
9911 * Given that the specified flag is being transitioned to the given state, set the value of the
9912 * flag to the value that should be kept in the cache.
9913 *
9914 * @param index the index of the flag whose state is being set
9915 * @param state the state to which the value is being transitioned
9916 */
9917 void _updateValueOfFlag(int index, CacheState state) {
9918 if (state == CacheState.VALID) {
9919 throw new IllegalArgumentException("Use setValue() to set the state to VAL ID");
9920 } else if (state != CacheState.IN_PROCESS) {
9921 //
9922 // If the value is in process, we can leave the current value in the cache for any 'get'
9923 // methods to access.
9924 //
9925 setFlag(index, false);
9926 }
9927 }
9928 }
9929
9930 /**
9931 * Instances of the class `ResolutionState` represent the information produced b y resolving
9932 * a compilation unit as part of a specific library.
9933 */
9934 class DartEntryImpl_ResolutionState {
9935 /**
9936 * The next resolution state or `null` if none.
9937 */
9938 DartEntryImpl_ResolutionState _nextState;
9939
9940 /**
9941 * The source for the defining compilation unit of the library that contains t his unit. If this
9942 * unit is the defining compilation unit for it's library, then this will be t he source for this
9943 * unit.
9944 */
9945 Source _librarySource;
9946
9947 /**
9948 * The state of the cached compilation unit that contains references to the bu ilt element model.
9949 */
9950 CacheState _builtUnitState = CacheState.INVALID;
9951
9952 /**
9953 * The compilation unit that contains references to the built element model, o r `null` if
9954 * that compilation unit is not currently cached.
9955 */
9956 CompilationUnit _builtUnit;
9957
9958 /**
9959 * The state of the cached errors reported while building an element model.
9960 */
9961 CacheState _buildElementErrorsState = CacheState.INVALID;
9962
9963 /**
9964 * The errors produced while building an element model, or an empty array if t he errors are not
9965 * currently cached.
9966 */
9967 List<AnalysisError> _buildElementErrors = AnalysisError.NO_ERRORS;
9968
9969 /**
9970 * The state of the cached resolved compilation unit.
9971 */
9972 CacheState _resolvedUnitState = CacheState.INVALID;
9973
9974 /**
9975 * The resolved compilation unit, or `null` if the resolved compilation unit i s not
9976 * currently cached.
9977 */
9978 CompilationUnit _resolvedUnit;
9979
9980 /**
9981 * The state of the cached resolution errors.
9982 */
9983 CacheState _resolutionErrorsState = CacheState.INVALID;
9984
9985 /**
9986 * The errors produced while resolving the compilation unit, or an empty array if the errors are
9987 * not currently cached.
9988 */
9989 List<AnalysisError> _resolutionErrors = AnalysisError.NO_ERRORS;
9990
9991 /**
9992 * The state of the cached verification errors.
9993 */
9994 CacheState _verificationErrorsState = CacheState.INVALID;
9995
9996 /**
9997 * The errors produced while verifying the compilation unit, or an empty array if the errors are
9998 * not currently cached.
9999 */
10000 List<AnalysisError> _verificationErrors = AnalysisError.NO_ERRORS;
10001
10002 /**
10003 * The state of the cached hints.
10004 */
10005 CacheState _hintsState = CacheState.INVALID;
10006
10007 /**
10008 * The hints produced while auditing the compilation unit, or an empty array i f the hints are
10009 * not currently cached.
10010 */
10011 List<AnalysisError> _hints = AnalysisError.NO_ERRORS;
10012
10013 /**
10014 * Set this state to be exactly like the given state, recursively copying the next state as
10015 * necessary.
10016 *
10017 * @param other the state to be copied
10018 */
10019 void copyFrom(DartEntryImpl_ResolutionState other) {
10020 _librarySource = other._librarySource;
10021 _builtUnitState = other._builtUnitState;
10022 _builtUnit = other._builtUnit;
10023 _buildElementErrorsState = other._buildElementErrorsState;
10024 _buildElementErrors = other._buildElementErrors;
10025 _resolvedUnitState = other._resolvedUnitState;
10026 _resolvedUnit = other._resolvedUnit;
10027 _resolutionErrorsState = other._resolutionErrorsState;
10028 _resolutionErrors = other._resolutionErrors;
10029 _verificationErrorsState = other._verificationErrorsState;
10030 _verificationErrors = other._verificationErrors;
10031 _hintsState = other._hintsState;
10032 _hints = other._hints;
10033 if (other._nextState != null) {
10034 _nextState = new DartEntryImpl_ResolutionState();
10035 _nextState.copyFrom(other._nextState);
10036 }
10037 }
10038
10039 /**
10040 * Flush any AST structures being maintained by this state.
10041 */
10042 void flushAstStructures() {
10043 if (_builtUnitState == CacheState.VALID) {
10044 _builtUnitState = CacheState.FLUSHED;
10045 _builtUnit = null;
10046 }
10047 if (_resolvedUnitState == CacheState.VALID) {
10048 _resolvedUnitState = CacheState.FLUSHED;
10049 _resolvedUnit = null;
10050 }
10051 if (_nextState != null) {
10052 _nextState.flushAstStructures();
10053 }
10054 }
10055
10056 bool get hasErrorState => _builtUnitState == CacheState.ERROR || _buildElement ErrorsState == CacheState.ERROR || _resolvedUnitState == CacheState.ERROR || _re solutionErrorsState == CacheState.ERROR || _verificationErrorsState == CacheStat e.ERROR || _hintsState == CacheState.ERROR || (_nextState != null && _nextState. hasErrorState);
10057
10058 /**
10059 * Invalidate all of the resolution information associated with the compilatio n unit.
10060 */
10061 void invalidateAllResolutionInformation() {
10062 _nextState = null;
10063 _librarySource = null;
10064 _builtUnitState = CacheState.INVALID;
10065 _builtUnit = null;
10066 _buildElementErrorsState = CacheState.INVALID;
10067 _buildElementErrors = AnalysisError.NO_ERRORS;
10068 _resolvedUnitState = CacheState.INVALID;
10069 _resolvedUnit = null;
10070 _resolutionErrorsState = CacheState.INVALID;
10071 _resolutionErrors = AnalysisError.NO_ERRORS;
10072 _verificationErrorsState = CacheState.INVALID;
10073 _verificationErrors = AnalysisError.NO_ERRORS;
10074 _hintsState = CacheState.INVALID;
10075 _hints = AnalysisError.NO_ERRORS;
10076 }
10077
10078 /**
10079 * Record that an error occurred while attempting to build the element model f or the source
10080 * represented by this state.
10081 */
10082 void recordBuildElementError() {
10083 _builtUnitState = CacheState.ERROR;
10084 _builtUnit = null;
10085 _buildElementErrorsState = CacheState.ERROR;
10086 _buildElementErrors = AnalysisError.NO_ERRORS;
10087 recordResolutionError();
10088 }
10089
10090 /**
10091 * Record that an error occurred while attempting to generate hints for the so urce represented
10092 * by this entry. This will set the state of all verification information as b eing in error.
10093 */
10094 void recordHintError() {
10095 _hints = AnalysisError.NO_ERRORS;
10096 _hintsState = CacheState.ERROR;
10097 }
10098
10099 /**
10100 * Record that an error occurred while attempting to resolve the source repres ented by this
10101 * state.
10102 */
10103 void recordResolutionError() {
10104 _resolvedUnitState = CacheState.ERROR;
10105 _resolvedUnit = null;
10106 _resolutionErrorsState = CacheState.ERROR;
10107 _resolutionErrors = AnalysisError.NO_ERRORS;
10108 recordVerificationError();
10109 }
10110
10111 /**
10112 * Record that an error occurred while attempting to scan or parse the entry r epresented by this
10113 * entry. This will set the state of all resolution-based information as being in error, but
10114 * will not change the state of any parse results.
10115 */
10116 void recordResolutionErrorsInAllLibraries() {
10117 _builtUnitState = CacheState.ERROR;
10118 _builtUnit = null;
10119 _buildElementErrorsState = CacheState.ERROR;
10120 _buildElementErrors = AnalysisError.NO_ERRORS;
10121 _resolvedUnitState = CacheState.ERROR;
10122 _resolvedUnit = null;
10123 _resolutionErrorsState = CacheState.ERROR;
10124 _resolutionErrors = AnalysisError.NO_ERRORS;
10125 recordVerificationError();
10126 if (_nextState != null) {
10127 _nextState.recordResolutionErrorsInAllLibraries();
10128 }
10129 }
10130
10131 /**
10132 * Record that an in-process parse has stopped without recording results becau se the results
10133 * were invalidated before they could be recorded.
10134 */
10135 void recordResolutionNotInProcess() {
10136 if (_resolvedUnitState == CacheState.IN_PROCESS) {
10137 _resolvedUnitState = CacheState.INVALID;
10138 }
10139 if (_resolutionErrorsState == CacheState.IN_PROCESS) {
10140 _resolutionErrorsState = CacheState.INVALID;
10141 }
10142 if (_verificationErrorsState == CacheState.IN_PROCESS) {
10143 _verificationErrorsState = CacheState.INVALID;
10144 }
10145 if (_hintsState == CacheState.IN_PROCESS) {
10146 _hintsState = CacheState.INVALID;
10147 }
10148 if (_nextState != null) {
10149 _nextState.recordResolutionNotInProcess();
10150 }
10151 }
10152
10153 /**
10154 * Record that an error occurred while attempting to generate errors and warni ngs for the source
10155 * represented by this entry. This will set the state of all verification info rmation as being
10156 * in error.
10157 */
10158 void recordVerificationError() {
10159 _verificationErrors = AnalysisError.NO_ERRORS;
10160 _verificationErrorsState = CacheState.ERROR;
10161 recordHintError();
10162 }
10163
10164 /**
10165 * Write a textual representation of the difference between the old entry and this entry to the
10166 * given string builder.
10167 *
10168 * @param builder the string builder to which the difference is to be written
10169 * @param oldEntry the entry that was replaced by this entry
10170 * @return `true` if some difference was written
10171 */
10172 bool writeDiffOn(JavaStringBuilder builder, bool needsSeparator, DartEntry old Entry) {
10173 needsSeparator = writeStateDiffOn(builder, needsSeparator, oldEntry, DartEnt ry.RESOLVED_UNIT, _resolvedUnitState, "resolvedUnit");
10174 needsSeparator = writeStateDiffOn(builder, needsSeparator, oldEntry, DartEnt ry.RESOLUTION_ERRORS, _resolutionErrorsState, "resolutionErrors");
10175 needsSeparator = writeStateDiffOn(builder, needsSeparator, oldEntry, DartEnt ry.VERIFICATION_ERRORS, _verificationErrorsState, "verificationErrors");
10176 needsSeparator = writeStateDiffOn(builder, needsSeparator, oldEntry, DartEnt ry.HINTS, _hintsState, "hints");
10177 return needsSeparator;
10178 }
10179
10180 /**
10181 * Write a textual representation of this state to the given builder. The resu lt will only be
10182 * used for debugging purposes.
10183 *
10184 * @param builder the builder to which the text should be written
10185 */
10186 void writeOn(JavaStringBuilder builder) {
10187 if (_librarySource != null) {
10188 builder.append("; builtUnit = ");
10189 builder.append(_builtUnitState);
10190 builder.append("; buildElementErrors = ");
10191 builder.append(_buildElementErrorsState);
10192 builder.append("; resolvedUnit = ");
10193 builder.append(_resolvedUnitState);
10194 builder.append("; resolutionErrors = ");
10195 builder.append(_resolutionErrorsState);
10196 builder.append("; verificationErrors = ");
10197 builder.append(_verificationErrorsState);
10198 builder.append("; hints = ");
10199 builder.append(_hintsState);
10200 if (_nextState != null) {
10201 _nextState.writeOn(builder);
10202 }
10203 }
10204 }
10205
10206 /**
10207 * Write a textual representation of the difference between the state of the s pecified data
10208 * between the old entry and this entry to the given string builder.
10209 *
10210 * @param builder the string builder to which the difference is to be written
10211 * @param needsSeparator `true` if any data that is written
10212 * @param oldEntry the entry that was replaced by this entry
10213 * @param descriptor the descriptor defining the data whose state is being com pared
10214 * @param label the label used to describe the state
10215 * @return `true` if some difference was written
10216 */
10217 bool writeStateDiffOn(JavaStringBuilder builder, bool needsSeparator, SourceEn try oldEntry, DataDescriptor descriptor, CacheState newState, String label) {
10218 CacheState oldState = (oldEntry as DartEntryImpl).getStateInLibrary(descript or, _librarySource);
10219 if (oldState != newState) {
10220 if (needsSeparator) {
10221 builder.append("; ");
10222 }
10223 builder.append(label);
10224 builder.append(" = ");
10225 builder.append(oldState);
10226 builder.append(" -> ");
10227 builder.append(newState);
10228 return true;
10229 }
10230 return needsSeparator;
10231 }
10232 }
10233
10234 /**
10235 * Instances of the class `DataDescriptor` are immutable constants representing data that can
10236 * be stored in the cache.
10237 */
10238 class DataDescriptor<E> {
10239 /**
10240 * The name of the descriptor, used for debugging purposes.
10241 */
10242 final String _name;
10243
10244 /**
10245 * Initialize a newly created descriptor to have the given name.
10246 *
10247 * @param name the name of the descriptor
10248 */
10249 DataDescriptor(this._name);
10250
10251 @override
10252 String toString() => _name;
10253 }
10254
10255 /**
10256 * Instances of the class `DefaultRetentionPolicy` implement a retention policy that will keep
10257 * AST's in the cache if there is analysis information that needs to be computed for a source, where
10258 * the computation is dependent on having the AST.
10259 */
10260 class DefaultRetentionPolicy implements CacheRetentionPolicy {
10261 /**
10262 * An instance of this class that can be shared.
10263 */
10264 static DefaultRetentionPolicy POLICY = new DefaultRetentionPolicy();
10265
10266 @override
10267 RetentionPriority getAstPriority(Source source, SourceEntry sourceEntry) {
10268 if (sourceEntry is DartEntry) {
10269 DartEntry dartEntry = sourceEntry;
10270 if (astIsNeeded(dartEntry)) {
10271 return RetentionPriority.MEDIUM;
10272 }
10273 }
10274 return RetentionPriority.LOW;
10275 }
10276
10277 /**
10278 * Return `true` if there is analysis information in the given entry that need s to be
10279 * computed, where the computation is dependent on having the AST.
10280 *
10281 * @param dartEntry the entry being tested
10282 * @return `true` if there is analysis information that needs to be computed f rom the AST
10283 */
10284 bool astIsNeeded(DartEntry dartEntry) => dartEntry.hasInvalidData(DartEntry.HI NTS) || dartEntry.hasInvalidData(DartEntry.VERIFICATION_ERRORS) || dartEntry.has InvalidData(DartEntry.RESOLUTION_ERRORS);
10285 }
10286
10287 /**
10288 * Recursively visits [HtmlUnit] and every embedded [Expression].
10289 */
10290 abstract class ExpressionVisitor extends ht.RecursiveXmlVisitor<Object> {
10291 /**
10292 * Visits the given [Expression]s embedded into tag or attribute.
10293 *
10294 * @param expression the [Expression] to visit, not `null`
10295 */
10296 void visitExpression(Expression expression);
10297
10298 @override
10299 Object visitXmlAttributeNode(ht.XmlAttributeNode node) {
10300 _visitExpressions(node.expressions);
10301 return super.visitXmlAttributeNode(node);
10302 }
10303
10304 @override
10305 Object visitXmlTagNode(ht.XmlTagNode node) {
10306 _visitExpressions(node.expressions);
10307 return super.visitXmlTagNode(node);
10308 }
10309
10310 /**
10311 * Visits [Expression]s of the given [XmlExpression]s.
10312 */
10313 void _visitExpressions(List<ht.XmlExpression> expressions) {
10314 for (ht.XmlExpression xmlExpression in expressions) {
10315 if (xmlExpression is AngularXmlExpression) {
10316 AngularXmlExpression angularXmlExpression = xmlExpression;
10317 List<Expression> dartExpressions = angularXmlExpression.expression.expre ssions;
10318 for (Expression dartExpression in dartExpressions) {
10319 visitExpression(dartExpression);
10320 }
10321 }
10322 if (xmlExpression is ht.RawXmlExpression) {
10323 ht.RawXmlExpression rawXmlExpression = xmlExpression;
10324 visitExpression(rawXmlExpression.expression);
10325 }
10326 }
10327 }
10328 }
10329
10330 /**
10331 * Instances of the class `GenerateDartErrorsTask` generate errors and warnings for a single
10332 * Dart source.
10333 */
10334 class GenerateDartErrorsTask extends AnalysisTask {
10335 /**
10336 * Check each directive in the given compilation unit to see if the referenced source exists and
10337 * report an error if it does not.
10338 *
10339 * @param context the context in which the library exists
10340 * @param librarySource the source representing the library containing the dir ectives
10341 * @param unit the compilation unit containing the directives to be validated
10342 * @param errorListener the error listener to which errors should be reported
10343 */
10344 static void validateDirectives(AnalysisContext context, Source librarySource, CompilationUnit unit, AnalysisErrorListener errorListener) {
10345 for (Directive directive in unit.directives) {
10346 if (directive is UriBasedDirective) {
10347 validateReferencedSource(context, librarySource, directive, errorListene r);
10348 }
10349 }
10350 }
10351
10352 /**
10353 * Check the given directive to see if the referenced source exists and report an error if it does
10354 * not.
10355 *
10356 * @param context the context in which the library exists
10357 * @param librarySource the source representing the library containing the dir ective
10358 * @param directive the directive to be verified
10359 * @param errorListener the error listener to which errors should be reported
10360 */
10361 static void validateReferencedSource(AnalysisContext context, Source librarySo urce, UriBasedDirective directive, AnalysisErrorListener errorListener) {
10362 Source source = directive.source;
10363 if (source != null) {
10364 if (context.exists(source)) {
10365 return;
10366 }
10367 } else {
10368 // Don't report errors already reported by ParseDartTask#resolveDirective
10369 if (directive.validate() != null) {
10370 return;
10371 }
10372 }
10373 StringLiteral uriLiteral = directive.uri;
10374 errorListener.onError(new AnalysisError.con2(librarySource, uriLiteral.offse t, uriLiteral.length, CompileTimeErrorCode.URI_DOES_NOT_EXIST, [directive.uriCon tent]));
10375 }
10376
10377 /**
10378 * The source for which errors and warnings are to be produced.
10379 */
10380 final Source source;
10381
10382 /**
10383 * The time at which the contents of the source were last modified.
10384 */
10385 final int modificationTime;
10386
10387 /**
10388 * The compilation unit used to resolve the dependencies.
10389 */
10390 final CompilationUnit _unit;
10391
10392 /**
10393 * The element model for the library containing the source.
10394 */
10395 final LibraryElement libraryElement;
10396
10397 /**
10398 * The errors that were generated for the source.
10399 */
10400 List<AnalysisError> _errors;
10401
10402 /**
10403 * Initialize a newly created task to perform analysis within the given contex t.
10404 *
10405 * @param context the context in which the task is to be performed
10406 * @param source the source for which errors and warnings are to be produced
10407 * @param modificationTime the time at which the contents of the source were l ast modified
10408 * @param unit the compilation unit used to resolve the dependencies
10409 * @param libraryElement the element model for the library containing the sour ce
10410 */
10411 GenerateDartErrorsTask(InternalAnalysisContext context, this.source, this.modi ficationTime, this._unit, this.libraryElement) : super(context);
10412
10413 @override
10414 accept(AnalysisTaskVisitor visitor) => visitor.visitGenerateDartErrorsTask(thi s);
10415
10416 /**
10417 * Return the errors that were generated for the source.
10418 *
10419 * @return the errors that were generated for the source
10420 */
10421 List<AnalysisError> get errors => _errors;
10422
10423 @override
10424 String get taskDescription => "generate errors and warnings for ${source.fullN ame}";
10425
10426 @override
10427 void internalPerform() {
10428 TimeCounter_TimeCounterHandle timeCounter = PerformanceStatistics.errors.sta rt();
10429 try {
10430 RecordingErrorListener errorListener = new RecordingErrorListener();
10431 ErrorReporter errorReporter = new ErrorReporter(errorListener, source);
10432 TypeProvider typeProvider = context.typeProvider;
10433 //
10434 // Validate the directives
10435 //
10436 validateDirectives(context, source, _unit, errorListener);
10437 //
10438 // Use the ConstantVerifier to verify the use of constants. This needs to happen before using
10439 // the ErrorVerifier because some error codes need the computed constant v alues.
10440 //
10441 ConstantVerifier constantVerifier = new ConstantVerifier(errorReporter, li braryElement, typeProvider);
10442 _unit.accept(constantVerifier);
10443 //
10444 // Use the ErrorVerifier to compute the rest of the errors.
10445 //
10446 ErrorVerifier errorVerifier = new ErrorVerifier(errorReporter, libraryElem ent, typeProvider, new InheritanceManager(libraryElement));
10447 _unit.accept(errorVerifier);
10448 _errors = errorListener.getErrorsForSource(source);
10449 } finally {
10450 timeCounter.stop();
10451 }
10452 }
10453 }
10454
10455 /**
10456 * Instances of the class `GenerateDartHintsTask` generate hints for a single Da rt library.
10457 */
10458 class GenerateDartHintsTask extends AnalysisTask {
10459 /**
10460 * The compilation units that comprise the library, with the defining compilat ion unit appearing
10461 * first in the array.
10462 */
10463 final List<TimestampedData<CompilationUnit>> _units;
10464
10465 /**
10466 * The element model for the library being analyzed.
10467 */
10468 final LibraryElement libraryElement;
10469
10470 /**
10471 * A table mapping the sources that were analyzed to the hints that were gener ated for the
10472 * sources.
10473 */
10474 HashMap<Source, TimestampedData<List<AnalysisError>>> _hintMap;
10475
10476 /**
10477 * Initialize a newly created task to perform analysis within the given contex t.
10478 *
10479 * @param context the context in which the task is to be performed
10480 * @param units the compilation units that comprise the library, with the defi ning compilation
10481 * unit appearing first in the array
10482 * @param libraryElement the element model for the library being analyzed
10483 */
10484 GenerateDartHintsTask(InternalAnalysisContext context, this._units, this.libra ryElement) : super(context);
10485
10486 @override
10487 accept(AnalysisTaskVisitor visitor) => visitor.visitGenerateDartHintsTask(this );
10488
10489 /**
10490 * Return a table mapping the sources that were analyzed to the hints that wer e generated for the
10491 * sources, or `null` if the task has not been performed or if the analysis di d not complete
10492 * normally.
10493 *
10494 * @return a table mapping the sources that were analyzed to the hints that we re generated for the
10495 * sources
10496 */
10497 HashMap<Source, TimestampedData<List<AnalysisError>>> get hintMap => _hintMap;
10498
10499 @override
10500 String get taskDescription {
10501 Source librarySource = libraryElement.source;
10502 if (librarySource == null) {
10503 return "generate Dart hints for library without source";
10504 }
10505 return "generate Dart hints for ${librarySource.fullName}";
10506 }
10507
10508 @override
10509 void internalPerform() {
10510 //
10511 // Gather the compilation units.
10512 //
10513 int unitCount = _units.length;
10514 List<CompilationUnit> compilationUnits = new List<CompilationUnit>(unitCount );
10515 for (int i = 0; i < unitCount; i++) {
10516 compilationUnits[i] = _units[i].data;
10517 }
10518 //
10519 // Analyze all of the units.
10520 //
10521 RecordingErrorListener errorListener = new RecordingErrorListener();
10522 HintGenerator hintGenerator = new HintGenerator(compilationUnits, context, e rrorListener);
10523 hintGenerator.generateForLibrary();
10524 //
10525 // Store the results.
10526 //
10527 _hintMap = new HashMap<Source, TimestampedData<List<AnalysisError>>>();
10528 for (int i = 0; i < unitCount; i++) {
10529 int modificationTime = _units[i].modificationTime;
10530 Source source = _units[i].data.element.source;
10531 List<AnalysisError> errors = errorListener.getErrorsForSource(source);
10532 _hintMap[source] = new TimestampedData<List<AnalysisError>>(modificationTi me, errors);
10533 }
10534 }
10535 }
10536
10537 /**
10538 * Instances of the class `GetContentTask` get the contents of a source.
10539 */
10540 class GetContentTask extends AnalysisTask {
10541 /**
10542 * The source to be read.
10543 */
10544 final Source source;
10545
10546 /**
10547 * A flag indicating whether this task is complete.
10548 */
10549 bool _complete = false;
10550
10551 /**
10552 * The contents of the source.
10553 */
10554 String _content;
10555
10556 /**
10557 * The time at which the contents of the source were last modified.
10558 */
10559 int _modificationTime = -1;
10560
10561 /**
10562 * Initialize a newly created task to perform analysis within the given contex t.
10563 *
10564 * @param context the context in which the task is to be performed
10565 * @param source the source to be parsed
10566 * @param contentData the time-stamped contents of the source
10567 */
10568 GetContentTask(InternalAnalysisContext context, this.source) : super(context) {
10569 if (source == null) {
10570 throw new IllegalArgumentException("Cannot get contents of null source");
10571 }
10572 }
10573
10574 @override
10575 accept(AnalysisTaskVisitor visitor) => visitor.visitGetContentTask(this);
10576
10577 /**
10578 * Return the contents of the source, or `null` if the task has not completed or if there
10579 * was an exception while getting the contents.
10580 *
10581 * @return the contents of the source
10582 */
10583 String get content => _content;
10584
10585 /**
10586 * Return the time at which the contents of the source that was parsed were la st modified, or a
10587 * negative value if the task has not yet been performed or if an exception oc curred.
10588 *
10589 * @return the time at which the contents of the source that was parsed were l ast modified
10590 */
10591 int get modificationTime => _modificationTime;
10592
10593 /**
10594 * Return `true` if this task is complete. Unlike most tasks, this task is all owed to be
10595 * visited more than once in order to support asynchronous IO. If the task is not complete when it
10596 * is visited synchronously as part of the [AnalysisTask#perform]
10597 * method, it will be visited again, using the same visitor, when the IO opera tion has been
10598 * performed.
10599 *
10600 * @return `true` if this task is complete
10601 */
10602 bool get isComplete => _complete;
10603
10604 @override
10605 String get taskDescription => "get contents of ${source.fullName}";
10606
10607 @override
10608 void internalPerform() {
10609 _complete = true;
10610 try {
10611 TimestampedData<String> data = context.getContents(source);
10612 _content = data.data;
10613 _modificationTime = data.modificationTime;
10614 } catch (exception, stackTrace) {
10615 throw new AnalysisException("Could not get contents of ${source}", new Cau ghtException(exception, stackTrace));
10616 }
10617 }
10618 }
10619
10620 /**
10621 * The interface `HtmlEntry` defines the behavior of objects that maintain the i nformation
10622 * cached by an analysis context about an individual HTML file.
10623 */
10624 abstract class HtmlEntry implements SourceEntry {
10625 /**
10626 * The data descriptor representing the information about an Angular applicati on this source is
10627 * used in.
10628 */
10629 static final DataDescriptor<AngularApplication> ANGULAR_APPLICATION = new Data Descriptor<AngularApplication>("HtmlEntry.ANGULAR_APPLICATION");
10630
10631 /**
10632 * The data descriptor representing the information about an Angular component this source is used
10633 * as template for.
10634 */
10635 static final DataDescriptor<AngularComponentElement> ANGULAR_COMPONENT = new D ataDescriptor<AngularComponentElement>("HtmlEntry.ANGULAR_COMPONENT");
10636
10637 /**
10638 * The data descriptor representing the information about an Angular applicati on this source is
10639 * entry point for.
10640 */
10641 static final DataDescriptor<AngularApplication> ANGULAR_ENTRY = new DataDescri ptor<AngularApplication>("HtmlEntry.ANGULAR_ENTRY");
10642
10643 /**
10644 * The data descriptor representing the errors reported during Angular resolut ion.
10645 */
10646 static final DataDescriptor<List<AnalysisError>> ANGULAR_ERRORS = new DataDesc riptor<List<AnalysisError>>("HtmlEntry.ANGULAR_ERRORS");
10647
10648 /**
10649 * The data descriptor representing the HTML element.
10650 */
10651 static final DataDescriptor<HtmlElement> ELEMENT = new DataDescriptor<HtmlElem ent>("HtmlEntry.ELEMENT");
10652
10653 /**
10654 * The data descriptor representing the hints resulting from auditing the sour ce.
10655 */
10656 static final DataDescriptor<List<AnalysisError>> HINTS = new DataDescriptor<Li st<AnalysisError>>("HtmlEntry.HINTS");
10657
10658 /**
10659 * The data descriptor representing the errors resulting from parsing the sour ce.
10660 */
10661 static final DataDescriptor<List<AnalysisError>> PARSE_ERRORS = new DataDescri ptor<List<AnalysisError>>("HtmlEntry.PARSE_ERRORS");
10662
10663 /**
10664 * The data descriptor representing the parsed AST structure.
10665 */
10666 static final DataDescriptor<ht.HtmlUnit> PARSED_UNIT = new DataDescriptor<ht.H tmlUnit>("HtmlEntry.PARSED_UNIT");
10667
10668 /**
10669 * The data descriptor representing the resolved AST structure.
10670 */
10671 static final DataDescriptor<ht.HtmlUnit> RESOLVED_UNIT = new DataDescriptor<ht .HtmlUnit>("HtmlEntry.RESOLVED_UNIT");
10672
10673 /**
10674 * The data descriptor representing the list of referenced libraries.
10675 */
10676 static final DataDescriptor<List<Source>> REFERENCED_LIBRARIES = new DataDescr iptor<List<Source>>("HtmlEntry.REFERENCED_LIBRARIES");
10677
10678 /**
10679 * The data descriptor representing the errors resulting from resolving the so urce.
10680 */
10681 static final DataDescriptor<List<AnalysisError>> RESOLUTION_ERRORS = new DataD escriptor<List<AnalysisError>>("HtmlEntry.RESOLUTION_ERRORS");
10682
10683 /**
10684 * The data descriptor representing the status of Polymer elements in the sour ce.
10685 */
10686 static final DataDescriptor<List<AnalysisError>> POLYMER_BUILD_ERRORS = new Da taDescriptor<List<AnalysisError>>("HtmlEntry.POLYMER_BUILD_ERRORS");
10687
10688 /**
10689 * The data descriptor representing the errors reported during Polymer resolut ion.
10690 */
10691 static final DataDescriptor<List<AnalysisError>> POLYMER_RESOLUTION_ERRORS = n ew DataDescriptor<List<AnalysisError>>("HtmlEntry.POLYMER_RESOLUTION_ERRORS");
10692
10693 /**
10694 * Return all of the errors associated with the compilation unit that are curr ently cached.
10695 *
10696 * @return all of the errors associated with the compilation unit
10697 */
10698 List<AnalysisError> get allErrors;
10699
10700 /**
10701 * Return a valid parsed unit, either an unresolved AST structure or the resul t of resolving the
10702 * AST structure, or `null` if there is no parsed unit available.
10703 *
10704 * @return a valid parsed unit
10705 */
10706 ht.HtmlUnit get anyParsedUnit;
10707
10708 @override
10709 HtmlEntryImpl get writableCopy;
10710 }
10711
10712 /**
10713 * Instances of the class `HtmlEntryImpl` implement an [HtmlEntry].
10714 */
10715 class HtmlEntryImpl extends SourceEntryImpl implements HtmlEntry {
10716 /**
10717 * The state of the cached parsed (but not resolved) HTML unit.
10718 */
10719 CacheState _parsedUnitState = CacheState.INVALID;
10720
10721 /**
10722 * The parsed HTML unit, or `null` if the parsed HTML unit is not currently ca ched.
10723 */
10724 ht.HtmlUnit _parsedUnit;
10725
10726 /**
10727 * The state of the cached resolved HTML unit.
10728 */
10729 CacheState _resolvedUnitState = CacheState.INVALID;
10730
10731 /**
10732 * The resolved HTML unit, or `null` if the resolved HTML unit is not currentl y cached.
10733 */
10734 ht.HtmlUnit _resolvedUnit;
10735
10736 /**
10737 * The state of the cached parse errors.
10738 */
10739 CacheState _parseErrorsState = CacheState.INVALID;
10740
10741 /**
10742 * The errors produced while scanning and parsing the HTML, or `null` if the e rrors are not
10743 * currently cached.
10744 */
10745 List<AnalysisError> _parseErrors = AnalysisError.NO_ERRORS;
10746
10747 /**
10748 * The state of the cached resolution errors.
10749 */
10750 CacheState _resolutionErrorsState = CacheState.INVALID;
10751
10752 /**
10753 * The errors produced while resolving the HTML, or `null` if the errors are n ot currently
10754 * cached.
10755 */
10756 List<AnalysisError> _resolutionErrors = AnalysisError.NO_ERRORS;
10757
10758 /**
10759 * The state of the cached list of referenced libraries.
10760 */
10761 CacheState _referencedLibrariesState = CacheState.INVALID;
10762
10763 /**
10764 * The list of libraries referenced in the HTML, or `null` if the list is not currently
10765 * cached. Note that this list does not include libraries defined directly wit hin the HTML file.
10766 */
10767 List<Source> _referencedLibraries = Source.EMPTY_ARRAY;
10768
10769 /**
10770 * The state of the cached HTML element.
10771 */
10772 CacheState _elementState = CacheState.INVALID;
10773
10774 /**
10775 * The element representing the HTML file, or `null` if the element is not cur rently cached.
10776 */
10777 HtmlElement _element;
10778
10779 /**
10780 * The state of the [angularApplication].
10781 */
10782 CacheState _angularApplicationState = CacheState.VALID;
10783
10784 /**
10785 * Information about the Angular Application this unit is used in.
10786 */
10787 AngularApplication _angularApplication;
10788
10789 /**
10790 * The state of the [angularEntry].
10791 */
10792 CacheState _angularEntryState = CacheState.INVALID;
10793
10794 /**
10795 * Information about the Angular Application this unit is entry point for.
10796 */
10797 AngularApplication _angularEntry = null;
10798
10799 /**
10800 * The state of the [angularComponent].
10801 */
10802 CacheState _angularComponentState = CacheState.VALID;
10803
10804 /**
10805 * Information about the [AngularComponentElement] this unit is used as templa te for.
10806 */
10807 AngularComponentElement _angularComponent = null;
10808
10809 /**
10810 * The state of the Angular resolution errors.
10811 */
10812 CacheState _angularErrorsState = CacheState.INVALID;
10813
10814 /**
10815 * The hints produced while performing Angular resolution, or an empty array i f the error are not
10816 * currently cached.
10817 */
10818 List<AnalysisError> _angularErrors = AnalysisError.NO_ERRORS;
10819
10820 /**
10821 * The state of the cached hints.
10822 */
10823 CacheState _hintsState = CacheState.INVALID;
10824
10825 /**
10826 * The hints produced while auditing the compilation unit, or an empty array i f the hints are not
10827 * currently cached.
10828 */
10829 List<AnalysisError> _hints = AnalysisError.NO_ERRORS;
10830
10831 /**
10832 * The state of the Polymer elements.
10833 */
10834 CacheState _polymerBuildErrorsState = CacheState.INVALID;
10835
10836 /**
10837 * The hints produced while performing Polymer HTML elements building, or an e mpty array if the
10838 * error are not currently cached.
10839 */
10840 List<AnalysisError> _polymerBuildErrors = AnalysisError.NO_ERRORS;
10841
10842 /**
10843 * The state of the Polymer resolution errors.
10844 */
10845 CacheState _polymerResolutionErrorsState = CacheState.INVALID;
10846
10847 /**
10848 * The hints produced while performing Polymer resolution, or an empty array i f the error are not
10849 * currently cached.
10850 */
10851 List<AnalysisError> _polymerResolutionErrors = AnalysisError.NO_ERRORS;
10852
10853 /**
10854 * Flush any AST structures being maintained by this entry.
10855 */
10856 void flushAstStructures() {
10857 if (_parsedUnitState == CacheState.VALID) {
10858 _parsedUnitState = CacheState.FLUSHED;
10859 _parsedUnit = null;
10860 }
10861 if (_resolvedUnitState == CacheState.VALID) {
10862 _resolvedUnitState = CacheState.FLUSHED;
10863 _resolvedUnit = null;
10864 }
10865 if (_angularEntryState == CacheState.VALID) {
10866 _angularEntryState = CacheState.FLUSHED;
10867 }
10868 if (_angularErrorsState == CacheState.VALID) {
10869 _angularErrorsState = CacheState.FLUSHED;
10870 }
10871 }
10872
10873 @override
10874 List<AnalysisError> get allErrors {
10875 List<AnalysisError> errors = new List<AnalysisError>();
10876 if (_parseErrors != null) {
10877 for (AnalysisError error in _parseErrors) {
10878 errors.add(error);
10879 }
10880 }
10881 if (_resolutionErrors != null) {
10882 for (AnalysisError error in _resolutionErrors) {
10883 errors.add(error);
10884 }
10885 }
10886 if (_angularErrors != null) {
10887 for (AnalysisError error in _angularErrors) {
10888 errors.add(error);
10889 }
10890 }
10891 if (_hints != null) {
10892 for (AnalysisError error in _hints) {
10893 errors.add(error);
10894 }
10895 }
10896 if (_polymerBuildErrors != null) {
10897 for (AnalysisError error in _polymerBuildErrors) {
10898 errors.add(error);
10899 }
10900 }
10901 if (_polymerResolutionErrors != null) {
10902 for (AnalysisError error in _polymerResolutionErrors) {
10903 errors.add(error);
10904 }
10905 }
10906 if (errors.length == 0) {
10907 return AnalysisError.NO_ERRORS;
10908 }
10909 return new List.from(errors);
10910 }
10911
10912 @override
10913 ht.HtmlUnit get anyParsedUnit {
10914 if (_parsedUnitState == CacheState.VALID) {
10915 // parsedUnitAccessed = true;
10916 return _parsedUnit;
10917 }
10918 if (_resolvedUnitState == CacheState.VALID) {
10919 // resovledUnitAccessed = true;
10920 return _resolvedUnit;
10921 }
10922 return null;
10923 }
10924
10925 @override
10926 SourceKind get kind => SourceKind.HTML;
10927
10928 @override
10929 CacheState getState(DataDescriptor descriptor) {
10930 if (identical(descriptor, HtmlEntry.ANGULAR_APPLICATION)) {
10931 return _angularApplicationState;
10932 } else if (identical(descriptor, HtmlEntry.ANGULAR_COMPONENT)) {
10933 return _angularComponentState;
10934 } else if (identical(descriptor, HtmlEntry.ANGULAR_ENTRY)) {
10935 return _angularEntryState;
10936 } else if (identical(descriptor, HtmlEntry.ANGULAR_ERRORS)) {
10937 return _angularErrorsState;
10938 } else if (identical(descriptor, HtmlEntry.ELEMENT)) {
10939 return _elementState;
10940 } else if (identical(descriptor, HtmlEntry.PARSE_ERRORS)) {
10941 return _parseErrorsState;
10942 } else if (identical(descriptor, HtmlEntry.PARSED_UNIT)) {
10943 return _parsedUnitState;
10944 } else if (identical(descriptor, HtmlEntry.RESOLVED_UNIT)) {
10945 return _resolvedUnitState;
10946 } else if (identical(descriptor, HtmlEntry.REFERENCED_LIBRARIES)) {
10947 return _referencedLibrariesState;
10948 } else if (identical(descriptor, HtmlEntry.RESOLUTION_ERRORS)) {
10949 return _resolutionErrorsState;
10950 } else if (identical(descriptor, HtmlEntry.HINTS)) {
10951 return _hintsState;
10952 } else if (identical(descriptor, HtmlEntry.POLYMER_BUILD_ERRORS)) {
10953 return _polymerBuildErrorsState;
10954 } else if (identical(descriptor, HtmlEntry.POLYMER_RESOLUTION_ERRORS)) {
10955 return _polymerResolutionErrorsState;
10956 }
10957 return super.getState(descriptor);
10958 }
10959
10960 @override
10961 Object getValue(DataDescriptor descriptor) {
10962 if (identical(descriptor, HtmlEntry.ANGULAR_APPLICATION)) {
10963 return _angularApplication;
10964 } else if (identical(descriptor, HtmlEntry.ANGULAR_COMPONENT)) {
10965 return _angularComponent;
10966 } else if (identical(descriptor, HtmlEntry.ANGULAR_ENTRY)) {
10967 return _angularEntry;
10968 } else if (identical(descriptor, HtmlEntry.ANGULAR_ERRORS)) {
10969 return _angularErrors;
10970 } else if (identical(descriptor, HtmlEntry.ELEMENT)) {
10971 return _element;
10972 } else if (identical(descriptor, HtmlEntry.PARSE_ERRORS)) {
10973 return _parseErrors;
10974 } else if (identical(descriptor, HtmlEntry.PARSED_UNIT)) {
10975 return _parsedUnit;
10976 } else if (identical(descriptor, HtmlEntry.RESOLVED_UNIT)) {
10977 return _resolvedUnit;
10978 } else if (identical(descriptor, HtmlEntry.REFERENCED_LIBRARIES)) {
10979 return _referencedLibraries;
10980 } else if (identical(descriptor, HtmlEntry.RESOLUTION_ERRORS)) {
10981 return _resolutionErrors;
10982 } else if (identical(descriptor, HtmlEntry.HINTS)) {
10983 return _hints;
10984 } else if (identical(descriptor, HtmlEntry.POLYMER_BUILD_ERRORS)) {
10985 return _polymerBuildErrors;
10986 } else if (identical(descriptor, HtmlEntry.POLYMER_RESOLUTION_ERRORS)) {
10987 return _polymerResolutionErrors;
10988 }
10989 return super.getValue(descriptor);
10990 }
10991
10992 @override
10993 HtmlEntryImpl get writableCopy {
10994 HtmlEntryImpl copy = new HtmlEntryImpl();
10995 copy.copyFrom(this);
10996 return copy;
10997 }
10998
10999 @override
11000 void invalidateAllInformation() {
11001 super.invalidateAllInformation();
11002 _parseErrors = AnalysisError.NO_ERRORS;
11003 _parseErrorsState = CacheState.INVALID;
11004 _parsedUnit = null;
11005 _parsedUnitState = CacheState.INVALID;
11006 _resolvedUnit = null;
11007 _resolvedUnitState = CacheState.INVALID;
11008 invalidateAllResolutionInformation(true);
11009 }
11010
11011 /**
11012 * Invalidate all of the resolution information associated with the HTML file.
11013 *
11014 * @param invalidateUris true if the cached results of converting URIs to sour ce files should also
11015 * be invalidated.
11016 */
11017 void invalidateAllResolutionInformation(bool invalidateUris) {
11018 _angularEntry = null;
11019 _angularEntryState = CacheState.INVALID;
11020 _angularErrors = AnalysisError.NO_ERRORS;
11021 _angularErrorsState = CacheState.INVALID;
11022 _polymerBuildErrors = AnalysisError.NO_ERRORS;
11023 _polymerBuildErrorsState = CacheState.INVALID;
11024 _polymerResolutionErrors = AnalysisError.NO_ERRORS;
11025 _polymerResolutionErrorsState = CacheState.INVALID;
11026 _element = null;
11027 _elementState = CacheState.INVALID;
11028 _resolutionErrors = AnalysisError.NO_ERRORS;
11029 _resolutionErrorsState = CacheState.INVALID;
11030 _hints = AnalysisError.NO_ERRORS;
11031 _hintsState = CacheState.INVALID;
11032 if (invalidateUris) {
11033 _referencedLibraries = Source.EMPTY_ARRAY;
11034 _referencedLibrariesState = CacheState.INVALID;
11035 }
11036 }
11037
11038 @override
11039 void recordContentError(CaughtException exception) {
11040 super.recordContentError(exception);
11041 recordParseError(exception);
11042 }
11043
11044 /**
11045 * Record that an error was encountered while attempting to parse the source a ssociated with this
11046 * entry.
11047 *
11048 * @param exception the exception that shows where the error occurred
11049 */
11050 void recordParseError(CaughtException exception) {
11051 // If the scanning and parsing of HTML are separated, the following line can be removed.
11052 recordScanError(exception);
11053 _parseErrors = AnalysisError.NO_ERRORS;
11054 _parseErrorsState = CacheState.ERROR;
11055 _parsedUnit = null;
11056 _parsedUnitState = CacheState.ERROR;
11057 _referencedLibraries = Source.EMPTY_ARRAY;
11058 _referencedLibrariesState = CacheState.ERROR;
11059 recordResolutionError(exception);
11060 }
11061
11062 /**
11063 * Record that an error was encountered while attempting to resolve the source associated with
11064 * this entry.
11065 *
11066 * @param exception the exception that shows where the error occurred
11067 */
11068 void recordResolutionError(CaughtException exception) {
11069 this.exception = exception;
11070 _angularErrors = AnalysisError.NO_ERRORS;
11071 _angularErrorsState = CacheState.ERROR;
11072 _resolvedUnit = null;
11073 _resolvedUnitState = CacheState.ERROR;
11074 _element = null;
11075 _elementState = CacheState.ERROR;
11076 _resolutionErrors = AnalysisError.NO_ERRORS;
11077 _resolutionErrorsState = CacheState.ERROR;
11078 _hints = AnalysisError.NO_ERRORS;
11079 _hintsState = CacheState.ERROR;
11080 _polymerBuildErrors = AnalysisError.NO_ERRORS;
11081 _polymerBuildErrorsState = CacheState.ERROR;
11082 _polymerResolutionErrors = AnalysisError.NO_ERRORS;
11083 _polymerResolutionErrorsState = CacheState.ERROR;
11084 }
11085
11086 @override
11087 void setState(DataDescriptor descriptor, CacheState state) {
11088 if (identical(descriptor, HtmlEntry.ANGULAR_APPLICATION)) {
11089 _angularApplication = updatedValue(state, _angularApplication, null);
11090 _angularApplicationState = state;
11091 } else if (identical(descriptor, HtmlEntry.ANGULAR_COMPONENT)) {
11092 _angularComponent = updatedValue(state, _angularComponent, null);
11093 _angularComponentState = state;
11094 } else if (identical(descriptor, HtmlEntry.ANGULAR_ENTRY)) {
11095 _angularEntry = updatedValue(state, _angularEntry, null);
11096 _angularEntryState = state;
11097 } else if (identical(descriptor, HtmlEntry.ANGULAR_ERRORS)) {
11098 _angularErrors = updatedValue(state, _angularErrors, null);
11099 _angularErrorsState = state;
11100 } else if (identical(descriptor, HtmlEntry.ELEMENT)) {
11101 _element = updatedValue(state, _element, null);
11102 _elementState = state;
11103 } else if (identical(descriptor, HtmlEntry.PARSE_ERRORS)) {
11104 _parseErrors = updatedValue(state, _parseErrors, null);
11105 _parseErrorsState = state;
11106 } else if (identical(descriptor, HtmlEntry.PARSED_UNIT)) {
11107 _parsedUnit = updatedValue(state, _parsedUnit, null);
11108 _parsedUnitState = state;
11109 } else if (identical(descriptor, HtmlEntry.RESOLVED_UNIT)) {
11110 _resolvedUnit = updatedValue(state, _resolvedUnit, null);
11111 _resolvedUnitState = state;
11112 } else if (identical(descriptor, HtmlEntry.REFERENCED_LIBRARIES)) {
11113 _referencedLibraries = updatedValue(state, _referencedLibraries, Source.EM PTY_ARRAY);
11114 _referencedLibrariesState = state;
11115 } else if (identical(descriptor, HtmlEntry.RESOLUTION_ERRORS)) {
11116 _resolutionErrors = updatedValue(state, _resolutionErrors, AnalysisError.N O_ERRORS);
11117 _resolutionErrorsState = state;
11118 } else if (identical(descriptor, HtmlEntry.HINTS)) {
11119 _hints = updatedValue(state, _hints, AnalysisError.NO_ERRORS);
11120 _hintsState = state;
11121 } else if (identical(descriptor, HtmlEntry.POLYMER_BUILD_ERRORS)) {
11122 _polymerBuildErrors = updatedValue(state, _polymerBuildErrors, null);
11123 _polymerBuildErrorsState = state;
11124 } else if (identical(descriptor, HtmlEntry.POLYMER_RESOLUTION_ERRORS)) {
11125 _polymerResolutionErrors = updatedValue(state, _polymerResolutionErrors, n ull);
11126 _polymerResolutionErrorsState = state;
11127 } else {
11128 super.setState(descriptor, state);
11129 }
11130 }
11131
11132 @override
11133 void setValue(DataDescriptor descriptor, Object value) {
11134 if (identical(descriptor, HtmlEntry.ANGULAR_APPLICATION)) {
11135 _angularApplication = value as AngularApplication;
11136 _angularApplicationState = CacheState.VALID;
11137 } else if (identical(descriptor, HtmlEntry.ANGULAR_COMPONENT)) {
11138 _angularComponent = value as AngularComponentElement;
11139 _angularComponentState = CacheState.VALID;
11140 } else if (identical(descriptor, HtmlEntry.ANGULAR_ENTRY)) {
11141 _angularEntry = value as AngularApplication;
11142 _angularEntryState = CacheState.VALID;
11143 } else if (identical(descriptor, HtmlEntry.ANGULAR_ERRORS)) {
11144 _angularErrors = value as List<AnalysisError>;
11145 _angularErrorsState = CacheState.VALID;
11146 } else if (identical(descriptor, HtmlEntry.ELEMENT)) {
11147 _element = value as HtmlElement;
11148 _elementState = CacheState.VALID;
11149 } else if (identical(descriptor, HtmlEntry.PARSE_ERRORS)) {
11150 _parseErrors = value as List<AnalysisError>;
11151 _parseErrorsState = CacheState.VALID;
11152 } else if (identical(descriptor, HtmlEntry.PARSED_UNIT)) {
11153 _parsedUnit = value as ht.HtmlUnit;
11154 _parsedUnitState = CacheState.VALID;
11155 } else if (identical(descriptor, HtmlEntry.RESOLVED_UNIT)) {
11156 _resolvedUnit = value as ht.HtmlUnit;
11157 _resolvedUnitState = CacheState.VALID;
11158 } else if (identical(descriptor, HtmlEntry.REFERENCED_LIBRARIES)) {
11159 _referencedLibraries = value == null ? Source.EMPTY_ARRAY : (value as List <Source>);
11160 _referencedLibrariesState = CacheState.VALID;
11161 } else if (identical(descriptor, HtmlEntry.RESOLUTION_ERRORS)) {
11162 _resolutionErrors = value as List<AnalysisError>;
11163 _resolutionErrorsState = CacheState.VALID;
11164 } else if (identical(descriptor, HtmlEntry.HINTS)) {
11165 _hints = value as List<AnalysisError>;
11166 _hintsState = CacheState.VALID;
11167 } else if (identical(descriptor, HtmlEntry.POLYMER_BUILD_ERRORS)) {
11168 _polymerBuildErrors = value as List<AnalysisError>;
11169 _polymerBuildErrorsState = CacheState.VALID;
11170 } else if (identical(descriptor, HtmlEntry.POLYMER_RESOLUTION_ERRORS)) {
11171 _polymerResolutionErrors = value as List<AnalysisError>;
11172 _polymerResolutionErrorsState = CacheState.VALID;
11173 } else {
11174 super.setValue(descriptor, value);
11175 }
11176 }
11177
11178 @override
11179 void copyFrom(SourceEntryImpl entry) {
11180 super.copyFrom(entry);
11181 HtmlEntryImpl other = entry as HtmlEntryImpl;
11182 _angularApplicationState = other._angularApplicationState;
11183 _angularApplication = other._angularApplication;
11184 _angularComponentState = other._angularComponentState;
11185 _angularComponent = other._angularComponent;
11186 _angularEntryState = other._angularEntryState;
11187 _angularEntry = other._angularEntry;
11188 _angularErrorsState = other._angularErrorsState;
11189 _angularErrors = other._angularErrors;
11190 _parseErrorsState = other._parseErrorsState;
11191 _parseErrors = other._parseErrors;
11192 _parsedUnitState = other._parsedUnitState;
11193 _parsedUnit = other._parsedUnit;
11194 _resolvedUnitState = other._resolvedUnitState;
11195 _resolvedUnit = other._resolvedUnit;
11196 _referencedLibrariesState = other._referencedLibrariesState;
11197 _referencedLibraries = other._referencedLibraries;
11198 _resolutionErrorsState = other._resolutionErrorsState;
11199 _resolutionErrors = other._resolutionErrors;
11200 _elementState = other._elementState;
11201 _element = other._element;
11202 _hintsState = other._hintsState;
11203 _hints = other._hints;
11204 _polymerBuildErrorsState = other._polymerBuildErrorsState;
11205 _polymerBuildErrors = other._polymerBuildErrors;
11206 _polymerResolutionErrorsState = other._polymerResolutionErrorsState;
11207 _polymerResolutionErrors = other._polymerResolutionErrors;
11208 }
11209
11210 @override
11211 bool get hasErrorState => super.hasErrorState || _parsedUnitState == CacheStat e.ERROR || _resolvedUnitState == CacheState.ERROR || _parseErrorsState == CacheS tate.ERROR || _resolutionErrorsState == CacheState.ERROR || _referencedLibraries State == CacheState.ERROR || _elementState == CacheState.ERROR || _angularErrors State == CacheState.ERROR || _hintsState == CacheState.ERROR || _polymerBuildErr orsState == CacheState.ERROR || _polymerResolutionErrorsState == CacheState.ERRO R;
11212
11213 @override
11214 bool writeDiffOn(JavaStringBuilder builder, SourceEntry oldEntry) {
11215 bool needsSeparator = super.writeDiffOn(builder, oldEntry);
11216 if (oldEntry is! HtmlEntryImpl) {
11217 if (needsSeparator) {
11218 builder.append("; ");
11219 }
11220 builder.append("entry type changed; was ${oldEntry.runtimeType.toString()} ");
11221 return true;
11222 }
11223 needsSeparator = writeStateDiffOn(builder, needsSeparator, oldEntry, HtmlEnt ry.PARSE_ERRORS, "parseErrors");
11224 needsSeparator = writeStateDiffOn(builder, needsSeparator, oldEntry, HtmlEnt ry.PARSED_UNIT, "parsedUnit");
11225 needsSeparator = writeStateDiffOn(builder, needsSeparator, oldEntry, HtmlEnt ry.RESOLVED_UNIT, "resolvedUnit");
11226 needsSeparator = writeStateDiffOn(builder, needsSeparator, oldEntry, HtmlEnt ry.RESOLUTION_ERRORS, "resolutionErrors");
11227 needsSeparator = writeStateDiffOn(builder, needsSeparator, oldEntry, HtmlEnt ry.REFERENCED_LIBRARIES, "referencedLibraries");
11228 needsSeparator = writeStateDiffOn(builder, needsSeparator, oldEntry, HtmlEnt ry.ELEMENT, "element");
11229 needsSeparator = writeStateDiffOn(builder, needsSeparator, oldEntry, HtmlEnt ry.ANGULAR_APPLICATION, "angularApplicationState");
11230 needsSeparator = writeStateDiffOn(builder, needsSeparator, oldEntry, HtmlEnt ry.ANGULAR_COMPONENT, "angularComponent");
11231 needsSeparator = writeStateDiffOn(builder, needsSeparator, oldEntry, HtmlEnt ry.ANGULAR_ENTRY, "angularEntry");
11232 needsSeparator = writeStateDiffOn(builder, needsSeparator, oldEntry, HtmlEnt ry.ANGULAR_ERRORS, "angularErrors");
11233 needsSeparator = writeStateDiffOn(builder, needsSeparator, oldEntry, HtmlEnt ry.POLYMER_BUILD_ERRORS, "polymerBuildErrors");
11234 needsSeparator = writeStateDiffOn(builder, needsSeparator, oldEntry, HtmlEnt ry.POLYMER_RESOLUTION_ERRORS, "polymerResolutionErrors");
11235 return needsSeparator;
11236 }
11237
11238 @override
11239 void writeOn(JavaStringBuilder builder) {
11240 builder.append("Html: ");
11241 super.writeOn(builder);
11242 builder.append("; parseErrors = ");
11243 builder.append(_parseErrorsState);
11244 builder.append("; parsedUnit = ");
11245 builder.append(_parsedUnitState);
11246 builder.append("; resolvedUnit = ");
11247 builder.append(_resolvedUnitState);
11248 builder.append("; resolutionErrors = ");
11249 builder.append(_resolutionErrorsState);
11250 builder.append("; referencedLibraries = ");
11251 builder.append(_referencedLibrariesState);
11252 builder.append("; element = ");
11253 builder.append(_elementState);
11254 builder.append("; angularApplication = ");
11255 builder.append(_angularApplicationState);
11256 builder.append("; angularComponent = ");
11257 builder.append(_angularComponentState);
11258 builder.append("; angularEntry = ");
11259 builder.append(_angularEntryState);
11260 builder.append("; angularErrors = ");
11261 builder.append(_angularErrorsState);
11262 builder.append("; polymerBuildErrors = ");
11263 builder.append(_polymerBuildErrorsState);
11264 builder.append("; polymerResolutionErrors = ");
11265 builder.append(_polymerResolutionErrorsState);
11266 }
11267 }
11268
11269 /**
11270 * Instances of the class `IncrementalAnalysisCache` hold information used to pe rform
11271 * incremental analysis.
11272 *
11273 * @see AnalysisContextImpl#setChangedContents(Source, String, int, int, int)
11274 */
11275 class IncrementalAnalysisCache {
11276 /**
11277 * Determine if the incremental analysis result can be cached for the next inc remental analysis.
11278 *
11279 * @param cache the prior incremental analysis cache
11280 * @param unit the incrementally updated compilation unit
11281 * @return the cache used for incremental analysis or `null` if incremental an alysis results
11282 * cannot be cached for the next incremental analysis
11283 */
11284 static IncrementalAnalysisCache cacheResult(IncrementalAnalysisCache cache, Co mpilationUnit unit) {
11285 if (cache != null && unit != null) {
11286 return new IncrementalAnalysisCache(cache.librarySource, cache.source, uni t, cache._newContents, cache._newContents, 0, 0, 0);
11287 }
11288 return null;
11289 }
11290
11291 /**
11292 * Determine if the cache should be cleared.
11293 *
11294 * @param cache the prior cache or `null` if none
11295 * @param source the source being updated (not `null`)
11296 * @return the cache used for incremental analysis or `null` if incremental an alysis cannot
11297 * be performed
11298 */
11299 static IncrementalAnalysisCache clear(IncrementalAnalysisCache cache, Source s ource) {
11300 if (cache == null || cache.source == source) {
11301 return null;
11302 }
11303 return cache;
11304 }
11305
11306 /**
11307 * Determine if incremental analysis can be performed from the given informati on.
11308 *
11309 * @param cache the prior cache or `null` if none
11310 * @param source the source being updated (not `null`)
11311 * @param oldContents the original source contents prior to this update (may b e `null`)
11312 * @param newContents the new contents after this incremental change (not `nul l`)
11313 * @param offset the offset at which the change occurred
11314 * @param oldLength the length of the text being replaced
11315 * @param newLength the length of the replacement text
11316 * @param sourceEntry the cached entry for the given source or `null` if none
11317 * @return the cache used for incremental analysis or `null` if incremental an alysis cannot
11318 * be performed
11319 */
11320 static IncrementalAnalysisCache update(IncrementalAnalysisCache cache, Source source, String oldContents, String newContents, int offset, int oldLength, int n ewLength, SourceEntry sourceEntry) {
11321 // Determine the cache resolved unit
11322 Source librarySource = null;
11323 CompilationUnit unit = null;
11324 if (sourceEntry is DartEntryImpl) {
11325 DartEntryImpl dartEntry = sourceEntry;
11326 List<Source> librarySources = dartEntry.librariesContaining;
11327 if (librarySources.length == 1) {
11328 librarySource = librarySources[0];
11329 if (librarySource != null) {
11330 unit = dartEntry.getValueInLibrary(DartEntry.RESOLVED_UNIT, librarySou rce);
11331 }
11332 }
11333 }
11334 // Create a new cache if there is not an existing cache or the source is dif ferent
11335 // or a new resolved compilation unit is available
11336 if (cache == null || cache.source != source || unit != null) {
11337 if (unit == null) {
11338 return null;
11339 }
11340 if (oldContents == null) {
11341 if (oldLength != 0) {
11342 return null;
11343 }
11344 oldContents = "${newContents.substring(0, offset)}${newContents.substrin g(offset + newLength)}";
11345 }
11346 return new IncrementalAnalysisCache(librarySource, source, unit, oldConten ts, newContents, offset, oldLength, newLength);
11347 }
11348 // Update the existing cache if the change is contiguous
11349 if (cache._oldLength == 0 && cache._newLength == 0) {
11350 cache._offset = offset;
11351 cache._oldLength = oldLength;
11352 cache._newLength = newLength;
11353 } else {
11354 if (cache._offset > offset || offset > cache._offset + cache._newLength) {
11355 return null;
11356 }
11357 cache._newLength += newLength - oldLength;
11358 }
11359 cache._newContents = newContents;
11360 return cache;
11361 }
11362
11363 /**
11364 * Verify that the incrementally parsed and resolved unit in the incremental c ache is structurally
11365 * equivalent to the fully parsed unit.
11366 *
11367 * @param cache the prior cache or `null` if none
11368 * @param source the source of the compilation unit that was parsed (not `null `)
11369 * @param unit the compilation unit that was just parsed
11370 * @return the cache used for incremental analysis or `null` if incremental an alysis results
11371 * cannot be cached for the next incremental analysis
11372 */
11373 static IncrementalAnalysisCache verifyStructure(IncrementalAnalysisCache cache , Source source, CompilationUnit unit) {
11374 if (cache != null && unit != null && cache.source == source) {
11375 if (!AstComparator.equalNodes(cache.resolvedUnit, unit)) {
11376 return null;
11377 }
11378 }
11379 return cache;
11380 }
11381
11382 final Source librarySource;
11383
11384 final Source source;
11385
11386 final String oldContents;
11387
11388 final CompilationUnit resolvedUnit;
11389
11390 String _newContents;
11391
11392 int _offset = 0;
11393
11394 int _oldLength = 0;
11395
11396 int _newLength = 0;
11397
11398 IncrementalAnalysisCache(this.librarySource, this.source, this.resolvedUnit, t his.oldContents, String newContents, int offset, int oldLength, int newLength) {
11399 this._newContents = newContents;
11400 this._offset = offset;
11401 this._oldLength = oldLength;
11402 this._newLength = newLength;
11403 }
11404
11405 /**
11406 * Return the current contents for the receiver's source.
11407 *
11408 * @return the contents (not `null`)
11409 */
11410 String get newContents => _newContents;
11411
11412 /**
11413 * Return the number of characters in the replacement text.
11414 *
11415 * @return the replacement length (zero or greater)
11416 */
11417 int get newLength => _newLength;
11418
11419 /**
11420 * Return the character position of the first changed character.
11421 *
11422 * @return the offset (zero or greater)
11423 */
11424 int get offset => _offset;
11425
11426 /**
11427 * Return the number of characters that were replaced.
11428 *
11429 * @return the replaced length (zero or greater)
11430 */
11431 int get oldLength => _oldLength;
11432
11433 /**
11434 * Determine if the cache contains source changes that need to be analyzed
11435 *
11436 * @return `true` if the cache contains changes to be analyzed, else `false`
11437 */
11438 bool get hasWork => _oldLength > 0 || _newLength > 0;
11439 }
11440
11441 /**
11442 * Instances of the class `IncrementalAnalysisTask` incrementally update existin g analysis.
11443 */
11444 class IncrementalAnalysisTask extends AnalysisTask {
11445 /**
11446 * The information used to perform incremental analysis.
11447 */
11448 final IncrementalAnalysisCache cache;
11449
11450 /**
11451 * The compilation unit that was produced by incrementally updating the existi ng unit.
11452 */
11453 CompilationUnit _updatedUnit;
11454
11455 /**
11456 * Initialize a newly created task to perform analysis within the given contex t.
11457 *
11458 * @param context the context in which the task is to be performed
11459 * @param cache the incremental analysis cache used to perform the analysis
11460 */
11461 IncrementalAnalysisTask(InternalAnalysisContext context, this.cache) : super(c ontext);
11462
11463 @override
11464 accept(AnalysisTaskVisitor visitor) => visitor.visitIncrementalAnalysisTask(th is);
11465
11466 /**
11467 * Return the compilation unit that was produced by incrementally updating the existing
11468 * compilation unit, or `null` if the task has not yet been performed, could n ot be
11469 * performed, or if an exception occurred.
11470 *
11471 * @return the compilation unit
11472 */
11473 CompilationUnit get compilationUnit => _updatedUnit;
11474
11475 /**
11476 * Return the source that is to be incrementally analyzed.
11477 *
11478 * @return the source
11479 */
11480 Source get source => cache != null ? cache.source : null;
11481
11482 @override
11483 String get taskDescription => "incremental analysis ${(cache != null ? cache.s ource : "null")}";
11484
11485 @override
11486 void internalPerform() {
11487 if (cache == null) {
11488 return;
11489 }
11490 // Only handle small changes
11491 if (cache.oldLength > 0 || cache.newLength > 30) {
11492 return;
11493 }
11494 // Produce an updated token stream
11495 CharacterReader reader = new CharSequenceReader(cache.newContents);
11496 BooleanErrorListener errorListener = new BooleanErrorListener();
11497 IncrementalScanner scanner = new IncrementalScanner(cache.source, reader, er rorListener);
11498 scanner.rescan(cache.resolvedUnit.beginToken, cache.offset, cache.oldLength, cache.newLength);
11499 if (errorListener.errorReported) {
11500 return;
11501 }
11502 // Produce an updated AST
11503 IncrementalParser parser = new IncrementalParser(cache.source, scanner.token Map, AnalysisErrorListener.NULL_LISTENER);
11504 _updatedUnit = parser.reparse(cache.resolvedUnit, scanner.leftToken, scanner .rightToken, cache.offset, cache.offset + cache.oldLength);
11505 // Update the resolution
11506 TypeProvider typeProvider = this.typeProvider;
11507 if (_updatedUnit != null && typeProvider != null) {
11508 CompilationUnitElement element = _updatedUnit.element;
11509 if (element != null) {
11510 LibraryElement library = element.library;
11511 if (library != null) {
11512 IncrementalResolver resolver = new IncrementalResolver(library, cache. source, typeProvider, errorListener);
11513 resolver.resolve(parser.updatedNode);
11514 }
11515 }
11516 }
11517 }
11518
11519 /**
11520 * Return the type provider used for incremental resolution.
11521 *
11522 * @return the type provider (or `null` if an exception occurs)
11523 */
11524 TypeProvider get typeProvider {
11525 try {
11526 return context.typeProvider;
11527 } on AnalysisException catch (exception) {
11528 return null;
11529 }
11530 }
11531 }
11532
11533 /**
11534 * Instances of the class `InstrumentedAnalysisContextImpl` implement an
11535 * [AnalysisContext] by recording instrumentation data and delegating to
11536 * another analysis context to do the non-instrumentation work.
11537 */
11538 class InstrumentedAnalysisContextImpl implements InternalAnalysisContext {
11539 /**
11540 * If the current thread is the UI thread, then note this in the specified ins trumentation and
11541 * append this information to the log.
11542 *
11543 * @param instrumentation the instrumentation, not `null`
11544 */
11545 static void _checkThread(InstrumentationBuilder instrumentation) {
11546 }
11547
11548 /**
11549 * Record an exception that was thrown during analysis.
11550 *
11551 * @param instrumentation the instrumentation builder being used to record the exception
11552 * @param exception the exception being reported
11553 */
11554 static void _recordAnalysisException(InstrumentationBuilder instrumentation, C aughtException exception) {
11555 instrumentation.record(exception);
11556 }
11557
11558 /**
11559 * The unique identifier used to identify this analysis context in the instrum entation data.
11560 */
11561 String _contextId = UUID.randomUUID().toString();
11562
11563 /**
11564 * The analysis context to which all of the non-instrumentation work is delega ted.
11565 */
11566 InternalAnalysisContext _basis;
11567
11568 /**
11569 * Create a new [InstrumentedAnalysisContextImpl] which wraps a new
11570 * [AnalysisContextImpl] as the basis context.
11571 */
11572 InstrumentedAnalysisContextImpl() : this.con1(new AnalysisContextImpl());
11573
11574 /**
11575 * Create a new [InstrumentedAnalysisContextImpl] with a specified basis conte xt, aka the
11576 * context to wrap and instrument.
11577 *
11578 * @param context some [InstrumentedAnalysisContext] to wrap and instrument
11579 */
11580 InstrumentedAnalysisContextImpl.con1(InternalAnalysisContext context) {
11581 _basis = context;
11582 }
11583
11584 @override
11585 void addListener(AnalysisListener listener) {
11586 _basis.addListener(listener);
11587 }
11588
11589 @override
11590 void addSourceInfo(Source source, SourceEntry info) {
11591 _basis.addSourceInfo(source, info);
11592 }
11593
11594 @override
11595 void applyAnalysisDelta(AnalysisDelta delta) {
11596 InstrumentationBuilder instrumentation = Instrumentation.builder2("Analysis- updateAnalysis");
11597 _checkThread(instrumentation);
11598 try {
11599 instrumentation.metric3("contextId", _contextId);
11600 _basis.applyAnalysisDelta(delta);
11601 } finally {
11602 instrumentation.log();
11603 }
11604 }
11605
11606 @override
11607 void applyChanges(ChangeSet changeSet) {
11608 InstrumentationBuilder instrumentation = Instrumentation.builder2("Analysis- applyChanges");
11609 _checkThread(instrumentation);
11610 try {
11611 instrumentation.metric3("contextId", _contextId);
11612 _basis.applyChanges(changeSet);
11613 } finally {
11614 instrumentation.log();
11615 }
11616 }
11617
11618 @override
11619 String computeDocumentationComment(Element element) {
11620 InstrumentationBuilder instrumentation = Instrumentation.builder2("Analysis- computeDocumentationComment");
11621 _checkThread(instrumentation);
11622 try {
11623 instrumentation.metric3("contextId", _contextId);
11624 return _basis.computeDocumentationComment(element);
11625 } finally {
11626 instrumentation.log();
11627 }
11628 }
11629
11630 @override
11631 List<AnalysisError> computeErrors(Source source) {
11632 InstrumentationBuilder instrumentation = Instrumentation.builder2("Analysis- computeErrors");
11633 _checkThread(instrumentation);
11634 try {
11635 instrumentation.metric3("contextId", _contextId);
11636 List<AnalysisError> errors = _basis.computeErrors(source);
11637 instrumentation.metric2("Errors-count", errors.length);
11638 return errors;
11639 } finally {
11640 instrumentation.log();
11641 }
11642 }
11643
11644 @override
11645 List<Source> computeExportedLibraries(Source source) => _basis.computeExported Libraries(source);
11646
11647 @override
11648 HtmlElement computeHtmlElement(Source source) {
11649 InstrumentationBuilder instrumentation = Instrumentation.builder2("Analysis- computeHtmlElement");
11650 _checkThread(instrumentation);
11651 try {
11652 instrumentation.metric3("contextId", _contextId);
11653 return _basis.computeHtmlElement(source);
11654 } on AnalysisException catch (e, stackTrace) {
11655 _recordAnalysisException(instrumentation, new CaughtException(e, stackTrac e));
11656 throw e;
11657 } finally {
11658 instrumentation.log();
11659 }
11660 }
11661
11662 @override
11663 List<Source> computeImportedLibraries(Source source) => _basis.computeImported Libraries(source);
11664
11665 @override
11666 SourceKind computeKindOf(Source source) {
11667 InstrumentationBuilder instrumentation = Instrumentation.builder2("Analysis- computeKindOf");
11668 _checkThread(instrumentation);
11669 try {
11670 instrumentation.metric3("contextId", _contextId);
11671 return _basis.computeKindOf(source);
11672 } finally {
11673 instrumentation.log();
11674 }
11675 }
11676
11677 @override
11678 LibraryElement computeLibraryElement(Source source) {
11679 InstrumentationBuilder instrumentation = Instrumentation.builder2("Analysis- computeLibraryElement");
11680 _checkThread(instrumentation);
11681 try {
11682 instrumentation.metric3("contextId", _contextId);
11683 return _basis.computeLibraryElement(source);
11684 } on AnalysisException catch (e, stackTrace) {
11685 _recordAnalysisException(instrumentation, new CaughtException(e, stackTrac e));
11686 throw e;
11687 } finally {
11688 instrumentation.log();
11689 }
11690 }
11691
11692 @override
11693 LineInfo computeLineInfo(Source source) {
11694 InstrumentationBuilder instrumentation = Instrumentation.builder2("Analysis- computeLineInfo");
11695 _checkThread(instrumentation);
11696 try {
11697 instrumentation.metric3("contextId", _contextId);
11698 return _basis.computeLineInfo(source);
11699 } on AnalysisException catch (e, stackTrace) {
11700 _recordAnalysisException(instrumentation, new CaughtException(e, stackTrac e));
11701 throw e;
11702 } finally {
11703 instrumentation.log();
11704 }
11705 }
11706
11707 @override
11708 ResolvableCompilationUnit computeResolvableCompilationUnit(Source source) => _ basis.computeResolvableCompilationUnit(source);
11709
11710 @override
11711 void dispose() {
11712 InstrumentationBuilder instrumentation = Instrumentation.builder2("Analysis- dispose");
11713 _checkThread(instrumentation);
11714 try {
11715 instrumentation.metric3("contextId", _contextId);
11716 _basis.dispose();
11717 } finally {
11718 instrumentation.log();
11719 }
11720 }
11721
11722 @override
11723 bool exists(Source source) {
11724 InstrumentationBuilder instrumentation = Instrumentation.builder2("Analysis- exists");
11725 _checkThread(instrumentation);
11726 try {
11727 instrumentation.metric3("contextId", _contextId);
11728 return _basis.exists(source);
11729 } finally {
11730 instrumentation.log();
11731 }
11732 }
11733
11734 @override
11735 AnalysisContext extractContext(SourceContainer container) {
11736 InstrumentationBuilder instrumentation = Instrumentation.builder2("Analysis- extractContext");
11737 _checkThread(instrumentation);
11738 try {
11739 instrumentation.metric3("contextId", _contextId);
11740 InstrumentedAnalysisContextImpl newContext = new InstrumentedAnalysisConte xtImpl();
11741 _basis.extractContextInto(container, newContext._basis);
11742 return newContext;
11743 } finally {
11744 instrumentation.log();
11745 }
11746 }
11747
11748 @override
11749 InternalAnalysisContext extractContextInto(SourceContainer container, Internal AnalysisContext newContext) => _basis.extractContextInto(container, newContext);
11750
11751 @override
11752 AnalysisOptions get analysisOptions {
11753 InstrumentationBuilder instrumentation = Instrumentation.builder2("Analysis- getAnalysisOptions");
11754 _checkThread(instrumentation);
11755 try {
11756 instrumentation.metric3("contextId", _contextId);
11757 return _basis.analysisOptions;
11758 } finally {
11759 instrumentation.log();
11760 }
11761 }
11762
11763 @override
11764 AngularApplication getAngularApplicationWithHtml(Source htmlSource) {
11765 InstrumentationBuilder instrumentation = Instrumentation.builder2("Analysis- getAngularApplication");
11766 _checkThread(instrumentation);
11767 try {
11768 instrumentation.metric3("contextId", _contextId);
11769 return _basis.getAngularApplicationWithHtml(htmlSource);
11770 } finally {
11771 instrumentation.log();
11772 }
11773 }
11774
11775 /**
11776 * @return the underlying [AnalysisContext].
11777 */
11778 AnalysisContext get basis => _basis;
11779
11780 @override
11781 CompilationUnitElement getCompilationUnitElement(Source unitSource, Source lib rarySource) {
11782 InstrumentationBuilder instrumentation = Instrumentation.builder2("Analysis- getCompilationUnitElement");
11783 _checkThread(instrumentation);
11784 try {
11785 instrumentation.metric3("contextId", _contextId);
11786 return _basis.getCompilationUnitElement(unitSource, librarySource);
11787 } finally {
11788 instrumentation.log();
11789 }
11790 }
11791
11792 @override
11793 TimestampedData<String> getContents(Source source) => _basis.getContents(sourc e);
11794
11795 @override
11796 DeclaredVariables get declaredVariables => _basis.declaredVariables;
11797
11798 @override
11799 Element getElement(ElementLocation location) {
11800 InstrumentationBuilder instrumentation = Instrumentation.builder2("Analysis- getElement");
11801 _checkThread(instrumentation);
11802 try {
11803 instrumentation.metric3("contextId", _contextId);
11804 return _basis.getElement(location);
11805 } finally {
11806 instrumentation.log();
11807 }
11808 }
11809
11810 @override
11811 AnalysisErrorInfo getErrors(Source source) {
11812 InstrumentationBuilder instrumentation = Instrumentation.builder2("Analysis- getErrors");
11813 _checkThread(instrumentation);
11814 try {
11815 instrumentation.metric3("contextId", _contextId);
11816 AnalysisErrorInfo ret = _basis.getErrors(source);
11817 if (ret != null) {
11818 instrumentation.metric2("Errors-count", ret.errors.length);
11819 }
11820 return ret;
11821 } finally {
11822 instrumentation.log();
11823 }
11824 }
11825
11826 @override
11827 HtmlElement getHtmlElement(Source source) {
11828 InstrumentationBuilder instrumentation = Instrumentation.builder2("Analysis- getHtmlElement");
11829 _checkThread(instrumentation);
11830 try {
11831 instrumentation.metric3("contextId", _contextId);
11832 return _basis.getHtmlElement(source);
11833 } finally {
11834 instrumentation.log();
11835 }
11836 }
11837
11838 @override
11839 List<Source> getHtmlFilesReferencing(Source source) {
11840 InstrumentationBuilder instrumentation = Instrumentation.builder2("Analysis- getHtmlFilesReferencing");
11841 _checkThread(instrumentation);
11842 try {
11843 instrumentation.metric3("contextId", _contextId);
11844 List<Source> ret = _basis.getHtmlFilesReferencing(source);
11845 if (ret != null) {
11846 instrumentation.metric2("Source-count", ret.length);
11847 }
11848 return ret;
11849 } finally {
11850 instrumentation.log();
11851 }
11852 }
11853
11854 @override
11855 List<Source> get htmlSources {
11856 InstrumentationBuilder instrumentation = Instrumentation.builder2("Analysis- getHtmlSources");
11857 _checkThread(instrumentation);
11858 try {
11859 instrumentation.metric3("contextId", _contextId);
11860 List<Source> ret = _basis.htmlSources;
11861 if (ret != null) {
11862 instrumentation.metric2("Source-count", ret.length);
11863 }
11864 return ret;
11865 } finally {
11866 instrumentation.log();
11867 }
11868 }
11869
11870 @override
11871 SourceKind getKindOf(Source source) {
11872 InstrumentationBuilder instrumentation = Instrumentation.builder2("Analysis- getKindOf");
11873 _checkThread(instrumentation);
11874 try {
11875 instrumentation.metric3("contextId", _contextId);
11876 return _basis.getKindOf(source);
11877 } finally {
11878 instrumentation.log();
11879 }
11880 }
11881
11882 @override
11883 List<Source> get launchableClientLibrarySources {
11884 InstrumentationBuilder instrumentation = Instrumentation.builder2("Analysis- getLaunchableClientLibrarySources");
11885 _checkThread(instrumentation);
11886 try {
11887 instrumentation.metric3("contextId", _contextId);
11888 List<Source> ret = _basis.launchableClientLibrarySources;
11889 if (ret != null) {
11890 instrumentation.metric2("Source-count", ret.length);
11891 }
11892 return ret;
11893 } finally {
11894 instrumentation.log();
11895 }
11896 }
11897
11898 @override
11899 List<Source> get launchableServerLibrarySources {
11900 InstrumentationBuilder instrumentation = Instrumentation.builder2("Analysis- getLaunchableServerLibrarySources");
11901 _checkThread(instrumentation);
11902 try {
11903 instrumentation.metric3("contextId", _contextId);
11904 List<Source> ret = _basis.launchableServerLibrarySources;
11905 if (ret != null) {
11906 instrumentation.metric2("Source-count", ret.length);
11907 }
11908 return ret;
11909 } finally {
11910 instrumentation.log();
11911 }
11912 }
11913
11914 @override
11915 List<Source> getLibrariesContaining(Source source) {
11916 InstrumentationBuilder instrumentation = Instrumentation.builder2("Analysis- getLibrariesContaining");
11917 _checkThread(instrumentation);
11918 try {
11919 instrumentation.metric3("contextId", _contextId);
11920 List<Source> ret = _basis.getLibrariesContaining(source);
11921 if (ret != null) {
11922 instrumentation.metric2("Source-count", ret.length);
11923 }
11924 return ret;
11925 } finally {
11926 instrumentation.log2(2);
11927 }
11928 }
11929
11930 @override
11931 List<Source> getLibrariesDependingOn(Source librarySource) {
11932 InstrumentationBuilder instrumentation = Instrumentation.builder2("Analysis- getLibrariesDependingOn");
11933 _checkThread(instrumentation);
11934 try {
11935 instrumentation.metric3("contextId", _contextId);
11936 List<Source> ret = _basis.getLibrariesDependingOn(librarySource);
11937 if (ret != null) {
11938 instrumentation.metric2("Source-count", ret.length);
11939 }
11940 return ret;
11941 } finally {
11942 instrumentation.log();
11943 }
11944 }
11945
11946 @override
11947 List<Source> getLibrariesReferencedFromHtml(Source htmlSource) {
11948 InstrumentationBuilder instrumentation = Instrumentation.builder2("Analysis- getLibrariesReferencedFromHtml");
11949 _checkThread(instrumentation);
11950 try {
11951 instrumentation.metric3("contextId", _contextId);
11952 return _basis.getLibrariesReferencedFromHtml(htmlSource);
11953 } finally {
11954 instrumentation.log();
11955 }
11956 }
11957
11958 @override
11959 LibraryElement getLibraryElement(Source source) {
11960 InstrumentationBuilder instrumentation = Instrumentation.builder2("Analysis- getLibraryElement");
11961 _checkThread(instrumentation);
11962 try {
11963 instrumentation.metric3("contextId", _contextId);
11964 return _basis.getLibraryElement(source);
11965 } finally {
11966 instrumentation.log();
11967 }
11968 }
11969
11970 @override
11971 List<Source> get librarySources {
11972 InstrumentationBuilder instrumentation = Instrumentation.builder2("Analysis- getLibrarySources");
11973 _checkThread(instrumentation);
11974 try {
11975 instrumentation.metric3("contextId", _contextId);
11976 List<Source> ret = _basis.librarySources;
11977 if (ret != null) {
11978 instrumentation.metric2("Source-count", ret.length);
11979 }
11980 return ret;
11981 } finally {
11982 instrumentation.log();
11983 }
11984 }
11985
11986 @override
11987 LineInfo getLineInfo(Source source) {
11988 InstrumentationBuilder instrumentation = Instrumentation.builder2("Analysis- getLineInfo");
11989 _checkThread(instrumentation);
11990 try {
11991 instrumentation.metric3("contextId", _contextId);
11992 return _basis.getLineInfo(source);
11993 } finally {
11994 instrumentation.log();
11995 }
11996 }
11997
11998 @override
11999 int getModificationStamp(Source source) {
12000 InstrumentationBuilder instrumentation = Instrumentation.builder2("Analysis- getModificationStamp");
12001 _checkThread(instrumentation);
12002 try {
12003 instrumentation.metric3("contextId", _contextId);
12004 return _basis.getModificationStamp(source);
12005 } finally {
12006 instrumentation.log();
12007 }
12008 }
12009
12010 @override
12011 List<Source> get prioritySources {
12012 InstrumentationBuilder instrumentation = Instrumentation.builder2("Analysis- getPrioritySources");
12013 _checkThread(instrumentation);
12014 try {
12015 instrumentation.metric3("contextId", _contextId);
12016 return _basis.prioritySources;
12017 } finally {
12018 instrumentation.log();
12019 }
12020 }
12021
12022 @override
12023 Namespace getPublicNamespace(LibraryElement library) => _basis.getPublicNamesp ace(library);
12024
12025 @override
12026 List<Source> get refactoringUnsafeSources {
12027 InstrumentationBuilder instrumentation = Instrumentation.builder2("Analysis- getRefactoringUnsafeSources");
12028 _checkThread(instrumentation);
12029 try {
12030 instrumentation.metric3("contextId", _contextId);
12031 return _basis.refactoringUnsafeSources;
12032 } finally {
12033 instrumentation.log();
12034 }
12035 }
12036
12037 @override
12038 CompilationUnit getResolvedCompilationUnit(Source unitSource, LibraryElement l ibrary) {
12039 InstrumentationBuilder instrumentation = Instrumentation.builder2("Analysis- getResolvedCompilationUnit");
12040 _checkThread(instrumentation);
12041 try {
12042 instrumentation.metric3("contextId", _contextId);
12043 return _basis.getResolvedCompilationUnit(unitSource, library);
12044 } finally {
12045 instrumentation.log();
12046 }
12047 }
12048
12049 @override
12050 CompilationUnit getResolvedCompilationUnit2(Source unitSource, Source libraryS ource) {
12051 InstrumentationBuilder instrumentation = Instrumentation.builder2("Analysis- getResolvedCompilationUnit");
12052 _checkThread(instrumentation);
12053 try {
12054 instrumentation.metric3("contextId", _contextId);
12055 return _basis.getResolvedCompilationUnit2(unitSource, librarySource);
12056 } finally {
12057 instrumentation.log2(2);
12058 }
12059 }
12060
12061 @override
12062 ht.HtmlUnit getResolvedHtmlUnit(Source htmlSource) {
12063 InstrumentationBuilder instrumentation = Instrumentation.builder2("Analysis- getResolvedHtmlUnit");
12064 _checkThread(instrumentation);
12065 try {
12066 instrumentation.metric3("contextId", _contextId);
12067 return _basis.getResolvedHtmlUnit(htmlSource);
12068 } finally {
12069 instrumentation.log2(2);
12070 }
12071 }
12072
12073 @override
12074 SourceFactory get sourceFactory {
12075 InstrumentationBuilder instrumentation = Instrumentation.builder2("Analysis- getSourceFactory");
12076 try {
12077 instrumentation.metric3("contextId", _contextId);
12078 return _basis.sourceFactory;
12079 } finally {
12080 instrumentation.log2(2);
12081 }
12082 }
12083
12084 @override
12085 AnalysisContextStatistics get statistics => _basis.statistics;
12086
12087 @override
12088 TypeProvider get typeProvider => _basis.typeProvider;
12089
12090 @override
12091 bool isClientLibrary(Source librarySource) {
12092 InstrumentationBuilder instrumentation = Instrumentation.builder2("Analysis- isClientLibrary");
12093 _checkThread(instrumentation);
12094 try {
12095 instrumentation.metric3("contextId", _contextId);
12096 return _basis.isClientLibrary(librarySource);
12097 } finally {
12098 instrumentation.log();
12099 }
12100 }
12101
12102 @override
12103 bool get isDisposed {
12104 InstrumentationBuilder instrumentation = Instrumentation.builder2("Analysis- isDisposed");
12105 _checkThread(instrumentation);
12106 try {
12107 instrumentation.metric3("contextId", _contextId);
12108 return _basis.isDisposed;
12109 } finally {
12110 instrumentation.log();
12111 }
12112 }
12113
12114 @override
12115 bool isServerLibrary(Source librarySource) {
12116 InstrumentationBuilder instrumentation = Instrumentation.builder2("Analysis- isServerLibrary");
12117 _checkThread(instrumentation);
12118 try {
12119 instrumentation.metric3("contextId", _contextId);
12120 return _basis.isServerLibrary(librarySource);
12121 } finally {
12122 instrumentation.log();
12123 }
12124 }
12125
12126 @override
12127 void mergeContext(AnalysisContext context) {
12128 InstrumentationBuilder instrumentation = Instrumentation.builder2("Analysis- mergeContext");
12129 _checkThread(instrumentation);
12130 try {
12131 instrumentation.metric3("contextId", _contextId);
12132 if (context is InstrumentedAnalysisContextImpl) {
12133 context = (context as InstrumentedAnalysisContextImpl)._basis;
12134 }
12135 _basis.mergeContext(context);
12136 } finally {
12137 instrumentation.log();
12138 }
12139 }
12140
12141 @override
12142 CompilationUnit parseCompilationUnit(Source source) {
12143 InstrumentationBuilder instrumentation = Instrumentation.builder2("Analysis- parseCompilationUnit");
12144 _checkThread(instrumentation);
12145 try {
12146 instrumentation.metric3("contextId", _contextId);
12147 return _basis.parseCompilationUnit(source);
12148 } on AnalysisException catch (e, stackTrace) {
12149 _recordAnalysisException(instrumentation, new CaughtException(e, stackTrac e));
12150 throw e;
12151 } finally {
12152 instrumentation.log();
12153 }
12154 }
12155
12156 @override
12157 ht.HtmlUnit parseHtmlUnit(Source source) {
12158 InstrumentationBuilder instrumentation = Instrumentation.builder2("Analysis- parseHtmlUnit");
12159 _checkThread(instrumentation);
12160 try {
12161 instrumentation.metric3("contextId", _contextId);
12162 return _basis.parseHtmlUnit(source);
12163 } on AnalysisException catch (e, stackTrace) {
12164 _recordAnalysisException(instrumentation, new CaughtException(e, stackTrac e));
12165 throw e;
12166 } finally {
12167 instrumentation.log();
12168 }
12169 }
12170
12171 @override
12172 AnalysisResult performAnalysisTask() {
12173 InstrumentationBuilder instrumentation = Instrumentation.builder2("Analysis- performAnalysisTask");
12174 _checkThread(instrumentation);
12175 try {
12176 instrumentation.metric3("contextId", _contextId);
12177 AnalysisResult result = _basis.performAnalysisTask();
12178 if (result.changeNotices != null) {
12179 instrumentation.metric2("ChangeNotice-count", result.changeNotices.lengt h);
12180 }
12181 return result;
12182 } finally {
12183 instrumentation.log2(2);
12184 }
12185 }
12186
12187 @override
12188 void recordLibraryElements(Map<Source, LibraryElement> elementMap) {
12189 _basis.recordLibraryElements(elementMap);
12190 }
12191
12192 @override
12193 void removeListener(AnalysisListener listener) {
12194 _basis.removeListener(listener);
12195 }
12196
12197 @override
12198 CompilationUnit resolveCompilationUnit(Source unitSource, LibraryElement libra ry) {
12199 InstrumentationBuilder instrumentation = Instrumentation.builder2("Analysis- resolveCompilationUnit");
12200 _checkThread(instrumentation);
12201 try {
12202 instrumentation.metric3("contextId", _contextId);
12203 return _basis.resolveCompilationUnit(unitSource, library);
12204 } on AnalysisException catch (e, stackTrace) {
12205 _recordAnalysisException(instrumentation, new CaughtException(e, stackTrac e));
12206 throw e;
12207 } finally {
12208 instrumentation.log();
12209 }
12210 }
12211
12212 @override
12213 CompilationUnit resolveCompilationUnit2(Source unitSource, Source librarySourc e) {
12214 InstrumentationBuilder instrumentation = Instrumentation.builder2("Analysis- resolveCompilationUnit");
12215 _checkThread(instrumentation);
12216 try {
12217 instrumentation.metric3("contextId", _contextId);
12218 return _basis.resolveCompilationUnit2(unitSource, librarySource);
12219 } on AnalysisException catch (e, stackTrace) {
12220 _recordAnalysisException(instrumentation, new CaughtException(e, stackTrac e));
12221 throw e;
12222 } finally {
12223 instrumentation.log();
12224 }
12225 }
12226
12227 @override
12228 ht.HtmlUnit resolveHtmlUnit(Source htmlSource) {
12229 InstrumentationBuilder instrumentation = Instrumentation.builder2("Analysis- resolveHtmlUnit");
12230 _checkThread(instrumentation);
12231 try {
12232 instrumentation.metric3("contextId", _contextId);
12233 return _basis.resolveHtmlUnit(htmlSource);
12234 } on AnalysisException catch (e, stackTrace) {
12235 _recordAnalysisException(instrumentation, new CaughtException(e, stackTrac e));
12236 throw e;
12237 } finally {
12238 instrumentation.log();
12239 }
12240 }
12241
12242 @override
12243 void set analysisOptions(AnalysisOptions options) {
12244 InstrumentationBuilder instrumentation = Instrumentation.builder2("Analysis- setAnalysisOptions");
12245 _checkThread(instrumentation);
12246 try {
12247 instrumentation.metric3("contextId", _contextId);
12248 _basis.analysisOptions = options;
12249 } finally {
12250 instrumentation.log();
12251 }
12252 }
12253
12254 @override
12255 void set analysisPriorityOrder(List<Source> sources) {
12256 InstrumentationBuilder instrumentation = Instrumentation.builder2("Analysis- setAnalysisPriorityOrder");
12257 _checkThread(instrumentation);
12258 try {
12259 instrumentation.metric3("contextId", _contextId);
12260 _basis.analysisPriorityOrder = sources;
12261 } finally {
12262 instrumentation.log();
12263 }
12264 }
12265
12266 @override
12267 void setChangedContents(Source source, String contents, int offset, int oldLen gth, int newLength) {
12268 InstrumentationBuilder instrumentation = Instrumentation.builder2("Analysis- setChangedContents");
12269 _checkThread(instrumentation);
12270 try {
12271 instrumentation.metric3("contextId", _contextId);
12272 _basis.setChangedContents(source, contents, offset, oldLength, newLength);
12273 } finally {
12274 instrumentation.log();
12275 }
12276 }
12277
12278 @override
12279 void setContents(Source source, String contents) {
12280 InstrumentationBuilder instrumentation = Instrumentation.builder2("Analysis- setContents");
12281 _checkThread(instrumentation);
12282 try {
12283 instrumentation.metric3("contextId", _contextId);
12284 _basis.setContents(source, contents);
12285 } finally {
12286 instrumentation.log();
12287 }
12288 }
12289
12290 @override
12291 void set sourceFactory(SourceFactory factory) {
12292 InstrumentationBuilder instrumentation = Instrumentation.builder2("Analysis- setSourceFactory");
12293 _checkThread(instrumentation);
12294 try {
12295 instrumentation.metric3("contextId", _contextId);
12296 _basis.sourceFactory = factory;
12297 } finally {
12298 instrumentation.log();
12299 }
12300 }
12301 }
12302
12303 /**
12304 * The interface `InternalAnalysisContext` defines additional behavior for an an alysis context
12305 * that is required by internal users of the context.
12306 */
12307 abstract class InternalAnalysisContext implements AnalysisContext {
12308 /**
12309 * Add the given source with the given information to this context.
12310 *
12311 * @param source the source to be added
12312 * @param info the information about the source
12313 */
12314 void addSourceInfo(Source source, SourceEntry info);
12315
12316 /**
12317 * Return an array containing the sources of the libraries that are exported b y the library with
12318 * the given source. The array will be empty if the given source is invalid, i f the given source
12319 * does not represent a library, or if the library does not export any other l ibraries.
12320 *
12321 * @param source the source representing the library whose exports are to be r eturned
12322 * @return the sources of the libraries that are exported by the given library
12323 * @throws AnalysisException if the exported libraries could not be computed
12324 */
12325 List<Source> computeExportedLibraries(Source source);
12326
12327 /**
12328 * Return an array containing the sources of the libraries that are imported b y the library with
12329 * the given source. The array will be empty if the given source is invalid, i f the given source
12330 * does not represent a library, or if the library does not import any other l ibraries.
12331 *
12332 * @param source the source representing the library whose imports are to be r eturned
12333 * @return the sources of the libraries that are imported by the given library
12334 * @throws AnalysisException if the imported libraries could not be computed
12335 */
12336 List<Source> computeImportedLibraries(Source source);
12337
12338 /**
12339 * Return an AST structure corresponding to the given source, but ensure that the structure has
12340 * not already been resolved and will not be resolved by any other threads or in any other
12341 * library.
12342 *
12343 * <b>Note:</b> This method cannot be used in an async environment
12344 *
12345 * @param source the compilation unit for which an AST structure should be ret urned
12346 * @return the AST structure representing the content of the source
12347 * @throws AnalysisException if the analysis could not be performed
12348 */
12349 ResolvableCompilationUnit computeResolvableCompilationUnit(Source source);
12350
12351 /**
12352 * Initialize the specified context by removing the specified sources from the receiver and adding
12353 * them to the specified context.
12354 *
12355 * @param container the container containing sources that should be removed fr om this context and
12356 * added to the returned context
12357 * @param newContext the context to be initialized
12358 * @return the analysis context that was initialized
12359 */
12360 InternalAnalysisContext extractContextInto(SourceContainer container, Internal AnalysisContext newContext);
12361
12362 /**
12363 * Return an array containing all of the sources that have been marked as prio rity sources.
12364 * Clients must not modify the returned array.
12365 *
12366 * @return the sources that have been marked as priority sources
12367 */
12368 List<Source> get prioritySources;
12369
12370 /**
12371 * Return a namespace containing mappings for all of the public names defined by the given
12372 * library.
12373 *
12374 * @param library the library whose public namespace is to be returned
12375 * @return the public namespace of the given library
12376 */
12377 Namespace getPublicNamespace(LibraryElement library);
12378
12379 /**
12380 * Returns a statistics about this context.
12381 */
12382 AnalysisContextStatistics get statistics;
12383
12384 /**
12385 * Returns a type provider for this context or throws an exception if dart:cor e cannot be
12386 * resolved.
12387 *
12388 * @return the type provider (not `null`)
12389 * @throws AnalysisException if dart:core cannot be resolved
12390 */
12391 TypeProvider get typeProvider;
12392
12393 /**
12394 * Given a table mapping the source for the libraries represented by the corre sponding elements to
12395 * the elements representing the libraries, record those mappings.
12396 *
12397 * @param elementMap a table mapping the source for the libraries represented by the elements to
12398 * the elements representing the libraries
12399 */
12400 void recordLibraryElements(Map<Source, LibraryElement> elementMap);
12401 }
12402
12403 /**
12404 * The interface `Logger` defines the behavior of objects that can be used to re ceive
12405 * information about errors within the analysis engine. Implementations usually write this
12406 * information to a file, but can also record the information for later use (suc h as during testing)
12407 * or even ignore the information.
12408 */
12409 abstract class Logger {
12410 static final Logger NULL = new Logger_NullLogger();
12411
12412 /**
12413 * Log the given message as an error.
12414 *
12415 * @param message an explanation of why the error occurred or what it means
12416 */
12417 void logError(String message);
12418
12419 /**
12420 * Log the given exception as one representing an error.
12421 *
12422 * @param message an explanation of why the error occurred or what it means
12423 * @param exception the exception being logged
12424 */
12425 void logError2(String message, Exception exception);
12426
12427 /**
12428 * Log the given informational message.
12429 *
12430 * @param message an explanation of why the error occurred or what it means
12431 * @param exception the exception being logged
12432 */
12433 void logInformation(String message);
12434
12435 /**
12436 * Log the given exception as one representing an informational message.
12437 *
12438 * @param message an explanation of why the error occurred or what it means
12439 * @param exception the exception being logged
12440 */
12441 void logInformation2(String message, Exception exception);
12442 }
12443
12444 /**
12445 * Implementation of [Logger] that does nothing.
12446 */
12447 class Logger_NullLogger implements Logger {
12448 @override
12449 void logError(String message) {
12450 }
12451
12452 @override
12453 void logError2(String message, Exception exception) {
12454 }
12455
12456 @override
12457 void logInformation(String message) {
12458 }
12459
12460 @override
12461 void logInformation2(String message, Exception exception) {
12462 }
12463 }
12464
12465 /**
12466 * [NgComponentElementProcessor] applies [AngularComponentElement] by parsing ma pped
12467 * attributes as expressions.
12468 */
12469 class NgComponentElementProcessor extends NgDirectiveProcessor {
12470 final AngularComponentElement _element;
12471
12472 NgComponentElementProcessor(this._element);
12473
12474 @override
12475 void apply(AngularHtmlUnitResolver resolver, ht.XmlTagNode node) {
12476 node.element = _element.selector;
12477 for (AngularPropertyElement property in _element.properties) {
12478 String name = property.name;
12479 ht.XmlAttributeNode attribute = node.getAttribute(name);
12480 if (attribute != null) {
12481 attribute.element = property;
12482 // resolve if binding
12483 if (property.propertyKind != AngularPropertyKind.ATTR) {
12484 AngularExpression expression = parseAngularExpression(resolver, attrib ute);
12485 resolver._resolveExpression(expression);
12486 setAngularExpression(attribute, expression);
12487 }
12488 }
12489 }
12490 }
12491
12492 @override
12493 bool canApply(ht.XmlTagNode node) => _element.selector.apply(node);
12494 }
12495
12496 /**
12497 * [NgControllerElementProcessor] applies [AngularControllerElement].
12498 */
12499 class NgControllerElementProcessor extends NgProcessor {
12500 final AngularControllerElement _element;
12501
12502 NgControllerElementProcessor(this._element);
12503
12504 @override
12505 void apply(AngularHtmlUnitResolver resolver, ht.XmlTagNode node) {
12506 InterfaceType type = (_element.enclosingElement as ClassElement).type;
12507 String name = _element.name;
12508 LocalVariableElementImpl variable = resolver._createLocalVariableWithName(ty pe, name);
12509 resolver._defineVariable(variable);
12510 variable.toolkitObjects = <AngularElement> [_element];
12511 }
12512
12513 @override
12514 bool canApply(ht.XmlTagNode node) => _element.selector.apply(node);
12515 }
12516
12517 /**
12518 * [NgDecoratorElementProcessor] applies [AngularDecoratorElement] by parsing ma pped
12519 * attributes as expressions.
12520 */
12521 class NgDecoratorElementProcessor extends NgDirectiveProcessor {
12522 final AngularDecoratorElement _element;
12523
12524 NgDecoratorElementProcessor(this._element);
12525
12526 @override
12527 void apply(AngularHtmlUnitResolver resolver, ht.XmlTagNode node) {
12528 String selectorAttributeName = null;
12529 {
12530 AngularSelectorElement selector = _element.selector;
12531 if (selector is HasAttributeSelectorElementImpl) {
12532 selectorAttributeName = selector.name;
12533 // resolve attribute expression
12534 ht.XmlAttributeNode attribute = node.getAttribute(selectorAttributeName) ;
12535 if (attribute != null) {
12536 attribute.element = selector;
12537 }
12538 }
12539 }
12540 //
12541 for (AngularPropertyElement property in _element.properties) {
12542 // prepare attribute name
12543 String name = property.name;
12544 if (name == ".") {
12545 name = selectorAttributeName;
12546 }
12547 // prepare attribute
12548 ht.XmlAttributeNode attribute = node.getAttribute(name);
12549 if (attribute == null) {
12550 continue;
12551 }
12552 // if not resolved as the selector, resolve as a property
12553 if (name != selectorAttributeName) {
12554 attribute.element = property;
12555 }
12556 // skip if attribute has no value
12557 if (!NgDirectiveProcessor.hasValue(attribute)) {
12558 continue;
12559 }
12560 // resolve if binding
12561 if (property.propertyKind != AngularPropertyKind.ATTR) {
12562 resolver._pushNameScope();
12563 try {
12564 _onNgEventDirective(resolver);
12565 AngularExpression expression = parseAngularExpression(resolver, attrib ute);
12566 resolver._resolveExpression(expression);
12567 setAngularExpression(attribute, expression);
12568 } finally {
12569 resolver._popNameScope();
12570 }
12571 }
12572 }
12573 }
12574
12575 @override
12576 bool canApply(ht.XmlTagNode node) => _element.selector.apply(node);
12577
12578 /**
12579 * Support for <code>$event</code> variable in <code>NgEventDirective</code>.
12580 */
12581 void _onNgEventDirective(AngularHtmlUnitResolver resolver) {
12582 if (_element.isClass("NgEventDirective")) {
12583 DartType dynamicType = resolver.typeProvider.dynamicType;
12584 resolver._defineVariable(resolver._createLocalVariableWithName(dynamicType , "\$event"));
12585 }
12586 }
12587 }
12588
12589 /**
12590 * [NgDirectiveProcessor] describes any <code>Directive</code> annotation instan ce.
12591 */
12592 abstract class NgDirectiveProcessor extends NgProcessor {
12593 static bool hasValue(ht.XmlAttributeNode attribute) {
12594 ht.Token valueToken = attribute.valueToken;
12595 return valueToken != null && !valueToken.isSynthetic;
12596 }
12597
12598 static AngularRawXmlExpression newAngularRawXmlExpression(AngularExpression e) => new AngularRawXmlExpression(e);
12599
12600 static ht.RawXmlExpression newRawXmlExpression(Expression e) => new ht.RawXmlE xpression(e);
12601
12602 AngularExpression parseAngularExpression(AngularHtmlUnitResolver resolver, ht. XmlAttributeNode attribute) {
12603 Token token = _scanAttribute(resolver, attribute);
12604 return resolver._parseAngularExpressionInToken(token);
12605 }
12606
12607 Expression parseDartExpression(AngularHtmlUnitResolver resolver, ht.XmlAttribu teNode attribute) {
12608 Token token = _scanAttribute(resolver, attribute);
12609 return resolver._parseDartExpressionInToken(token);
12610 }
12611
12612 /**
12613 * Sets single [AngularExpression] for [XmlAttributeNode].
12614 */
12615 void setAngularExpression(ht.XmlAttributeNode attribute, AngularExpression exp ression) {
12616 _setExpression(attribute, newAngularRawXmlExpression(expression));
12617 }
12618
12619 /**
12620 * Sets single [Expression] for [XmlAttributeNode].
12621 */
12622 void setExpression(ht.XmlAttributeNode attribute, Expression expression) {
12623 _setExpression(attribute, newRawXmlExpression(expression));
12624 }
12625
12626 void setExpressions(ht.XmlAttributeNode attribute, List<ht.XmlExpression> xmlE xpressions) {
12627 attribute.expressions = new List.from(xmlExpressions);
12628 }
12629
12630 Token _scanAttribute(AngularHtmlUnitResolver resolver, ht.XmlAttributeNode att ribute) {
12631 int offset = attribute.valueToken.offset + 1;
12632 String value = attribute.text;
12633 return resolver._scanDart(value, 0, value.length, offset);
12634 }
12635
12636 void _setExpression(ht.XmlAttributeNode attribute, ht.XmlExpression xmlExpress ion) {
12637 attribute.expressions = <ht.XmlExpression> [xmlExpression];
12638 }
12639 }
12640
12641 /**
12642 * [NgModelProcessor] describes built-in <code>NgModel</code> directive.
12643 */
12644 class NgModelProcessor extends NgDirectiveProcessor {
12645 static String _NG_MODEL = "ng-model";
12646
12647 static NgModelProcessor INSTANCE = new NgModelProcessor();
12648
12649 @override
12650 void apply(AngularHtmlUnitResolver resolver, ht.XmlTagNode node) {
12651 ht.XmlAttributeNode attribute = node.getAttribute(_NG_MODEL);
12652 Expression expression = parseDartExpression(resolver, attribute);
12653 // identifiers have been already handled by "apply top"
12654 if (expression is SimpleIdentifier) {
12655 return;
12656 }
12657 // resolve
12658 resolver._resolveNode(expression);
12659 // remember expression
12660 setExpression(attribute, expression);
12661 }
12662
12663 @override
12664 bool canApply(ht.XmlTagNode node) => node.getAttribute(_NG_MODEL) != null;
12665
12666 /**
12667 * This method is used to define top-level [VariableElement]s for each "ng-mod el" with
12668 * simple identifier model.
12669 */
12670 void _applyTopDeclarations(AngularHtmlUnitResolver resolver, ht.XmlTagNode nod e) {
12671 ht.XmlAttributeNode attribute = node.getAttribute(_NG_MODEL);
12672 Expression expression = parseDartExpression(resolver, attribute);
12673 // if not identifier, then not a top-level model, delay until "apply"
12674 if (expression is! SimpleIdentifier) {
12675 return;
12676 }
12677 SimpleIdentifier identifier = expression as SimpleIdentifier;
12678 // define variable Element
12679 InterfaceType type = resolver.typeProvider.stringType;
12680 LocalVariableElementImpl element = resolver._createLocalVariableFromIdentifi er(type, identifier);
12681 resolver._defineTopVariable(element);
12682 // remember expression
12683 identifier.staticElement = element;
12684 identifier.staticType = type;
12685 setExpression(attribute, identifier);
12686 }
12687 }
12688
12689 /**
12690 * [NgProcessor] is used to apply an Angular feature.
12691 */
12692 abstract class NgProcessor {
12693 /**
12694 * Applies this [NgProcessor] to the resolver.
12695 *
12696 * @param resolver the [AngularHtmlUnitResolver] to apply to, not `null`
12697 * @param node the [XmlTagNode] to apply within, not `null`
12698 */
12699 void apply(AngularHtmlUnitResolver resolver, ht.XmlTagNode node);
12700
12701 /**
12702 * Checks if this processor can be applied to the given [XmlTagNode].
12703 *
12704 * @param node the [XmlTagNode] to check
12705 * @return `true` if this processor can be applied, or `false` otherwise
12706 */
12707 bool canApply(ht.XmlTagNode node);
12708 }
12709
12710 /**
12711 * Instances of the class `ObsoleteSourceAnalysisException` represent an analysi s attempt that
12712 * failed because a source was deleted between the time the analysis started and the time the
12713 * results of the analysis were ready to be recorded.
12714 */
12715 class ObsoleteSourceAnalysisException extends AnalysisException {
12716 /**
12717 * The source that was removed while it was being analyzed.
12718 */
12719 Source _source;
12720
12721 /**
12722 * Initialize a newly created exception to represent the removal of the given source.
12723 *
12724 * @param source the source that was removed while it was being analyzed
12725 */
12726 ObsoleteSourceAnalysisException(Source source) : super("The source '${source.f ullName}' was removed while it was being analyzed") {
12727 this._source = source;
12728 }
12729
12730 /**
12731 * Return the source that was removed while it was being analyzed.
12732 *
12733 * @return the source that was removed
12734 */
12735 Source get source => _source;
12736 }
12737
12738 /**
12739 * Instances of the class `ParseDartTask` parse a specific source as a Dart file .
12740 */
12741 class ParseDartTask extends AnalysisTask {
12742 /**
12743 * Return the result of resolving the URI of the given URI-based directive aga inst the URI of the
12744 * given library, or `null` if the URI is not valid.
12745 *
12746 * @param context the context in which the resolution is to be performed
12747 * @param librarySource the source representing the library containing the dir ective
12748 * @param directive the directive which URI should be resolved
12749 * @param errorListener the error listener to which errors should be reported
12750 * @return the result of resolving the URI against the URI of the library
12751 */
12752 static Source resolveDirective(AnalysisContext context, Source librarySource, UriBasedDirective directive, AnalysisErrorListener errorListener) {
12753 StringLiteral uriLiteral = directive.uri;
12754 String uriContent = uriLiteral.stringValue;
12755 if (uriContent != null) {
12756 uriContent = uriContent.trim();
12757 directive.uriContent = uriContent;
12758 }
12759 UriValidationCode code = directive.validate();
12760 if (code == null) {
12761 String encodedUriContent = Uri.encodeFull(uriContent);
12762 Source source = context.sourceFactory.resolveUri(librarySource, encodedUri Content);
12763 directive.source = source;
12764 return source;
12765 }
12766 if (code == UriValidationCode.URI_WITH_DART_EXT_SCHEME) {
12767 return null;
12768 }
12769 if (code == UriValidationCode.URI_WITH_INTERPOLATION) {
12770 errorListener.onError(new AnalysisError.con2(librarySource, uriLiteral.off set, uriLiteral.length, CompileTimeErrorCode.URI_WITH_INTERPOLATION, []));
12771 return null;
12772 }
12773 if (code == UriValidationCode.INVALID_URI) {
12774 errorListener.onError(new AnalysisError.con2(librarySource, uriLiteral.off set, uriLiteral.length, CompileTimeErrorCode.INVALID_URI, [uriContent]));
12775 return null;
12776 }
12777 throw new RuntimeException(message: "Failed to handle validation code: ${cod e}");
12778 }
12779
12780 /**
12781 * The source to be parsed.
12782 */
12783 final Source source;
12784
12785 /**
12786 * The time at which the contents of the source were last modified.
12787 */
12788 final int modificationTime;
12789
12790 /**
12791 * The head of the token stream used for parsing.
12792 */
12793 final Token _tokenStream;
12794
12795 /**
12796 * The line information associated with the source.
12797 */
12798 final LineInfo lineInfo;
12799
12800 /**
12801 * The compilation unit that was produced by parsing the source.
12802 */
12803 CompilationUnit _unit;
12804
12805 /**
12806 * A flag indicating whether the source contains a 'part of' directive.
12807 */
12808 bool _containsPartOfDirective = false;
12809
12810 /**
12811 * A flag indicating whether the source contains any directive other than a 'p art of' directive.
12812 */
12813 bool _containsNonPartOfDirective = false;
12814
12815 /**
12816 * A set containing the sources referenced by 'export' directives.
12817 */
12818 HashSet<Source> _exportedSources = new HashSet<Source>();
12819
12820 /**
12821 * A set containing the sources referenced by 'import' directives.
12822 */
12823 HashSet<Source> _importedSources = new HashSet<Source>();
12824
12825 /**
12826 * A set containing the sources referenced by 'part' directives.
12827 */
12828 HashSet<Source> _includedSources = new HashSet<Source>();
12829
12830 /**
12831 * The errors that were produced by scanning and parsing the source.
12832 */
12833 List<AnalysisError> _errors = AnalysisError.NO_ERRORS;
12834
12835 /**
12836 * Initialize a newly created task to perform analysis within the given contex t.
12837 *
12838 * @param context the context in which the task is to be performed
12839 * @param source the source to be parsed
12840 * @param modificationTime the time at which the contents of the source were l ast modified
12841 * @param tokenStream the head of the token stream used for parsing
12842 * @param lineInfo the line information associated with the source
12843 */
12844 ParseDartTask(InternalAnalysisContext context, this.source, this.modificationT ime, this._tokenStream, this.lineInfo) : super(context);
12845
12846 @override
12847 accept(AnalysisTaskVisitor visitor) => visitor.visitParseDartTask(this);
12848
12849 /**
12850 * Return the compilation unit that was produced by parsing the source, or `nu ll` if the
12851 * task has not yet been performed or if an exception occurred.
12852 *
12853 * @return the compilation unit that was produced by parsing the source
12854 */
12855 CompilationUnit get compilationUnit => _unit;
12856
12857 /**
12858 * Return the errors that were produced by scanning and parsing the source, or an empty array if
12859 * the task has not yet been performed or if an exception occurred.
12860 *
12861 * @return the errors that were produced by scanning and parsing the source
12862 */
12863 List<AnalysisError> get errors => _errors;
12864
12865 /**
12866 * Return an array containing the sources referenced by 'export' directives, o r an empty array if
12867 * the task has not yet been performed or if an exception occurred.
12868 *
12869 * @return an array containing the sources referenced by 'export' directives
12870 */
12871 List<Source> get exportedSources => _toArray(_exportedSources);
12872
12873 /**
12874 * Return an array containing the sources referenced by 'import' directives, o r an empty array if
12875 * the task has not yet been performed or if an exception occurred.
12876 *
12877 * @return an array containing the sources referenced by 'import' directives
12878 */
12879 List<Source> get importedSources => _toArray(_importedSources);
12880
12881 /**
12882 * Return an array containing the sources referenced by 'part' directives, or an empty array if
12883 * the task has not yet been performed or if an exception occurred.
12884 *
12885 * @return an array containing the sources referenced by 'part' directives
12886 */
12887 List<Source> get includedSources => _toArray(_includedSources);
12888
12889 /**
12890 * Return `true` if the source contains any directive other than a 'part of' d irective, or
12891 * `false` if the task has not yet been performed or if an exception occurred.
12892 *
12893 * @return `true` if the source contains any directive other than a 'part of' directive
12894 */
12895 bool get hasNonPartOfDirective => _containsNonPartOfDirective;
12896
12897 /**
12898 * Return `true` if the source contains a 'part of' directive, or `false` if t he task
12899 * has not yet been performed or if an exception occurred.
12900 *
12901 * @return `true` if the source contains a 'part of' directive
12902 */
12903 bool get hasPartOfDirective => _containsPartOfDirective;
12904
12905 @override
12906 String get taskDescription {
12907 if (source == null) {
12908 return "parse as dart null source";
12909 }
12910 return "parse as dart ${source.fullName}";
12911 }
12912
12913 @override
12914 void internalPerform() {
12915 //
12916 // Then parse the token stream.
12917 //
12918 TimeCounter_TimeCounterHandle timeCounterParse = PerformanceStatistics.parse .start();
12919 try {
12920 RecordingErrorListener errorListener = new RecordingErrorListener();
12921 Parser parser = new Parser(source, errorListener);
12922 AnalysisOptions options = context.analysisOptions;
12923 parser.parseFunctionBodies = options.analyzeFunctionBodies;
12924 parser.parseAsync = options.enableAsync;
12925 parser.parseDeferredLibraries = options.enableDeferredLoading;
12926 parser.parseEnum = options.enableEnum;
12927 _unit = parser.parseCompilationUnit(_tokenStream);
12928 _unit.lineInfo = lineInfo;
12929 AnalysisContext analysisContext = context;
12930 for (Directive directive in _unit.directives) {
12931 if (directive is PartOfDirective) {
12932 _containsPartOfDirective = true;
12933 } else {
12934 _containsNonPartOfDirective = true;
12935 if (directive is UriBasedDirective) {
12936 Source referencedSource = resolveDirective(analysisContext, source, directive, errorListener);
12937 if (referencedSource != null) {
12938 if (directive is ExportDirective) {
12939 _exportedSources.add(referencedSource);
12940 } else if (directive is ImportDirective) {
12941 _importedSources.add(referencedSource);
12942 } else if (directive is PartDirective) {
12943 if (referencedSource != source) {
12944 _includedSources.add(referencedSource);
12945 }
12946 } else {
12947 throw new AnalysisException("${runtimeType.toString()} failed to handle a ${directive.runtimeType.toString()}");
12948 }
12949 }
12950 }
12951 }
12952 }
12953 _errors = errorListener.getErrorsForSource(source);
12954 } finally {
12955 timeCounterParse.stop();
12956 }
12957 }
12958
12959 /**
12960 * Efficiently convert the given set of sources to an array.
12961 *
12962 * @param sources the set to be converted
12963 * @return an array containing all of the sources in the given set
12964 */
12965 List<Source> _toArray(HashSet<Source> sources) {
12966 int size = sources.length;
12967 if (size == 0) {
12968 return Source.EMPTY_ARRAY;
12969 }
12970 return new List.from(sources);
12971 }
12972 }
12973
12974 /**
12975 * Instances of the class `ParseHtmlTask` parse a specific source as an HTML fil e.
12976 */
12977 class ParseHtmlTask extends AnalysisTask {
12978 /**
12979 * The source to be parsed.
12980 */
12981 final Source source;
12982
12983 /**
12984 * The time at which the contents of the source were last modified.
12985 */
12986 final int modificationTime;
12987
12988 /**
12989 * The contents of the source.
12990 */
12991 final String _content;
12992
12993 /**
12994 * The line information that was produced.
12995 */
12996 LineInfo _lineInfo;
12997
12998 /**
12999 * The HTML unit that was produced by parsing the source.
13000 */
13001 ht.HtmlUnit _unit;
13002
13003 /**
13004 * The errors that were produced by scanning and parsing the source.
13005 */
13006 List<AnalysisError> _errors = AnalysisError.NO_ERRORS;
13007
13008 /**
13009 * An array containing the sources of the libraries that are referenced within the HTML.
13010 */
13011 List<Source> _referencedLibraries = Source.EMPTY_ARRAY;
13012
13013 /**
13014 * The name of the 'src' attribute in a HTML tag.
13015 */
13016 static String _ATTRIBUTE_SRC = "src";
13017
13018 /**
13019 * The name of the 'script' tag in an HTML file.
13020 */
13021 static String _TAG_SCRIPT = "script";
13022
13023 /**
13024 * Initialize a newly created task to perform analysis within the given contex t.
13025 *
13026 * @param context the context in which the task is to be performed
13027 * @param source the source to be parsed
13028 * @param modificationTime the time at which the contents of the source were l ast modified
13029 * @param content the contents of the source
13030 */
13031 ParseHtmlTask(InternalAnalysisContext context, this.source, this.modificationT ime, this._content) : super(context);
13032
13033 @override
13034 accept(AnalysisTaskVisitor visitor) => visitor.visitParseHtmlTask(this);
13035
13036 /**
13037 * Return the errors that were produced by scanning and parsing the source, or `null` if the
13038 * task has not yet been performed or if an exception occurred.
13039 *
13040 * @return the errors that were produced by scanning and parsing the source
13041 */
13042 List<AnalysisError> get errors => _errors;
13043
13044 /**
13045 * Return the HTML unit that was produced by parsing the source.
13046 *
13047 * @return the HTML unit that was produced by parsing the source
13048 */
13049 ht.HtmlUnit get htmlUnit => _unit;
13050
13051 /**
13052 * Return the line information that was produced, or `null` if the task has no t yet been
13053 * performed or if an exception occurred.
13054 *
13055 * @return the line information that was produced
13056 */
13057 LineInfo get lineInfo => _lineInfo;
13058
13059 /**
13060 * Return an array containing the sources of the libraries that are referenced within the HTML.
13061 *
13062 * @return the sources of the libraries that are referenced within the HTML
13063 */
13064 List<Source> get referencedLibraries => _referencedLibraries;
13065
13066 @override
13067 String get taskDescription {
13068 if (source == null) {
13069 return "parse as html null source";
13070 }
13071 return "parse as html ${source.fullName}";
13072 }
13073
13074 @override
13075 void internalPerform() {
13076 try {
13077 ht.AbstractScanner scanner = new ht.StringScanner(source, _content);
13078 scanner.passThroughElements = <String> [_TAG_SCRIPT];
13079 ht.Token token = scanner.tokenize();
13080 _lineInfo = new LineInfo(scanner.lineStarts);
13081 RecordingErrorListener errorListener = new RecordingErrorListener();
13082 _unit = new ht.HtmlParser(source, errorListener).parse(token, _lineInfo);
13083 _unit.accept(new RecursiveXmlVisitor_ParseHtmlTask_internalPerform(this, e rrorListener));
13084 _errors = errorListener.getErrorsForSource(source);
13085 _referencedLibraries = librarySources;
13086 } catch (exception, stackTrace) {
13087 throw new AnalysisException("Exception", new CaughtException(exception, st ackTrace));
13088 }
13089 }
13090
13091 /**
13092 * Return the sources of libraries that are referenced in the specified HTML f ile.
13093 *
13094 * @return the sources of libraries that are referenced in the HTML file
13095 */
13096 List<Source> get librarySources {
13097 List<Source> libraries = new List<Source>();
13098 _unit.accept(new RecursiveXmlVisitor_ParseHtmlTask_getLibrarySources(this, l ibraries));
13099 if (libraries.isEmpty) {
13100 return Source.EMPTY_ARRAY;
13101 }
13102 return new List.from(libraries);
13103 }
13104
13105 /**
13106 * Resolves directives in the given [CompilationUnit].
13107 */
13108 void _resolveScriptDirectives(CompilationUnit script, AnalysisErrorListener er rorListener) {
13109 if (script == null) {
13110 return;
13111 }
13112 AnalysisContext analysisContext = context;
13113 for (Directive directive in script.directives) {
13114 if (directive is UriBasedDirective) {
13115 ParseDartTask.resolveDirective(analysisContext, source, directive, error Listener);
13116 }
13117 }
13118 }
13119 }
13120
13121 /**
13122 * Instances of the class `PartitionManager` manage the partitions that can be s hared between
13123 * analysis contexts.
13124 */
13125 class PartitionManager {
13126 /**
13127 * A table mapping SDK's to the partitions used for those SDK's.
13128 */
13129 HashMap<DartSdk, SdkCachePartition> _sdkPartitions = new HashMap<DartSdk, SdkC achePartition>();
13130
13131 /**
13132 * The default cache size for a Dart SDK partition.
13133 */
13134 static int _DEFAULT_SDK_CACHE_SIZE = 256;
13135
13136 /**
13137 * Return the partition being used for the given SDK, creating the partition i f necessary.
13138 *
13139 * @param sdk the SDK for which a partition is being requested
13140 * @return the partition being used for the given SDK
13141 */
13142 SdkCachePartition forSdk(DartSdk sdk) {
13143 SdkCachePartition partition = _sdkPartitions[sdk];
13144 if (partition == null) {
13145 partition = new SdkCachePartition(_DEFAULT_SDK_CACHE_SIZE);
13146 _sdkPartitions[sdk] = partition;
13147 }
13148 return partition;
13149 }
13150 }
13151
13152 /**
13153 * Container with global [AnalysisContext] performance statistics.
13154 */
13155 class PerformanceStatistics {
13156 /**
13157 * The [TimeCounter] for time spent in reading files.
13158 */
13159 static TimeCounter io = new TimeCounter();
13160
13161 /**
13162 * The [TimeCounter] for time spent in scanning.
13163 */
13164 static TimeCounter scan = new TimeCounter();
13165
13166 /**
13167 * The [TimeCounter] for time spent in parsing.
13168 */
13169 static TimeCounter parse = new TimeCounter();
13170
13171 /**
13172 * The [TimeCounter] for time spent in resolving.
13173 */
13174 static TimeCounter resolve = new TimeCounter();
13175
13176 /**
13177 * The [TimeCounter] for time spent in Angular analysis.
13178 */
13179 static TimeCounter angular = new TimeCounter();
13180
13181 /**
13182 * The [TimeCounter] for time spent in Polymer analysis.
13183 */
13184 static TimeCounter polymer = new TimeCounter();
13185
13186 /**
13187 * The [TimeCounter] for time spent in error verifier.
13188 */
13189 static TimeCounter errors = new TimeCounter();
13190
13191 /**
13192 * The [TimeCounter] for time spent in hints generator.
13193 */
13194 static TimeCounter hints = new TimeCounter();
13195
13196 /**
13197 * Reset all of the time counters to zero.
13198 */
13199 static void reset() {
13200 io = new TimeCounter();
13201 scan = new TimeCounter();
13202 parse = new TimeCounter();
13203 resolve = new TimeCounter();
13204 angular = new TimeCounter();
13205 polymer = new TimeCounter();
13206 errors = new TimeCounter();
13207 hints = new TimeCounter();
13208 }
13209 }
13210
13211 /**
13212 * Instances of the class `PolymerBuildHtmlTask` build Polymer specific elements .
13213 */
13214 class PolymerBuildHtmlTask extends AnalysisTask {
13215 /**
13216 * The source to build which Polymer HTML elements for.
13217 */
13218 final Source source;
13219
13220 /**
13221 * The time at which the contents of the source were last modified.
13222 */
13223 final int modificationTime;
13224
13225 /**
13226 * The line information associated with the source.
13227 */
13228 final LineInfo _lineInfo;
13229
13230 /**
13231 * The HTML unit to be resolved.
13232 */
13233 final ht.HtmlUnit _unit;
13234
13235 /**
13236 * The resolution errors that were discovered while building elements.
13237 */
13238 List<AnalysisError> _errors = AnalysisError.NO_ERRORS;
13239
13240 /**
13241 * Initialize a newly created task to perform analysis within the given contex t.
13242 *
13243 * @param context the context in which the task is to be performed
13244 * @param source the source to be resolved
13245 * @param modificationTime the time at which the contents of the source were l ast modified
13246 * @param lineInfo the line information associated with the source
13247 * @param unit the HTML unit to build Polymer elements for
13248 */
13249 PolymerBuildHtmlTask(InternalAnalysisContext context, this.source, this.modifi cationTime, this._lineInfo, this._unit) : super(context);
13250
13251 @override
13252 accept(AnalysisTaskVisitor visitor) => visitor.visitPolymerBuildHtmlTask(this) ;
13253
13254 List<AnalysisError> get errors => _errors;
13255
13256 @override
13257 String get taskDescription => "build Polymer elements ${source.fullName}";
13258
13259 @override
13260 void internalPerform() {
13261 RecordingErrorListener errorListener = new RecordingErrorListener();
13262 PolymerHtmlUnitBuilder resolver = new PolymerHtmlUnitBuilder(context, errorL istener, source, _lineInfo, _unit);
13263 resolver.build();
13264 _errors = errorListener.getErrorsForSource(source);
13265 }
13266 }
13267
13268 /**
13269 * Instances of the class [PolymerHtmlUnitBuilder] build Polymer specific elemen ts.
13270 */
13271 class PolymerHtmlUnitBuilder extends ht.RecursiveXmlVisitor<Object> {
13272 /**
13273 * These names are forbidden to use as a custom tag name.
13274 *
13275 * http://w3c.github.io/webcomponents/spec/custom/#concepts
13276 */
13277 static Set<String> _FORBIDDEN_TAG_NAMES = new Set();
13278
13279 static bool isValidAttributeName(String name) {
13280 // cannot be empty
13281 if (name.isEmpty) {
13282 return false;
13283 }
13284 // check characters
13285 int length = name.length;
13286 for (int i = 0; i < length; i++) {
13287 int c = name.codeUnitAt(i);
13288 if (i == 0) {
13289 if (!Character.isLetter(c)) {
13290 return false;
13291 }
13292 } else {
13293 if (!(Character.isLetterOrDigit(c) || c == 0x5F)) {
13294 return false;
13295 }
13296 }
13297 }
13298 return true;
13299 }
13300
13301 static bool isValidTagName(String name) {
13302 // cannot be empty
13303 if (name.isEmpty) {
13304 return false;
13305 }
13306 // check for forbidden name
13307 if (_FORBIDDEN_TAG_NAMES.contains(name)) {
13308 return false;
13309 }
13310 // check characters
13311 int length = name.length;
13312 bool hasDash = false;
13313 for (int i = 0; i < length; i++) {
13314 int c = name.codeUnitAt(i);
13315 // check for '-'
13316 if (c == 0x2D) {
13317 hasDash = true;
13318 }
13319 // check character
13320 if (i == 0) {
13321 if (hasDash) {
13322 return false;
13323 }
13324 if (!Character.isLetter(c)) {
13325 return false;
13326 }
13327 } else {
13328 if (!(Character.isLetterOrDigit(c) || c == 0x2D || c == 0x5F)) {
13329 return false;
13330 }
13331 }
13332 }
13333 if (!hasDash) {
13334 return false;
13335 }
13336 return true;
13337 }
13338
13339 final InternalAnalysisContext _context;
13340
13341 TypeProvider _typeProvider;
13342
13343 final AnalysisErrorListener _errorListener;
13344
13345 final Source _source;
13346
13347 final LineInfo _lineInfo;
13348
13349 final ht.HtmlUnit _unit;
13350
13351 List<PolymerTagHtmlElement> _tagHtmlElements = [];
13352
13353 ht.XmlTagNode _elementNode;
13354
13355 String _elementName;
13356
13357 PolymerTagHtmlElementImpl _htmlElement;
13358
13359 PolymerTagDartElementImpl _dartElement;
13360
13361 PolymerHtmlUnitBuilder(this._context, this._errorListener, this._source, this. _lineInfo, this._unit) {
13362 this._typeProvider = _context.typeProvider;
13363 }
13364
13365 /**
13366 * Builds Polymer specific HTML elements.
13367 */
13368 void build() {
13369 _unit.accept(this);
13370 // set Polymer tags
13371 HtmlElementImpl unitElement = _unit.element as HtmlElementImpl;
13372 unitElement.polymerTags = new List.from(_tagHtmlElements);
13373 }
13374
13375 @override
13376 Object visitXmlTagNode(ht.XmlTagNode node) {
13377 if (node.tag == "polymer-element") {
13378 _createTagHtmlElement(node);
13379 }
13380 // visit children
13381 return super.visitXmlTagNode(node);
13382 }
13383
13384 void _createAttributeElements() {
13385 // prepare "attributes" attribute
13386 ht.XmlAttributeNode attributesAttribute = _elementNode.getAttribute("attribu tes");
13387 if (attributesAttribute == null) {
13388 return;
13389 }
13390 // check if there is a Dart part to resolve against it
13391 if (_dartElement == null) {
13392 // TODO(scheglov) maybe report error (if it is allowed at all to have elem ent without Dart part)
13393 return;
13394 }
13395 // prepare value of the "attributes" attribute
13396 String attributesText = attributesAttribute.text;
13397 if (attributesText.trim().isEmpty) {
13398 _reportErrorForAttribute(attributesAttribute, PolymerCode.EMPTY_ATTRIBUTES , []);
13399 return;
13400 }
13401 // prepare attribute name tokens
13402 List<PolymerHtmlUnitBuilder_NameToken> nameTokens = [];
13403 {
13404 int index = 0;
13405 int textOffset = attributesAttribute.textOffset;
13406 int nameOffset = -1;
13407 JavaStringBuilder nameBuilder = new JavaStringBuilder();
13408 while (index < attributesText.length) {
13409 int c = attributesText.codeUnitAt(index++);
13410 if (Character.isWhitespace(c)) {
13411 if (nameOffset != -1) {
13412 nameTokens.add(new PolymerHtmlUnitBuilder_NameToken(nameOffset, name Builder.toString()));
13413 nameBuilder = new JavaStringBuilder();
13414 nameOffset = -1;
13415 }
13416 continue;
13417 }
13418 if (nameOffset == -1) {
13419 nameOffset = textOffset + index - 1;
13420 }
13421 nameBuilder.appendChar(c);
13422 }
13423 if (nameOffset != -1) {
13424 nameTokens.add(new PolymerHtmlUnitBuilder_NameToken(nameOffset, nameBuil der.toString()));
13425 nameBuilder = new JavaStringBuilder();
13426 }
13427 }
13428 // create attributes for name tokens
13429 List<PolymerAttributeElement> attributes = [];
13430 Set<String> definedNames = new Set();
13431 ClassElement classElement = _dartElement.classElement;
13432 for (PolymerHtmlUnitBuilder_NameToken nameToken in nameTokens) {
13433 int offset = nameToken._offset;
13434 // prepare name
13435 String name = nameToken._value;
13436 if (!isValidAttributeName(name)) {
13437 _reportErrorForNameToken(nameToken, PolymerCode.INVALID_ATTRIBUTE_NAME, [name]);
13438 continue;
13439 }
13440 if (!definedNames.add(name)) {
13441 _reportErrorForNameToken(nameToken, PolymerCode.DUPLICATE_ATTRIBUTE_DEFI NITION, [name]);
13442 continue;
13443 }
13444 // create attribute
13445 PolymerAttributeElementImpl attribute = new PolymerAttributeElementImpl(na me, offset);
13446 attributes.add(attribute);
13447 // resolve field
13448 FieldElement field = classElement.getField(name);
13449 if (field == null) {
13450 _reportErrorForNameToken(nameToken, PolymerCode.UNDEFINED_ATTRIBUTE_FIEL D, [name, classElement.displayName]);
13451 continue;
13452 }
13453 if (!_isPublishedField(field)) {
13454 _reportErrorForNameToken(nameToken, PolymerCode.ATTRIBUTE_FIELD_NOT_PUBL ISHED, [name, classElement.displayName]);
13455 }
13456 attribute.field = field;
13457 }
13458 _htmlElement.attributes = new List.from(attributes);
13459 }
13460
13461 void _createTagHtmlElement(ht.XmlTagNode node) {
13462 this._elementNode = node;
13463 this._elementName = null;
13464 this._htmlElement = null;
13465 this._dartElement = null;
13466 // prepare 'name' attribute
13467 ht.XmlAttributeNode nameAttribute = node.getAttribute("name");
13468 if (nameAttribute == null) {
13469 _reportErrorForToken(node.tagToken, PolymerCode.MISSING_TAG_NAME, []);
13470 return;
13471 }
13472 // prepare name
13473 _elementName = nameAttribute.text;
13474 if (!isValidTagName(_elementName)) {
13475 _reportErrorForAttributeValue(nameAttribute, PolymerCode.INVALID_TAG_NAME, [_elementName]);
13476 return;
13477 }
13478 // TODO(scheglov) Maybe check that at least one of "template" or "script" ch ildren.
13479 // TODO(scheglov) Maybe check if more than one top-level "template".
13480 // create HTML element
13481 int nameOffset = nameAttribute.textOffset;
13482 _htmlElement = new PolymerTagHtmlElementImpl(_elementName, nameOffset);
13483 // bind to the corresponding Dart element
13484 _dartElement = _findTagDartElement();
13485 if (_dartElement != null) {
13486 _htmlElement.dartElement = _dartElement;
13487 _dartElement.htmlElement = _htmlElement;
13488 }
13489 // TODO(scheglov) create attributes
13490 _createAttributeElements();
13491 // done
13492 _tagHtmlElements.add(_htmlElement);
13493 }
13494
13495 /**
13496 * Returns the [PolymerTagDartElement] that corresponds to the Polymer custom tag declared
13497 * by the given [XmlTagNode].
13498 */
13499 PolymerTagDartElementImpl _findTagDartElement() {
13500 LibraryElement dartLibraryElement = dartUnitElement;
13501 if (dartLibraryElement == null) {
13502 return null;
13503 }
13504 return _findTagDartElement_inLibrary(dartLibraryElement);
13505 }
13506
13507 /**
13508 * Returns the [PolymerTagDartElementImpl] declared in the given [LibraryEleme nt] with
13509 * the [elementName]. Maybe `null`.
13510 */
13511 PolymerTagDartElementImpl _findTagDartElement_inLibrary(LibraryElement library ) {
13512 try {
13513 library.accept(new RecursiveElementVisitor_PolymerHtmlUnitBuilder_findTagD artElement_inLibrary(this));
13514 } on PolymerHtmlUnitBuilder_FoundTagDartElementError catch (e) {
13515 return e._result;
13516 }
13517 return null;
13518 }
13519
13520 /**
13521 * Returns the only [LibraryElement] referenced by a direct `script` child. Ma ybe
13522 * `null` if none.
13523 */
13524 LibraryElement get dartUnitElement {
13525 // TODO(scheglov) Maybe check if more than one "script".
13526 for (ht.XmlTagNode child in _elementNode.tagNodes) {
13527 if (child is ht.HtmlScriptTagNode) {
13528 HtmlScriptElement scriptElement = child.scriptElement;
13529 if (scriptElement is ExternalHtmlScriptElement) {
13530 Source scriptSource = scriptElement.scriptSource;
13531 if (scriptSource != null) {
13532 return _context.getLibraryElement(scriptSource);
13533 }
13534 }
13535 }
13536 }
13537 return null;
13538 }
13539
13540 bool _isPublishedAnnotation(ElementAnnotation annotation) {
13541 Element element = annotation.element;
13542 if (element != null && element.name == "published") {
13543 return true;
13544 }
13545 return false;
13546 }
13547
13548 bool _isPublishedField(FieldElement field) {
13549 List<ElementAnnotation> annotations = field.metadata;
13550 for (ElementAnnotation annotation in annotations) {
13551 if (_isPublishedAnnotation(annotation)) {
13552 return true;
13553 }
13554 }
13555 return false;
13556 }
13557
13558 /**
13559 * Reports an error on the attribute's value, or (if absent) on the attribute' s name.
13560 */
13561 void _reportErrorForAttribute(ht.XmlAttributeNode node, ErrorCode errorCode, L ist<Object> arguments) {
13562 _reportErrorForOffset(node.offset, node.length, errorCode, arguments);
13563 }
13564
13565 /**
13566 * Reports an error on the attribute's value, or (if absent) on the attribute' s name.
13567 */
13568 void _reportErrorForAttributeValue(ht.XmlAttributeNode node, ErrorCode errorCo de, List<Object> arguments) {
13569 ht.Token valueToken = node.valueToken;
13570 if (valueToken == null || valueToken.isSynthetic) {
13571 _reportErrorForAttribute(node, errorCode, arguments);
13572 } else {
13573 _reportErrorForToken(valueToken, errorCode, arguments);
13574 }
13575 }
13576
13577 void _reportErrorForNameToken(PolymerHtmlUnitBuilder_NameToken token, ErrorCod e errorCode, List<Object> arguments) {
13578 int offset = token._offset;
13579 int length = token._value.length;
13580 _reportErrorForOffset(offset, length, errorCode, arguments);
13581 }
13582
13583 void _reportErrorForOffset(int offset, int length, ErrorCode errorCode, List<O bject> arguments) {
13584 _errorListener.onError(new AnalysisError.con2(_source, offset, length, error Code, arguments));
13585 }
13586
13587 void _reportErrorForToken(ht.Token token, ErrorCode errorCode, List<Object> ar guments) {
13588 int offset = token.offset;
13589 int length = token.length;
13590 _reportErrorForOffset(offset, length, errorCode, arguments);
13591 }
13592 }
13593
13594 class PolymerHtmlUnitBuilder_FoundTagDartElementError extends Error {
13595 final PolymerTagDartElementImpl _result;
13596
13597 PolymerHtmlUnitBuilder_FoundTagDartElementError(this._result);
13598 }
13599
13600 class PolymerHtmlUnitBuilder_NameToken {
13601 final int _offset;
13602
13603 final String _value;
13604
13605 PolymerHtmlUnitBuilder_NameToken(this._offset, this._value);
13606 }
13607
13608 /**
13609 * Instances of the class [PolymerHtmlUnitResolver] resolve Polymer specific
13610 * [XmlTagNode]s and expressions.
13611 *
13612 * TODO(scheglov) implement it
13613 */
13614 class PolymerHtmlUnitResolver extends ht.RecursiveXmlVisitor<Object> {
13615 final InternalAnalysisContext _context;
13616
13617 TypeProvider _typeProvider;
13618
13619 final AnalysisErrorListener _errorListener;
13620
13621 final Source _source;
13622
13623 final LineInfo _lineInfo;
13624
13625 final ht.HtmlUnit _unit;
13626
13627 PolymerHtmlUnitResolver(this._context, this._errorListener, this._source, this ._lineInfo, this._unit) {
13628 this._typeProvider = _context.typeProvider;
13629 }
13630
13631 /**
13632 * Resolves Polymer specific features.
13633 */
13634 void resolveUnit() {
13635 }
13636
13637 @override
13638 Object visitXmlAttributeNode(ht.XmlAttributeNode node) => super.visitXmlAttrib uteNode(node);
13639
13640 @override
13641 Object visitXmlTagNode(ht.XmlTagNode node) => super.visitXmlTagNode(node);
13642 }
13643
13644 /**
13645 * Instances of the class `PolymerResolveHtmlTask` performs Polymer specific HTM L file
13646 * resolution.
13647 *
13648 * TODO(scheglov) implement it
13649 */
13650 class PolymerResolveHtmlTask extends AnalysisTask {
13651 /**
13652 * The source to be resolved.
13653 */
13654 final Source source;
13655
13656 /**
13657 * The time at which the contents of the source were last modified.
13658 */
13659 final int modificationTime;
13660
13661 /**
13662 * The line information associated with the source.
13663 */
13664 final LineInfo _lineInfo;
13665
13666 /**
13667 * The HTML unit to be resolved.
13668 */
13669 final ht.HtmlUnit _unit;
13670
13671 /**
13672 * The resolution errors that were discovered while resolving the source.
13673 */
13674 List<AnalysisError> _errors = AnalysisError.NO_ERRORS;
13675
13676 /**
13677 * Initialize a newly created task to perform analysis within the given contex t.
13678 *
13679 * @param context the context in which the task is to be performed
13680 * @param source the source to be resolved
13681 * @param modificationTime the time at which the contents of the source were l ast modified
13682 * @param unit the HTML unit to be resolved
13683 */
13684 PolymerResolveHtmlTask(InternalAnalysisContext context, this.source, this.modi ficationTime, this._lineInfo, this._unit) : super(context);
13685
13686 @override
13687 accept(AnalysisTaskVisitor visitor) => visitor.visitPolymerResolveHtmlTask(thi s);
13688
13689 List<AnalysisError> get errors => _errors;
13690
13691 @override
13692 String get taskDescription => "resolve as Polymer ${source.fullName}";
13693
13694 @override
13695 void internalPerform() {
13696 RecordingErrorListener errorListener = new RecordingErrorListener();
13697 PolymerHtmlUnitResolver resolver = new PolymerHtmlUnitResolver(context, erro rListener, source, _lineInfo, _unit);
13698 resolver.resolveUnit();
13699 _errors = errorListener.getErrorsForSource(source);
13700 }
13701 }
13702
13703 /**
13704 * Instances of the class `RecordingErrorListener` implement an error listener t hat will
13705 * record the errors that are reported to it in a way that is appropriate for ca ching those errors
13706 * within an analysis context.
13707 */
13708 class RecordingErrorListener implements AnalysisErrorListener {
13709 /**
13710 * A HashMap of lists containing the errors that were collected, keyed by each [Source].
13711 */
13712 Map<Source, HashSet<AnalysisError>> _errors = new HashMap<Source, HashSet<Anal ysisError>>();
13713
13714 /**
13715 * Add all of the errors recorded by the given listener to this listener.
13716 *
13717 * @param listener the listener that has recorded the errors to be added
13718 */
13719 void addAll(RecordingErrorListener listener) {
13720 for (AnalysisError error in listener.errors) {
13721 onError(error);
13722 }
13723 }
13724
13725 /**
13726 * Answer the errors collected by the listener.
13727 *
13728 * @return an array of errors (not `null`, contains no `null`s)
13729 */
13730 List<AnalysisError> get errors {
13731 Iterable<MapEntry<Source, HashSet<AnalysisError>>> entrySet = getMapEntrySet (_errors);
13732 int numEntries = entrySet.length;
13733 if (numEntries == 0) {
13734 return AnalysisError.NO_ERRORS;
13735 }
13736 List<AnalysisError> resultList = new List<AnalysisError>();
13737 for (MapEntry<Source, HashSet<AnalysisError>> entry in entrySet) {
13738 resultList.addAll(entry.getValue());
13739 }
13740 return new List.from(resultList);
13741 }
13742
13743 /**
13744 * Answer the errors collected by the listener for some passed [Source].
13745 *
13746 * @param source some [Source] for which the caller wants the set of [Analysis Error]s
13747 * collected by this listener
13748 * @return the errors collected by the listener for the passed [Source]
13749 */
13750 List<AnalysisError> getErrorsForSource(Source source) {
13751 HashSet<AnalysisError> errorsForSource = _errors[source];
13752 if (errorsForSource == null) {
13753 return AnalysisError.NO_ERRORS;
13754 } else {
13755 return new List.from(errorsForSource);
13756 }
13757 }
13758
13759 @override
13760 void onError(AnalysisError error) {
13761 Source source = error.source;
13762 HashSet<AnalysisError> errorsForSource = _errors[source];
13763 if (_errors[source] == null) {
13764 errorsForSource = new HashSet<AnalysisError>();
13765 _errors[source] = errorsForSource;
13766 }
13767 errorsForSource.add(error);
13768 }
13769 }
13770
13771 class RecursiveElementVisitor_PolymerHtmlUnitBuilder_findTagDartElement_inLibrar y extends RecursiveElementVisitor<Object> {
13772 final PolymerHtmlUnitBuilder PolymerHtmlUnitBuilder_this;
13773
13774 RecursiveElementVisitor_PolymerHtmlUnitBuilder_findTagDartElement_inLibrary(th is.PolymerHtmlUnitBuilder_this) : super();
13775
13776 @override
13777 Object visitPolymerTagDartElement(PolymerTagDartElement element) {
13778 if (element.name == PolymerHtmlUnitBuilder_this._elementName) {
13779 throw new PolymerHtmlUnitBuilder_FoundTagDartElementError(element as Polym erTagDartElementImpl);
13780 }
13781 return null;
13782 }
13783 }
13784
13785 class RecursiveXmlVisitor_AngularHtmlUnitResolver_hasAngularAnnotation extends h t.RecursiveXmlVisitor<Object> {
13786 @override
13787 Object visitXmlTagNode(ht.XmlTagNode node) {
13788 if (node.getAttribute(AngularHtmlUnitResolver._NG_APP) != null) {
13789 throw new AngularHtmlUnitResolver_FoundAppError();
13790 }
13791 return super.visitXmlTagNode(node);
13792 }
13793 }
13794
13795 class RecursiveXmlVisitor_AngularHtmlUnitResolver_visitModelDirectives extends h t.RecursiveXmlVisitor<Object> {
13796 final AngularHtmlUnitResolver AngularHtmlUnitResolver_this;
13797
13798 RecursiveXmlVisitor_AngularHtmlUnitResolver_visitModelDirectives(this.AngularH tmlUnitResolver_this) : super();
13799
13800 @override
13801 Object visitXmlTagNode(ht.XmlTagNode node) {
13802 NgModelProcessor directive = NgModelProcessor.INSTANCE;
13803 if (directive.canApply(node)) {
13804 directive._applyTopDeclarations(AngularHtmlUnitResolver_this, node);
13805 }
13806 return super.visitXmlTagNode(node);
13807 }
13808 }
13809
13810 class RecursiveXmlVisitor_ParseHtmlTask_getLibrarySources extends ht.RecursiveXm lVisitor<Object> {
13811 final ParseHtmlTask ParseHtmlTask_this;
13812
13813 List<Source> libraries;
13814
13815 RecursiveXmlVisitor_ParseHtmlTask_getLibrarySources(this.ParseHtmlTask_this, t his.libraries) : super();
13816
13817 @override
13818 Object visitHtmlScriptTagNode(ht.HtmlScriptTagNode node) {
13819 ht.XmlAttributeNode scriptAttribute = null;
13820 for (ht.XmlAttributeNode attribute in node.attributes) {
13821 if (javaStringEqualsIgnoreCase(attribute.name, ParseHtmlTask._ATTRIBUTE_SR C)) {
13822 scriptAttribute = attribute;
13823 }
13824 }
13825 if (scriptAttribute != null) {
13826 try {
13827 Uri uri = new Uri(path: scriptAttribute.text);
13828 String fileName = uri.path;
13829 Source librarySource = ParseHtmlTask_this.context.sourceFactory.resolveU ri(ParseHtmlTask_this.source, fileName);
13830 if (ParseHtmlTask_this.context.exists(librarySource)) {
13831 libraries.add(librarySource);
13832 }
13833 } on URISyntaxException catch (e) {
13834 }
13835 }
13836 return super.visitHtmlScriptTagNode(node);
13837 }
13838 }
13839
13840 class RecursiveXmlVisitor_ParseHtmlTask_internalPerform extends ht.RecursiveXmlV isitor<Object> {
13841 final ParseHtmlTask ParseHtmlTask_this;
13842
13843 RecordingErrorListener errorListener;
13844
13845 RecursiveXmlVisitor_ParseHtmlTask_internalPerform(this.ParseHtmlTask_this, thi s.errorListener) : super();
13846
13847 @override
13848 Object visitHtmlScriptTagNode(ht.HtmlScriptTagNode node) {
13849 ParseHtmlTask_this._resolveScriptDirectives(node.script, errorListener);
13850 return null;
13851 }
13852 }
13853
13854 class RecursiveXmlVisitor_ResolveHtmlTask_internalPerform extends ht.RecursiveXm lVisitor<Object> {
13855 final ResolveHtmlTask ResolveHtmlTask_this;
13856
13857 RecordingErrorListener errorListener;
13858
13859 RecursiveXmlVisitor_ResolveHtmlTask_internalPerform(this.ResolveHtmlTask_this, this.errorListener) : super();
13860
13861 @override
13862 Object visitHtmlScriptTagNode(ht.HtmlScriptTagNode node) {
13863 CompilationUnit script = node.script;
13864 if (script != null) {
13865 GenerateDartErrorsTask.validateDirectives(ResolveHtmlTask_this.context, Re solveHtmlTask_this.source, script, errorListener);
13866 }
13867 return null;
13868 }
13869 }
13870
13871 /**
13872 * Instances of the class `ResolutionEraser` remove any resolution information f rom an AST
13873 * structure when used to visit that structure.
13874 */
13875 class ResolutionEraser extends GeneralizingAstVisitor<Object> {
13876 @override
13877 Object visitAssignmentExpression(AssignmentExpression node) {
13878 node.staticElement = null;
13879 node.propagatedElement = null;
13880 return super.visitAssignmentExpression(node);
13881 }
13882
13883 @override
13884 Object visitBinaryExpression(BinaryExpression node) {
13885 node.staticElement = null;
13886 node.propagatedElement = null;
13887 return super.visitBinaryExpression(node);
13888 }
13889
13890 @override
13891 Object visitCompilationUnit(CompilationUnit node) {
13892 node.element = null;
13893 return super.visitCompilationUnit(node);
13894 }
13895
13896 @override
13897 Object visitConstructorDeclaration(ConstructorDeclaration node) {
13898 node.element = null;
13899 return super.visitConstructorDeclaration(node);
13900 }
13901
13902 @override
13903 Object visitConstructorName(ConstructorName node) {
13904 node.staticElement = null;
13905 return super.visitConstructorName(node);
13906 }
13907
13908 @override
13909 Object visitDirective(Directive node) {
13910 node.element = null;
13911 return super.visitDirective(node);
13912 }
13913
13914 @override
13915 Object visitExpression(Expression node) {
13916 node.staticType = null;
13917 node.propagatedType = null;
13918 return super.visitExpression(node);
13919 }
13920
13921 @override
13922 Object visitFunctionExpression(FunctionExpression node) {
13923 node.element = null;
13924 return super.visitFunctionExpression(node);
13925 }
13926
13927 @override
13928 Object visitFunctionExpressionInvocation(FunctionExpressionInvocation node) {
13929 node.staticElement = null;
13930 node.propagatedElement = null;
13931 return super.visitFunctionExpressionInvocation(node);
13932 }
13933
13934 @override
13935 Object visitIndexExpression(IndexExpression node) {
13936 node.staticElement = null;
13937 node.propagatedElement = null;
13938 return super.visitIndexExpression(node);
13939 }
13940
13941 @override
13942 Object visitInstanceCreationExpression(InstanceCreationExpression node) {
13943 node.staticElement = null;
13944 return super.visitInstanceCreationExpression(node);
13945 }
13946
13947 @override
13948 Object visitPostfixExpression(PostfixExpression node) {
13949 node.staticElement = null;
13950 node.propagatedElement = null;
13951 return super.visitPostfixExpression(node);
13952 }
13953
13954 @override
13955 Object visitPrefixExpression(PrefixExpression node) {
13956 node.staticElement = null;
13957 node.propagatedElement = null;
13958 return super.visitPrefixExpression(node);
13959 }
13960
13961 @override
13962 Object visitRedirectingConstructorInvocation(RedirectingConstructorInvocation node) {
13963 node.staticElement = null;
13964 return super.visitRedirectingConstructorInvocation(node);
13965 }
13966
13967 @override
13968 Object visitSimpleIdentifier(SimpleIdentifier node) {
13969 node.staticElement = null;
13970 node.propagatedElement = null;
13971 return super.visitSimpleIdentifier(node);
13972 }
13973
13974 @override
13975 Object visitSuperConstructorInvocation(SuperConstructorInvocation node) {
13976 node.staticElement = null;
13977 return super.visitSuperConstructorInvocation(node);
13978 }
13979 }
13980
13981 /**
13982 * Instances of the class `ResolvableCompilationUnit` represent a compilation un it that is not
13983 * referenced by any other objects and for which we have modification stamp info rmation. It is used
13984 * by the [LibraryResolver] to resolve a library.
13985 */
13986 class ResolvableCompilationUnit extends TimestampedData<CompilationUnit> {
13987 /**
13988 * The source of the compilation unit.
13989 */
13990 final Source source;
13991
13992 /**
13993 * Initialize a newly created holder to hold the given values.
13994 *
13995 * @param modificationTime the modification time of the source from which the AST was created
13996 * @param unit the AST that was created from the source
13997 */
13998 ResolvableCompilationUnit.con1(int modificationTime, CompilationUnit unit) : t his.con2(modificationTime, unit, null);
13999
14000 /**
14001 * Initialize a newly created holder to hold the given values.
14002 *
14003 * @param modificationTime the modification time of the source from which the AST was created
14004 * @param unit the AST that was created from the source
14005 * @param source the source of the compilation unit
14006 */
14007 ResolvableCompilationUnit.con2(int modificationTime, CompilationUnit unit, thi s.source) : super(modificationTime, unit);
14008
14009 /**
14010 * Return the AST that was created from the source.
14011 *
14012 * @return the AST that was created from the source
14013 */
14014 CompilationUnit get compilationUnit => data;
14015 }
14016
14017 /**
14018 * Instances of the class `ResolvableHtmlUnit` represent an HTML unit that is no t referenced
14019 * by any other objects and for which we have modification stamp information. It is used by the
14020 * [ResolveHtmlTask] to resolve an HTML source.
14021 */
14022 class ResolvableHtmlUnit extends TimestampedData<ht.HtmlUnit> {
14023 /**
14024 * Initialize a newly created holder to hold the given values.
14025 *
14026 * @param modificationTime the modification time of the source from which the AST was created
14027 * @param unit the AST that was created from the source
14028 */
14029 ResolvableHtmlUnit(int modificationTime, ht.HtmlUnit unit) : super(modificatio nTime, unit);
14030
14031 /**
14032 * Return the AST that was created from the source.
14033 *
14034 * @return the AST that was created from the source
14035 */
14036 ht.HtmlUnit get compilationUnit => data;
14037 }
14038
14039 /**
14040 * Instances of the class `ResolveAngularComponentTemplateTask` resolve HTML tem plate
14041 * referenced by [AngularComponentElement].
14042 */
14043 class ResolveAngularComponentTemplateTask extends AnalysisTask {
14044 /**
14045 * The source to be resolved.
14046 */
14047 final Source source;
14048
14049 /**
14050 * The time at which the contents of the source were last modified.
14051 */
14052 final int modificationTime;
14053
14054 /**
14055 * The HTML unit to be resolved.
14056 */
14057 final ht.HtmlUnit _unit;
14058
14059 /**
14060 * The [AngularComponentElement] to resolve template for.
14061 */
14062 final AngularComponentElement _component;
14063
14064 /**
14065 * The Angular application to resolve in context of.
14066 */
14067 final AngularApplication _application;
14068
14069 /**
14070 * The [HtmlUnit] that was resolved by this task.
14071 */
14072 ht.HtmlUnit _resolvedUnit;
14073
14074 /**
14075 * The resolution errors that were discovered while resolving the source.
14076 */
14077 List<AnalysisError> _resolutionErrors = AnalysisError.NO_ERRORS;
14078
14079 /**
14080 * Initialize a newly created task to perform analysis within the given contex t.
14081 *
14082 * @param context the context in which the task is to be performed
14083 * @param source the source to be resolved
14084 * @param modificationTime the time at which the contents of the source were l ast modified
14085 * @param unit the HTML unit to be resolved
14086 * @param component the component that uses this HTML template, not `null`
14087 * @param application the Angular application to resolve in context of
14088 */
14089 ResolveAngularComponentTemplateTask(InternalAnalysisContext context, this.sour ce, this.modificationTime, this._unit, this._component, this._application) : sup er(context);
14090
14091 @override
14092 accept(AnalysisTaskVisitor visitor) => visitor.visitResolveAngularComponentTem plateTask(this);
14093
14094 List<AnalysisError> get resolutionErrors => _resolutionErrors;
14095
14096 /**
14097 * Return the [HtmlUnit] that was resolved by this task.
14098 *
14099 * @return the [HtmlUnit] that was resolved by this task
14100 */
14101 ht.HtmlUnit get resolvedUnit => _resolvedUnit;
14102
14103 @override
14104 String get taskDescription => "resolve as Angular template ${source}";
14105
14106 @override
14107 void internalPerform() {
14108 //
14109 // Prepare for resolution.
14110 //
14111 RecordingErrorListener errorListener = new RecordingErrorListener();
14112 LineInfo lineInfo = context.getLineInfo(source);
14113 //
14114 // Perform resolution.
14115 //
14116 if (_application != null) {
14117 AngularHtmlUnitResolver resolver = new AngularHtmlUnitResolver(context, er rorListener, source, lineInfo, _unit);
14118 resolver.resolveComponentTemplate(_application, _component);
14119 _resolvedUnit = _unit;
14120 }
14121 //
14122 // Remember the errors.
14123 //
14124 _resolutionErrors = errorListener.getErrorsForSource(source);
14125 }
14126 }
14127
14128 /**
14129 * Instances of the class `ResolveAngularEntryHtmlTask` resolve a specific HTML file as an
14130 * Angular entry point.
14131 */
14132 class ResolveAngularEntryHtmlTask extends AnalysisTask {
14133 /**
14134 * The source to be resolved.
14135 */
14136 final Source source;
14137
14138 /**
14139 * The time at which the contents of the source were last modified.
14140 */
14141 final int modificationTime;
14142
14143 /**
14144 * The HTML unit to be resolved.
14145 */
14146 final ht.HtmlUnit _unit;
14147
14148 /**
14149 * The listener to record errors.
14150 */
14151 RecordingErrorListener _errorListener = new RecordingErrorListener();
14152
14153 /**
14154 * The [HtmlUnit] that was resolved by this task.
14155 */
14156 ht.HtmlUnit _resolvedUnit;
14157
14158 /**
14159 * The element produced by resolving the source.
14160 */
14161 HtmlElement _element = null;
14162
14163 /**
14164 * The Angular application to resolve in context of.
14165 */
14166 AngularApplication _application;
14167
14168 /**
14169 * Initialize a newly created task to perform analysis within the given contex t.
14170 *
14171 * @param context the context in which the task is to be performed
14172 * @param source the source to be resolved
14173 * @param modificationTime the time at which the contents of the source were l ast modified
14174 * @param unit the HTML unit to be resolved
14175 */
14176 ResolveAngularEntryHtmlTask(InternalAnalysisContext context, this.source, this .modificationTime, this._unit) : super(context);
14177
14178 @override
14179 accept(AnalysisTaskVisitor visitor) => visitor.visitResolveAngularEntryHtmlTas k(this);
14180
14181 /**
14182 * Returns the [AngularApplication] for the Web application with this Angular entry point,
14183 * maybe `null` if not an Angular entry point.
14184 */
14185 AngularApplication get application => _application;
14186
14187 HtmlElement get element => _element;
14188
14189 /**
14190 * The resolution errors that were discovered while resolving the source.
14191 */
14192 List<AnalysisError> get entryErrors => _errorListener.getErrorsForSource(sourc e);
14193
14194 /**
14195 * Returns [AnalysisError]s recorded for the given [Source].
14196 */
14197 List<AnalysisError> getErrors(Source source) => _errorListener.getErrorsForSou rce(source);
14198
14199 /**
14200 * Return the [HtmlUnit] that was resolved by this task.
14201 *
14202 * @return the [HtmlUnit] that was resolved by this task
14203 */
14204 ht.HtmlUnit get resolvedUnit => _resolvedUnit;
14205
14206 @override
14207 String get taskDescription {
14208 if (source == null) {
14209 return "resolve as Angular entry point null source";
14210 }
14211 return "resolve as Angular entry point ${source.fullName}";
14212 }
14213
14214 @override
14215 void internalPerform() {
14216 //
14217 // Prepare for resolution.
14218 //
14219 LineInfo lineInfo = context.getLineInfo(source);
14220 //
14221 // Try to resolve as an Angular entry point.
14222 //
14223 _application = new AngularHtmlUnitResolver(context, _errorListener, source, lineInfo, _unit).calculateAngularApplication();
14224 //
14225 // Perform resolution.
14226 //
14227 if (_application != null) {
14228 new AngularHtmlUnitResolver(context, _errorListener, source, lineInfo, _un it).resolveEntryPoint(_application);
14229 }
14230 //
14231 // Remember the resolved unit.
14232 //
14233 _resolvedUnit = _unit;
14234 }
14235 }
14236
14237 /**
14238 * Instances of the class `ResolveDartLibraryTask` resolve a specific Dart libra ry.
14239 */
14240 class ResolveDartLibraryCycleTask extends AnalysisTask {
14241 /**
14242 * The source representing the file whose compilation unit is to be returned. TODO(brianwilkerson)
14243 * This should probably be removed, but is being left in for now to ease the t ransition.
14244 */
14245 final Source unitSource;
14246
14247 /**
14248 * The source representing the library to be resolved.
14249 */
14250 final Source librarySource;
14251
14252 /**
14253 * The libraries that are part of the cycle containing the library to be resol ved.
14254 */
14255 final List<ResolvableLibrary> _librariesInCycle;
14256
14257 /**
14258 * The library resolver holding information about the libraries that were reso lved.
14259 */
14260 LibraryResolver2 _resolver;
14261
14262 /**
14263 * Initialize a newly created task to perform analysis within the given contex t.
14264 *
14265 * @param context the context in which the task is to be performed
14266 * @param unitSource the source representing the file whose compilation unit i s to be returned
14267 * @param librarySource the source representing the library to be resolved
14268 * @param librariesInCycle the libraries that are part of the cycle containing the library to be
14269 * resolved
14270 */
14271 ResolveDartLibraryCycleTask(InternalAnalysisContext context, this.unitSource, this.librarySource, this._librariesInCycle) : super(context);
14272
14273 @override
14274 accept(AnalysisTaskVisitor visitor) => visitor.visitResolveDartLibraryCycleTas k(this);
14275
14276 /**
14277 * Return the library resolver holding information about the libraries that we re resolved.
14278 *
14279 * @return the library resolver holding information about the libraries that w ere resolved
14280 */
14281 LibraryResolver2 get libraryResolver => _resolver;
14282
14283 @override
14284 String get taskDescription {
14285 if (librarySource == null) {
14286 return "resolve library null source";
14287 }
14288 return "resolve library ${librarySource.fullName}";
14289 }
14290
14291 @override
14292 void internalPerform() {
14293 _resolver = new LibraryResolver2(context);
14294 _resolver.resolveLibrary(librarySource, _librariesInCycle);
14295 }
14296 }
14297
14298 /**
14299 * Instances of the class `ResolveDartLibraryTask` resolve a specific Dart libra ry.
14300 */
14301 class ResolveDartLibraryTask extends AnalysisTask {
14302 /**
14303 * The source representing the file whose compilation unit is to be returned.
14304 */
14305 final Source unitSource;
14306
14307 /**
14308 * The source representing the library to be resolved.
14309 */
14310 final Source librarySource;
14311
14312 /**
14313 * The library resolver holding information about the libraries that were reso lved.
14314 */
14315 LibraryResolver _resolver;
14316
14317 /**
14318 * Initialize a newly created task to perform analysis within the given contex t.
14319 *
14320 * @param context the context in which the task is to be performed
14321 * @param unitSource the source representing the file whose compilation unit i s to be returned
14322 * @param librarySource the source representing the library to be resolved
14323 */
14324 ResolveDartLibraryTask(InternalAnalysisContext context, this.unitSource, this. librarySource) : super(context);
14325
14326 @override
14327 accept(AnalysisTaskVisitor visitor) => visitor.visitResolveDartLibraryTask(thi s);
14328
14329 /**
14330 * Return the library resolver holding information about the libraries that we re resolved.
14331 *
14332 * @return the library resolver holding information about the libraries that w ere resolved
14333 */
14334 LibraryResolver get libraryResolver => _resolver;
14335
14336 @override
14337 String get taskDescription {
14338 if (librarySource == null) {
14339 return "resolve library null source";
14340 }
14341 return "resolve library ${librarySource.fullName}";
14342 }
14343
14344 @override
14345 void internalPerform() {
14346 _resolver = new LibraryResolver(context);
14347 _resolver.resolveLibrary(librarySource, true);
14348 }
14349 }
14350
14351 /**
14352 * Instances of the class `ResolveDartUnitTask` resolve a single Dart file based on a existing
14353 * element model.
14354 */
14355 class ResolveDartUnitTask extends AnalysisTask {
14356 /**
14357 * The source that is to be resolved.
14358 */
14359 final Source source;
14360
14361 /**
14362 * The element model for the library containing the source.
14363 */
14364 final LibraryElement _libraryElement;
14365
14366 /**
14367 * The time at which the contents of the source were last modified.
14368 */
14369 int _modificationTime = -1;
14370
14371 /**
14372 * The compilation unit that was resolved by this task.
14373 */
14374 CompilationUnit _resolvedUnit;
14375
14376 /**
14377 * Initialize a newly created task to perform analysis within the given contex t.
14378 *
14379 * @param context the context in which the task is to be performed
14380 * @param source the source to be parsed
14381 * @param libraryElement the element model for the library containing the sour ce
14382 */
14383 ResolveDartUnitTask(InternalAnalysisContext context, this.source, this._librar yElement) : super(context);
14384
14385 @override
14386 accept(AnalysisTaskVisitor visitor) => visitor.visitResolveDartUnitTask(this);
14387
14388 /**
14389 * Return the source for the library containing the source that is to be resol ved.
14390 *
14391 * @return the source for the library containing the source that is to be reso lved
14392 */
14393 Source get librarySource => _libraryElement.source;
14394
14395 /**
14396 * Return the time at which the contents of the source that was parsed were la st modified, or a
14397 * negative value if the task has not yet been performed or if an exception oc curred.
14398 *
14399 * @return the time at which the contents of the source that was parsed were l ast modified
14400 */
14401 int get modificationTime => _modificationTime;
14402
14403 /**
14404 * Return the compilation unit that was resolved by this task.
14405 *
14406 * @return the compilation unit that was resolved by this task
14407 */
14408 CompilationUnit get resolvedUnit => _resolvedUnit;
14409
14410 @override
14411 String get taskDescription {
14412 Source librarySource = _libraryElement.source;
14413 if (librarySource == null) {
14414 return "resolve unit null source";
14415 }
14416 return "resolve unit ${librarySource.fullName}";
14417 }
14418
14419 @override
14420 void internalPerform() {
14421 TypeProvider typeProvider = (_libraryElement.context as InternalAnalysisCont ext).typeProvider;
14422 ResolvableCompilationUnit resolvableUnit = context.computeResolvableCompilat ionUnit(source);
14423 _modificationTime = resolvableUnit.modificationTime;
14424 CompilationUnit unit = resolvableUnit.compilationUnit;
14425 if (unit == null) {
14426 throw new AnalysisException("Internal error: computeResolvableCompilationU nit returned a value without a parsed Dart unit");
14427 }
14428 //
14429 // Resolve names in declarations.
14430 //
14431 new DeclarationResolver().resolve(unit, _find(_libraryElement, source));
14432 //
14433 // Resolve the type names.
14434 //
14435 RecordingErrorListener errorListener = new RecordingErrorListener();
14436 TypeResolverVisitor typeResolverVisitor = new TypeResolverVisitor.con2(_libr aryElement, source, typeProvider, errorListener);
14437 unit.accept(typeResolverVisitor);
14438 //
14439 // Resolve the rest of the structure
14440 //
14441 InheritanceManager inheritanceManager = new InheritanceManager(_libraryEleme nt);
14442 ResolverVisitor resolverVisitor = new ResolverVisitor.con2(_libraryElement, source, typeProvider, inheritanceManager, errorListener);
14443 unit.accept(resolverVisitor);
14444 //
14445 // Perform additional error checking.
14446 //
14447 TimeCounter_TimeCounterHandle counterHandleErrors = PerformanceStatistics.er rors.start();
14448 try {
14449 ErrorReporter errorReporter = new ErrorReporter(errorListener, source);
14450 ErrorVerifier errorVerifier = new ErrorVerifier(errorReporter, _libraryEle ment, typeProvider, inheritanceManager);
14451 unit.accept(errorVerifier);
14452 ConstantVerifier constantVerifier = new ConstantVerifier(errorReporter, _l ibraryElement, typeProvider);
14453 unit.accept(constantVerifier);
14454 } finally {
14455 counterHandleErrors.stop();
14456 }
14457 //
14458 // Capture the results.
14459 //
14460 _resolvedUnit = unit;
14461 }
14462
14463 /**
14464 * Search the compilation units that are part of the given library and return the element
14465 * representing the compilation unit with the given source. Return `null` if t here is no
14466 * such compilation unit.
14467 *
14468 * @param libraryElement the element representing the library being searched t hrough
14469 * @param unitSource the source for the compilation unit whose element is to b e returned
14470 * @return the element representing the compilation unit
14471 */
14472 CompilationUnitElement _find(LibraryElement libraryElement, Source unitSource) {
14473 CompilationUnitElement element = libraryElement.definingCompilationUnit;
14474 if (element.source == unitSource) {
14475 return element;
14476 }
14477 for (CompilationUnitElement partElement in libraryElement.parts) {
14478 if (partElement.source == unitSource) {
14479 return partElement;
14480 }
14481 }
14482 return null;
14483 }
14484 }
14485
14486 /**
14487 * Instances of the class `ResolveHtmlTask` resolve a specific source as an HTML file.
14488 */
14489 class ResolveHtmlTask extends AnalysisTask {
14490 /**
14491 * The source to be resolved.
14492 */
14493 final Source source;
14494
14495 /**
14496 * The time at which the contents of the source were last modified.
14497 */
14498 final int modificationTime;
14499
14500 /**
14501 * The HTML unit to be resolved.
14502 */
14503 final ht.HtmlUnit _unit;
14504
14505 /**
14506 * The [HtmlUnit] that was resolved by this task.
14507 */
14508 ht.HtmlUnit _resolvedUnit;
14509
14510 /**
14511 * The element produced by resolving the source.
14512 */
14513 HtmlElement _element = null;
14514
14515 /**
14516 * The resolution errors that were discovered while resolving the source.
14517 */
14518 List<AnalysisError> _resolutionErrors = AnalysisError.NO_ERRORS;
14519
14520 /**
14521 * Initialize a newly created task to perform analysis within the given contex t.
14522 *
14523 * @param context the context in which the task is to be performed
14524 * @param source the source to be resolved
14525 * @param modificationTime the time at which the contents of the source were l ast modified
14526 * @param unit the HTML unit to be resolved
14527 */
14528 ResolveHtmlTask(InternalAnalysisContext context, this.source, this.modificatio nTime, this._unit) : super(context);
14529
14530 @override
14531 accept(AnalysisTaskVisitor visitor) => visitor.visitResolveHtmlTask(this);
14532
14533 HtmlElement get element => _element;
14534
14535 List<AnalysisError> get resolutionErrors => _resolutionErrors;
14536
14537 /**
14538 * Return the [HtmlUnit] that was resolved by this task.
14539 *
14540 * @return the [HtmlUnit] that was resolved by this task
14541 */
14542 ht.HtmlUnit get resolvedUnit => _resolvedUnit;
14543
14544 @override
14545 String get taskDescription {
14546 if (source == null) {
14547 return "resolve as html null source";
14548 }
14549 return "resolve as html ${source.fullName}";
14550 }
14551
14552 @override
14553 void internalPerform() {
14554 //
14555 // Build the standard HTML element.
14556 //
14557 HtmlUnitBuilder builder = new HtmlUnitBuilder(context);
14558 _element = builder.buildHtmlElement(source, modificationTime, _unit);
14559 RecordingErrorListener errorListener = builder.errorListener;
14560 //
14561 // Validate the directives
14562 //
14563 _unit.accept(new RecursiveXmlVisitor_ResolveHtmlTask_internalPerform(this, e rrorListener));
14564 //
14565 // Record all resolution errors.
14566 //
14567 _resolutionErrors = errorListener.getErrorsForSource(source);
14568 //
14569 // Remember the resolved unit.
14570 //
14571 _resolvedUnit = _unit;
14572 }
14573 }
14574
14575 /**
14576 * The enumerated type `RetentionPriority` represents the priority of data in th e cache in
14577 * terms of the desirability of retaining some specified data about a specified source.
14578 */
14579 class RetentionPriority extends Enum<RetentionPriority> {
14580 /**
14581 * A priority indicating that a given piece of data can be removed from the ca che without
14582 * reservation.
14583 */
14584 static const RetentionPriority LOW = const RetentionPriority('LOW', 0);
14585
14586 /**
14587 * A priority indicating that a given piece of data should not be removed from the cache unless
14588 * there are no sources for which the corresponding data has a lower priority. Currently used for
14589 * data that is needed in order to finish some outstanding analysis task.
14590 */
14591 static const RetentionPriority MEDIUM = const RetentionPriority('MEDIUM', 1);
14592
14593 /**
14594 * A priority indicating that a given piece of data should not be removed from the cache.
14595 * Currently used for data related to a priority source.
14596 */
14597 static const RetentionPriority HIGH = const RetentionPriority('HIGH', 2);
14598
14599 static const List<RetentionPriority> values = const [LOW, MEDIUM, HIGH];
14600
14601 const RetentionPriority(String name, int ordinal) : super(name, ordinal);
14602 }
14603
14604 /**
14605 * Instances of the class `ScanDartTask` scan a specific source as a Dart file.
14606 */
14607 class ScanDartTask extends AnalysisTask {
14608 /**
14609 * The source to be scanned.
14610 */
14611 final Source source;
14612
14613 /**
14614 * The time at which the contents of the source were last modified.
14615 */
14616 final int modificationTime;
14617
14618 /**
14619 * The contents of the source.
14620 */
14621 final String _content;
14622
14623 /**
14624 * The token stream that was produced by scanning the source.
14625 */
14626 Token _tokenStream;
14627
14628 /**
14629 * The line information that was produced.
14630 */
14631 LineInfo _lineInfo;
14632
14633 /**
14634 * The errors that were produced by scanning the source.
14635 */
14636 List<AnalysisError> _errors = AnalysisError.NO_ERRORS;
14637
14638 /**
14639 * Initialize a newly created task to perform analysis within the given contex t.
14640 *
14641 * @param context the context in which the task is to be performed
14642 * @param source the source to be parsed
14643 * @param modificationTime the time at which the contents of the source were l ast modified
14644 * @param content the contents of the source
14645 */
14646 ScanDartTask(InternalAnalysisContext context, this.source, this.modificationTi me, this._content) : super(context);
14647
14648 @override
14649 accept(AnalysisTaskVisitor visitor) => visitor.visitScanDartTask(this);
14650
14651 /**
14652 * Return the errors that were produced by scanning the source, or `null` if t he task has
14653 * not yet been performed or if an exception occurred.
14654 *
14655 * @return the errors that were produced by scanning the source
14656 */
14657 List<AnalysisError> get errors => _errors;
14658
14659 /**
14660 * Return the line information that was produced, or `null` if the task has no t yet been
14661 * performed or if an exception occurred.
14662 *
14663 * @return the line information that was produced
14664 */
14665 LineInfo get lineInfo => _lineInfo;
14666
14667 /**
14668 * Return the token stream that was produced by scanning the source, or `null` if the task
14669 * has not yet been performed or if an exception occurred.
14670 *
14671 * @return the token stream that was produced by scanning the source
14672 */
14673 Token get tokenStream => _tokenStream;
14674
14675 @override
14676 String get taskDescription {
14677 if (source == null) {
14678 return "scan as dart null source";
14679 }
14680 return "scan as dart ${source.fullName}";
14681 }
14682
14683 @override
14684 void internalPerform() {
14685 RecordingErrorListener errorListener = new RecordingErrorListener();
14686 TimeCounter_TimeCounterHandle timeCounterScan = PerformanceStatistics.scan.s tart();
14687 try {
14688 Scanner scanner = new Scanner(source, new CharSequenceReader(_content), er rorListener);
14689 scanner.preserveComments = context.analysisOptions.preserveComments;
14690 _tokenStream = scanner.tokenize();
14691 _lineInfo = new LineInfo(scanner.lineStarts);
14692 _errors = errorListener.getErrorsForSource(source);
14693 } catch (exception, stackTrace) {
14694 throw new AnalysisException("Exception", new CaughtException(exception, st ackTrace));
14695 } finally {
14696 timeCounterScan.stop();
14697 }
14698 }
14699 }
14700
14701 /**
14702 * Instances of the class `SdkAnalysisContext` implement an [AnalysisContext] th at only
14703 * contains sources for a Dart SDK.
14704 */
14705 class SdkAnalysisContext extends AnalysisContextImpl {
14706 @override
14707 AnalysisCache createCacheFromSourceFactory(SourceFactory factory) {
14708 if (factory == null) {
14709 return super.createCacheFromSourceFactory(factory);
14710 }
14711 DartSdk sdk = factory.dartSdk;
14712 if (sdk == null) {
14713 throw new IllegalArgumentException("The source factory for an SDK analysis context must have a DartUriResolver");
14714 }
14715 return new AnalysisCache(<CachePartition> [AnalysisEngine.instance.partition Manager.forSdk(sdk)]);
14716 }
14717 }
14718
14719 /**
14720 * Instances of the class `SdkCachePartition` implement a cache partition that c ontains all of
14721 * the sources in the SDK.
14722 */
14723 class SdkCachePartition extends CachePartition {
14724 /**
14725 * Initialize a newly created partition.
14726 *
14727 * @param maxCacheSize the maximum number of sources for which AST structures should be kept in
14728 * the cache
14729 */
14730 SdkCachePartition(int maxCacheSize) : super(maxCacheSize, DefaultRetentionPoli cy.POLICY);
14731
14732 @override
14733 bool contains(Source source) => source.isInSystemLibrary;
14734 }
14735
14736 /**
14737 * The interface `SourceEntry` defines the behavior of objects that maintain the information
14738 * cached by an analysis context about an individual source, no matter what kind of source it is.
14739 *
14740 * Source entries should be treated as if they were immutable unless a writable copy of the entry
14741 * has been obtained and has not yet been made visible to other threads.
14742 */
14743 abstract class SourceEntry {
14744 /**
14745 * The data descriptor representing the contents of the source.
14746 */
14747 static final DataDescriptor<String> CONTENT = new DataDescriptor<String>("Dart Entry.CONTENT");
14748
14749 /**
14750 * The data descriptor representing the line information.
14751 */
14752 static final DataDescriptor<LineInfo> LINE_INFO = new DataDescriptor<LineInfo> ("SourceEntry.LINE_INFO");
14753
14754 /**
14755 * Return the exception that caused one or more values to have a state of [Cac heState#ERROR]
14756 * .
14757 *
14758 * @return the exception that caused one or more values to be uncomputable
14759 */
14760 CaughtException get exception;
14761
14762 /**
14763 * Return `true` if the source was explicitly added to the context or `false` if the
14764 * source was implicitly added because it was referenced by another source.
14765 *
14766 * @return `true` if the source was explicitly added to the context
14767 */
14768 bool get explicitlyAdded;
14769
14770 /**
14771 * Return the kind of the source, or `null` if the kind is not currently cache d.
14772 *
14773 * @return the kind of the source
14774 */
14775 SourceKind get kind;
14776
14777 /**
14778 * Return the most recent time at which the state of the source matched the st ate represented by
14779 * this entry.
14780 *
14781 * @return the modification time of this entry
14782 */
14783 int get modificationTime;
14784
14785 /**
14786 * Return the state of the data represented by the given descriptor.
14787 *
14788 * @param descriptor the descriptor representing the data whose state is to be returned
14789 * @return the state of the data represented by the given descriptor
14790 */
14791 CacheState getState(DataDescriptor descriptor);
14792
14793 /**
14794 * Return the value of the data represented by the given descriptor, or `null` if the data
14795 * represented by the descriptor is not in the cache.
14796 *
14797 * @param descriptor the descriptor representing which data is to be returned
14798 * @return the value of the data represented by the given descriptor
14799 */
14800 Object getValue(DataDescriptor descriptor);
14801
14802 /**
14803 * Return a new entry that is initialized to the same state as this entry but that can be
14804 * modified.
14805 *
14806 * @return a writable copy of this entry
14807 */
14808 SourceEntryImpl get writableCopy;
14809 }
14810
14811 /**
14812 * Instances of the abstract class `SourceEntryImpl` implement the behavior comm on to all
14813 * [SourceEntry].
14814 */
14815 abstract class SourceEntryImpl implements SourceEntry {
14816 /**
14817 * The most recent time at which the state of the source matched the state rep resented by this
14818 * entry.
14819 */
14820 int _modificationTime = 0;
14821
14822 /**
14823 * A bit-encoding of boolean flags associated with this element.
14824 */
14825 int _flags = 0;
14826
14827 /**
14828 * The exception that caused one or more values to have a state of [CacheState #ERROR].
14829 */
14830 CaughtException _exception;
14831
14832 /**
14833 * The state of the cached content.
14834 */
14835 CacheState _contentState = CacheState.INVALID;
14836
14837 /**
14838 * The content of the source, or `null` if the content is not currently cached .
14839 */
14840 String _content;
14841
14842 /**
14843 * The state of the cached line information.
14844 */
14845 CacheState _lineInfoState = CacheState.INVALID;
14846
14847 /**
14848 * The line information computed for the source, or `null` if the line informa tion is not
14849 * currently cached.
14850 */
14851 LineInfo _lineInfo;
14852
14853 /**
14854 * The index of the flag indicating whether the source was explicitly added to the context or
14855 * whether the source was implicitly added because it was referenced by anothe r source.
14856 */
14857 static int _EXPLICITLY_ADDED_FLAG = 0;
14858
14859 /**
14860 * Fix the state of the [exception] to match the current state of the entry.
14861 */
14862 void fixExceptionState() {
14863 if (hasErrorState) {
14864 if (_exception == null) {
14865 //
14866 // This code should never be reached, but is a fail-safe in case an exce ption is not
14867 // recorded when it should be.
14868 //
14869 _exception = new CaughtException(new AnalysisException("State set to ERR OR without setting an exception"), null);
14870 }
14871 } else {
14872 _exception = null;
14873 }
14874 }
14875
14876 /**
14877 * Return a textual representation of the difference between the old entry and this entry. The
14878 * difference is represented as a sequence of fields whose value would change if the old entry
14879 * were converted into the new entry.
14880 *
14881 * @param oldEntry the entry being diff'd with this entry
14882 * @return a textual representation of the difference
14883 */
14884 String getDiff(SourceEntry oldEntry) {
14885 JavaStringBuilder builder = new JavaStringBuilder();
14886 writeDiffOn(builder, oldEntry);
14887 return builder.toString();
14888 }
14889
14890 /**
14891 * Return the exception that caused one or more values to have a state of [Cac heState#ERROR]
14892 * .
14893 *
14894 * @return the exception that caused one or more values to be uncomputable
14895 */
14896 @override
14897 CaughtException get exception => _exception;
14898
14899 /**
14900 * Return `true` if the source was explicitly added to the context or `false` if the
14901 * source was implicitly added because it was referenced by another source.
14902 *
14903 * @return `true` if the source was explicitly added to the context
14904 */
14905 @override
14906 bool get explicitlyAdded => getFlag(_EXPLICITLY_ADDED_FLAG);
14907
14908 @override
14909 int get modificationTime => _modificationTime;
14910
14911 @override
14912 CacheState getState(DataDescriptor descriptor) {
14913 if (identical(descriptor, SourceEntry.CONTENT)) {
14914 return _contentState;
14915 } else if (identical(descriptor, SourceEntry.LINE_INFO)) {
14916 return _lineInfoState;
14917 } else {
14918 throw new IllegalArgumentException("Invalid descriptor: ${descriptor}");
14919 }
14920 }
14921
14922 @override
14923 Object getValue(DataDescriptor descriptor) {
14924 if (identical(descriptor, SourceEntry.CONTENT)) {
14925 return _content;
14926 } else if (identical(descriptor, SourceEntry.LINE_INFO)) {
14927 return _lineInfo;
14928 } else {
14929 throw new IllegalArgumentException("Invalid descriptor: ${descriptor}");
14930 }
14931 }
14932
14933 /**
14934 * Invalidate all of the information associated with this source.
14935 */
14936 void invalidateAllInformation() {
14937 _content = null;
14938 _contentState = _checkContentState(CacheState.INVALID);
14939 _lineInfo = null;
14940 _lineInfoState = CacheState.INVALID;
14941 }
14942
14943 /**
14944 * Record that an error occurred while attempting to get the contents of the s ource represented by
14945 * this entry. This will set the state of all information, including any resol ution-based
14946 * information, as being in error.
14947 *
14948 * @param exception the exception that shows where the error occurred
14949 */
14950 void recordContentError(CaughtException exception) {
14951 _content = null;
14952 _contentState = CacheState.ERROR;
14953 recordScanError(exception);
14954 }
14955
14956 /**
14957 * Record that an error occurred while attempting to scan or parse the entry r epresented by this
14958 * entry. This will set the state of all information, including any resolution -based information,
14959 * as being in error.
14960 *
14961 * @param exception the exception that shows where the error occurred
14962 */
14963 void recordScanError(CaughtException exception) {
14964 this.exception = exception;
14965 _lineInfo = null;
14966 _lineInfoState = CacheState.ERROR;
14967 }
14968
14969 /**
14970 * Set whether the source was explicitly added to the context to match the giv en value.
14971 *
14972 * @param explicitlyAdded `true` if the source was explicitly added to the con text
14973 */
14974 void set explicitlyAdded(bool explicitlyAdded) {
14975 setFlag(_EXPLICITLY_ADDED_FLAG, explicitlyAdded);
14976 }
14977
14978 /**
14979 * Set the most recent time at which the state of the source matched the state represented by this
14980 * entry to the given time.
14981 *
14982 * @param time the new modification time of this entry
14983 */
14984 void set modificationTime(int time) {
14985 _modificationTime = time;
14986 }
14987
14988 /**
14989 * Set the state of the data represented by the given descriptor to the given state.
14990 *
14991 * @param descriptor the descriptor representing the data whose state is to be set
14992 * @param the new state of the data represented by the given descriptor
14993 */
14994 void setState(DataDescriptor descriptor, CacheState state) {
14995 if (identical(descriptor, SourceEntry.CONTENT)) {
14996 _content = updatedValue(state, _content, null);
14997 _contentState = _checkContentState(state);
14998 } else if (identical(descriptor, SourceEntry.LINE_INFO)) {
14999 _lineInfo = updatedValue(state, _lineInfo, null);
15000 _lineInfoState = state;
15001 } else {
15002 throw new IllegalArgumentException("Invalid descriptor: ${descriptor}");
15003 }
15004 }
15005
15006 /**
15007 * Set the value of the data represented by the given descriptor to the given value.
15008 *
15009 * @param descriptor the descriptor representing the data whose value is to be set
15010 * @param value the new value of the data represented by the given descriptor
15011 */
15012 void setValue(DataDescriptor descriptor, Object value) {
15013 if (identical(descriptor, SourceEntry.CONTENT)) {
15014 _content = value as String;
15015 _contentState = _checkContentState(CacheState.VALID);
15016 } else if (identical(descriptor, SourceEntry.LINE_INFO)) {
15017 _lineInfo = value as LineInfo;
15018 _lineInfoState = CacheState.VALID;
15019 } else {
15020 throw new IllegalArgumentException("Invalid descriptor: ${descriptor}");
15021 }
15022 }
15023
15024 @override
15025 String toString() {
15026 JavaStringBuilder builder = new JavaStringBuilder();
15027 writeOn(builder);
15028 return builder.toString();
15029 }
15030
15031 /**
15032 * Set the value of all of the flags with the given indexes to false.
15033 *
15034 * @param indexes the indexes of the flags whose value is to be set to false
15035 */
15036 void clearFlags(List<int> indexes) {
15037 for (int i = 0; i < indexes.length; i++) {
15038 _flags = BooleanArray.set(_flags, indexes[i], false);
15039 }
15040 }
15041
15042 /**
15043 * Copy the information from the given cache entry.
15044 *
15045 * @param entry the cache entry from which information will be copied
15046 */
15047 void copyFrom(SourceEntryImpl entry) {
15048 _modificationTime = entry._modificationTime;
15049 _flags = entry._flags;
15050 _exception = entry._exception;
15051 _contentState = entry._contentState;
15052 _content = entry._content;
15053 _lineInfoState = entry._lineInfoState;
15054 _lineInfo = entry._lineInfo;
15055 }
15056
15057 /**
15058 * Return the value of the flag with the given index.
15059 *
15060 * @param index the index of the flag whose value is to be returned
15061 * @return the value of the flag with the given index
15062 */
15063 bool getFlag(int index) => BooleanArray.get(_flags, index);
15064
15065 /**
15066 * Return `true` if the state of any data value is [CacheState#ERROR].
15067 *
15068 * @return `true` if the state of any data value is [CacheState#ERROR]
15069 */
15070 bool get hasErrorState => _contentState == CacheState.ERROR || _lineInfoState == CacheState.ERROR;
15071
15072 /**
15073 * Set the exception that caused one or more values to have a state of [CacheS tate#ERROR] to
15074 * the given exception.
15075 *
15076 * @param exception the exception that caused one or more values to be uncompu table
15077 */
15078 void set exception(CaughtException exception) {
15079 if (exception == null) {
15080 throw new IllegalArgumentException("exception cannot be null");
15081 }
15082 this._exception = exception;
15083 }
15084
15085 /**
15086 * Set the value of the flag with the given index to the given value.
15087 *
15088 * @param index the index of the flag whose value is to be returned
15089 * @param value the value of the flag with the given index
15090 */
15091 void setFlag(int index, bool value) {
15092 _flags = BooleanArray.set(_flags, index, value);
15093 }
15094
15095 /**
15096 * Given that some data is being transitioned to the given state, return the v alue that should be
15097 * kept in the cache.
15098 *
15099 * @param state the state to which the data is being transitioned
15100 * @param currentValue the value of the data before the transition
15101 * @param defaultValue the value to be used if the current value is to be remo ved from the cache
15102 * @return the value of the data that should be kept in the cache
15103 */
15104 Object updatedValue(CacheState state, Object currentValue, Object defaultValue ) {
15105 if (state == CacheState.VALID) {
15106 throw new IllegalArgumentException("Use setValue() to set the state to VAL ID");
15107 } else if (state == CacheState.IN_PROCESS) {
15108 //
15109 // We can leave the current value in the cache for any 'get' methods to ac cess.
15110 //
15111 return currentValue;
15112 }
15113 return defaultValue;
15114 }
15115
15116 /**
15117 * Write a textual representation of the difference between the old entry and this entry to the
15118 * given string builder.
15119 *
15120 * @param builder the string builder to which the difference is to be written
15121 * @param oldEntry the entry that was replaced by this entry
15122 * @return `true` if some difference was written
15123 */
15124 bool writeDiffOn(JavaStringBuilder builder, SourceEntry oldEntry) {
15125 bool needsSeparator = false;
15126 CaughtException oldException = oldEntry.exception;
15127 if (!identical(oldException, _exception)) {
15128 builder.append("exception = ");
15129 builder.append(oldException.runtimeType);
15130 builder.append(" -> ");
15131 builder.append(_exception.runtimeType);
15132 needsSeparator = true;
15133 }
15134 int oldModificationTime = oldEntry.modificationTime;
15135 if (oldModificationTime != _modificationTime) {
15136 if (needsSeparator) {
15137 builder.append("; ");
15138 }
15139 builder.append("time = ");
15140 builder.append(oldModificationTime);
15141 builder.append(" -> ");
15142 builder.append(_modificationTime);
15143 needsSeparator = true;
15144 }
15145 needsSeparator = writeStateDiffOn(builder, needsSeparator, oldEntry, SourceE ntry.CONTENT, "content");
15146 needsSeparator = writeStateDiffOn(builder, needsSeparator, oldEntry, SourceE ntry.LINE_INFO, "lineInfo");
15147 return needsSeparator;
15148 }
15149
15150 /**
15151 * Write a textual representation of this entry to the given builder. The resu lt will only be used
15152 * for debugging purposes.
15153 *
15154 * @param builder the builder to which the text should be written
15155 */
15156 void writeOn(JavaStringBuilder builder) {
15157 builder.append("time = ");
15158 builder.append(_modificationTime);
15159 builder.append("; content = ");
15160 builder.append(_contentState);
15161 builder.append("; lineInfo = ");
15162 builder.append(_lineInfoState);
15163 }
15164
15165 /**
15166 * Write a textual representation of the difference between the state of the s pecified data
15167 * between the old entry and this entry to the given string builder.
15168 *
15169 * @param builder the string builder to which the difference is to be written
15170 * @param needsSeparator `true` if any data that is written
15171 * @param oldEntry the entry that was replaced by this entry
15172 * @param descriptor the descriptor defining the data whose state is being com pared
15173 * @param label the label used to describe the state
15174 * @return `true` if some difference was written
15175 */
15176 bool writeStateDiffOn(JavaStringBuilder builder, bool needsSeparator, SourceEn try oldEntry, DataDescriptor descriptor, String label) {
15177 CacheState oldState = oldEntry.getState(descriptor);
15178 CacheState newState = getState(descriptor);
15179 if (oldState != newState) {
15180 if (needsSeparator) {
15181 builder.append("; ");
15182 }
15183 builder.append(label);
15184 builder.append(" = ");
15185 builder.append(oldState);
15186 builder.append(" -> ");
15187 builder.append(newState);
15188 return true;
15189 }
15190 return needsSeparator;
15191 }
15192
15193 /**
15194 * If the state is changing from ERROR to anything else, capture the informati on. This is an
15195 * attempt to discover the underlying cause of a long-standing bug.
15196 *
15197 * @param newState the new state of the content
15198 * @return the new state of the content
15199 */
15200 CacheState _checkContentState(CacheState newState) {
15201 if (_contentState == CacheState.ERROR) {
15202 InstrumentationBuilder builder = Instrumentation.builder2("SourceEntryImpl -checkContentState");
15203 builder.data3("message", "contentState changing from ${_contentState} to $ {newState}");
15204 //builder.data("source", source.getFullName());
15205 builder.record(new CaughtException(new AnalysisException(), null));
15206 builder.log();
15207 }
15208 return newState;
15209 }
15210 }
15211
15212 /**
15213 * The enumerated type `Priority` defines the priority levels used to return sou rces in an
15214 * optimal order. A smaller ordinal value equates to a higher priority.
15215 */
15216 class SourcePriority extends Enum<SourcePriority> {
15217 /**
15218 * Used for a Dart source that is known to be a part contained in a library th at was recently
15219 * resolved. These parts are given a higher priority because there is a high p robability that
15220 * their AST structure is still in the cache and therefore would not need to b e re-created.
15221 */
15222 static const SourcePriority PRIORITY_PART = const SourcePriority('PRIORITY_PAR T', 0);
15223
15224 /**
15225 * Used for a Dart source that is known to be a library.
15226 */
15227 static const SourcePriority LIBRARY = const SourcePriority('LIBRARY', 1);
15228
15229 /**
15230 * Used for a Dart source whose kind is unknown.
15231 */
15232 static const SourcePriority UNKNOWN = const SourcePriority('UNKNOWN', 2);
15233
15234 /**
15235 * Used for a Dart source that is known to be a part but whose library has not yet been resolved.
15236 */
15237 static const SourcePriority NORMAL_PART = const SourcePriority('NORMAL_PART', 3);
15238
15239 /**
15240 * Used for an HTML source.
15241 */
15242 static const SourcePriority HTML = const SourcePriority('HTML', 4);
15243
15244 static const List<SourcePriority> values = const [PRIORITY_PART, LIBRARY, UNKN OWN, NORMAL_PART, HTML];
15245
15246 const SourcePriority(String name, int ordinal) : super(name, ordinal);
15247 }
15248
15249 /**
15250 * Instances of the class `TimestampedData` represent analysis data for which we have a
15251 * modification time.
15252 */
15253 class TimestampedData<E> {
15254 /**
15255 * The modification time of the source from which the data was created.
15256 */
15257 final int modificationTime;
15258
15259 /**
15260 * The data that was created from the source.
15261 */
15262 final E data;
15263
15264 /**
15265 * Initialize a newly created holder to hold the given values.
15266 *
15267 * @param modificationTime the modification time of the source from which the data was created
15268 * @param unit the data that was created from the source
15269 */
15270 TimestampedData(this.modificationTime, this.data);
15271 }
15272
15273 /**
15274 * Instances of the class `UniversalCachePartition` implement a cache partition that contains
15275 * all sources not contained in other partitions.
15276 */
15277 class UniversalCachePartition extends CachePartition {
15278 /**
15279 * Initialize a newly created partition.
15280 *
15281 * @param maxCacheSize the maximum number of sources for which AST structures should be kept in
15282 * the cache
15283 * @param retentionPolicy the policy used to determine which pieces of data to remove from the
15284 * cache
15285 */
15286 UniversalCachePartition(int maxCacheSize, CacheRetentionPolicy retentionPolicy ) : super(maxCacheSize, retentionPolicy);
15287
15288 @override
15289 bool contains(Source source) => true;
15290 }
15291
15292 /**
15293 * The unique instances of the class `WaitForAsyncTask` represents a state in wh ich there is
15294 * no analysis work that can be done until some asynchronous task (such as IO) h as completed, but
15295 * where analysis is not yet complete.
15296 */
15297 class WaitForAsyncTask extends AnalysisTask {
15298 /**
15299 * The unique instance of this class.
15300 */
15301 static WaitForAsyncTask _UniqueInstance = new WaitForAsyncTask();
15302
15303 /**
15304 * Return the unique instance of this class.
15305 *
15306 * @return the unique instance of this class
15307 */
15308 static WaitForAsyncTask get instance => _UniqueInstance;
15309
15310 /**
15311 * Prevent the creation of instances of this class.
15312 */
15313 WaitForAsyncTask() : super(null);
15314
15315 @override
15316 accept(AnalysisTaskVisitor visitor) => null;
15317
15318 @override
15319 String get taskDescription => "Waiting for async analysis";
15320
15321 @override
15322 void internalPerform() {
15323 }
15324 }
15325
15326 /**
15327 * Instances of the class `WorkManager` manage a list of sources that need to ha ve analysis
15328 * work performed on them.
15329 */
15330 class WorkManager {
15331 /**
15332 * An array containing the various queues is priority order.
15333 */
15334 List<List<Source>> _workQueues;
15335
15336 /**
15337 * Initialize a newly created manager to have no work queued up.
15338 */
15339 WorkManager() {
15340 int queueCount = SourcePriority.values.length;
15341 _workQueues = new List<List>(queueCount);
15342 for (int i = 0; i < queueCount; i++) {
15343 _workQueues[i] = new List<Source>();
15344 }
15345 }
15346
15347 /**
15348 * Record that the given source needs to be analyzed. The priority level is us ed to control when
15349 * the source will be analyzed with respect to other sources. If the source wa s previously added
15350 * then it's priority is updated. If it was previously added with the same pri ority then it's
15351 * position in the queue is unchanged.
15352 *
15353 * @param source the source that needs to be analyzed
15354 * @param priority the priority level of the source
15355 */
15356 void add(Source source, SourcePriority priority) {
15357 int queueCount = _workQueues.length;
15358 int ordinal = priority.ordinal;
15359 for (int i = 0; i < queueCount; i++) {
15360 List<Source> queue = _workQueues[i];
15361 if (i == ordinal) {
15362 if (!queue.contains(source)) {
15363 queue.add(source);
15364 }
15365 } else {
15366 queue.remove(source);
15367 }
15368 }
15369 }
15370
15371 /**
15372 * Record that the given source needs to be analyzed. The priority level is us ed to control when
15373 * the source will be analyzed with respect to other sources. If the source wa s previously added
15374 * then it's priority is updated. In either case, it will be analyzed before o ther sources of the
15375 * same priority.
15376 *
15377 * @param source the source that needs to be analyzed
15378 * @param priority the priority level of the source
15379 */
15380 void addFirst(Source source, SourcePriority priority) {
15381 int queueCount = _workQueues.length;
15382 int ordinal = priority.ordinal;
15383 for (int i = 0; i < queueCount; i++) {
15384 List<Source> queue = _workQueues[i];
15385 if (i == ordinal) {
15386 queue.remove(source);
15387 queue.insert(0, source);
15388 } else {
15389 queue.remove(source);
15390 }
15391 }
15392 }
15393
15394 /**
15395 * Return an iterator that can be used to access the sources to be analyzed in the order in which
15396 * they should be analyzed.
15397 *
15398 * <b>Note:</b> As with other iterators, no sources can be added or removed fr om this work manager
15399 * while the iterator is being used. Unlike some implementations, however, the iterator will not
15400 * detect when this requirement has been violated; it might work correctly, it might return the
15401 * wrong source, or it might throw an exception.
15402 *
15403 * @return an iterator that can be used to access the next source to be analyz ed
15404 */
15405 WorkManager_WorkIterator iterator() => new WorkManager_WorkIterator(this);
15406
15407 /**
15408 * Record that the given source is fully analyzed.
15409 *
15410 * @param source the source that is fully analyzed
15411 */
15412 void remove(Source source) {
15413 int queueCount = _workQueues.length;
15414 for (int i = 0; i < queueCount; i++) {
15415 _workQueues[i].remove(source);
15416 }
15417 }
15418
15419 @override
15420 String toString() {
15421 JavaStringBuilder builder = new JavaStringBuilder();
15422 List<SourcePriority> priorities = SourcePriority.values;
15423 bool needsSeparator = false;
15424 int queueCount = _workQueues.length;
15425 for (int i = 0; i < queueCount; i++) {
15426 List<Source> queue = _workQueues[i];
15427 if (!queue.isEmpty) {
15428 if (needsSeparator) {
15429 builder.append("; ");
15430 }
15431 builder.append(priorities[i]);
15432 builder.append(": ");
15433 int queueSize = queue.length;
15434 for (int j = 0; j < queueSize; j++) {
15435 if (j > 0) {
15436 builder.append(", ");
15437 }
15438 builder.append(queue[j].fullName);
15439 }
15440 needsSeparator = true;
15441 }
15442 }
15443 return builder.toString();
15444 }
15445 }
15446
15447 /**
15448 * Instances of the class `WorkIterator` implement an iterator that returns the sources in a
15449 * work manager in the order in which they are to be analyzed.
15450 */
15451 class WorkManager_WorkIterator {
15452 final WorkManager WorkManager_this;
15453
15454 /**
15455 * The index of the work queue through which we are currently iterating.
15456 */
15457 int _queueIndex = 0;
15458
15459 /**
15460 * The index of the next element of the work queue to be returned.
15461 */
15462 int _index = -1;
15463
15464 /**
15465 * Initialize a newly created iterator to be ready to return the first element in the iteration.
15466 */
15467 WorkManager_WorkIterator(this.WorkManager_this) {
15468 _advance();
15469 }
15470
15471 /**
15472 * Return `true` if there is another [Source] available for processing.
15473 *
15474 * @return `true` if there is another [Source] available for processing
15475 */
15476 bool get hasNext => _queueIndex < WorkManager_this._workQueues.length;
15477
15478 /**
15479 * Return the next [Source] available for processing and advance so that the r eturned
15480 * source will not be returned again.
15481 *
15482 * @return the next [Source] available for processing
15483 */
15484 Source next() {
15485 if (!hasNext) {
15486 throw new NoSuchElementException();
15487 }
15488 Source source = WorkManager_this._workQueues[_queueIndex][_index];
15489 _advance();
15490 return source;
15491 }
15492
15493 /**
15494 * Increment the [index] and [queueIndex] so that they are either indicating t he
15495 * next source to be returned or are indicating that there are no more sources to be returned.
15496 */
15497 void _advance() {
15498 _index++;
15499 if (_index >= WorkManager_this._workQueues[_queueIndex].length) {
15500 _index = 0;
15501 _queueIndex++;
15502 while (_queueIndex < WorkManager_this._workQueues.length && WorkManager_th is._workQueues[_queueIndex].isEmpty) {
15503 _queueIndex++;
15504 }
15505 }
15506 }
15507 }
OLDNEW

Powered by Google App Engine
This is Rietveld 408576698