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

Side by Side Diff: pkg/analyzer/lib/src/context/cache.dart

Issue 913483002: First cut at analysis driver (Closed) Base URL: https://dart.googlecode.com/svn/branches/bleeding_edge/dart
Patch Set: Created 5 years, 10 months ago
Use n/p to move between diff chunks; N/P to move between comments. Draft comments are only viewable by you.
Jump to:
View unified diff | Download patch | Annotate | Revision Log
OLDNEW
(Empty)
1 // Copyright (c) 2015, the Dart project authors. Please see the AUTHORS file
2 // for details. All rights reserved. Use of this source code is governed by a
3 // BSD-style license that can be found in the LICENSE file.
4
5 library analyzer.src.context.cache;
6
7 import 'dart:collection';
8
9 import 'package:analyzer/src/generated/ast.dart';
10 import 'package:analyzer/src/generated/engine.dart' show AnalysisEngine,
11 CacheState, InternalAnalysisContext, RetentionPriority;
12 import 'package:analyzer/src/generated/html.dart';
13 import 'package:analyzer/src/generated/java_engine.dart';
14 import 'package:analyzer/src/generated/utilities_collection.dart';
15 import 'package:analyzer/task/model.dart';
16
17 /**
18 * An LRU cache of results produced by analysis.
19 */
20 class AnalysisCache {
21 /**
22 * A flag used to control whether trace information should be produced when
23 * the content of the cache is modified.
24 */
25 static bool _TRACE_CHANGES = false;
26
27 /**
28 * An array containing the partitions of which this cache is comprised.
29 */
30 final List<CachePartition> _partitions;
31
32 /**
33 * Initialize a newly created cache to have the given [partitions]. The
34 * partitions will be searched in the order in which they appear in the array,
35 * so the most specific partition (usually an [SdkCachePartition]) should be
36 * first and the most general (usually a [UniversalCachePartition]) last.
37 */
38 AnalysisCache(this._partitions);
39
40 /**
41 * Return the number of entries in this cache that have an AST associated with
42 * them.
43 */
44 int get astSize => _partitions[_partitions.length - 1].astSize;
Paul Berry 2015/03/03 17:21:31 Why not sum .astSize over all partitions?
Brian Wilkerson 2015/03/03 21:21:17 This is kind of a hold-over from an earlier implem
45
46 // /**
Paul Berry 2015/03/03 17:21:31 Add a TODO comment here?
Brian Wilkerson 2015/03/03 21:21:16 Done
47 // * Return information about each of the partitions in this cache.
48 // */
49 // List<AnalysisContextStatistics_PartitionData> get partitionData {
50 // int count = _partitions.length;
51 // List<AnalysisContextStatistics_PartitionData> data =
52 // new List<AnalysisContextStatistics_PartitionData>(count);
53 // for (int i = 0; i < count; i++) {
54 // CachePartition partition = _partitions[i];
55 // data[i] = new AnalysisContextStatisticsImpl_PartitionDataImpl(
56 // partition.astSize,
57 // partition.map.length);
58 // }
59 // return data;
60 // }
61
62 /**
63 * Record that the AST associated with the given [target] was just read from
64 * the cache.
65 */
66 void accessedAst(AnalysisTarget target) {
67 int count = _partitions.length;
68 for (int i = 0; i < count; i++) {
69 if (_partitions[i].contains(target)) {
Paul Berry 2015/03/03 17:21:31 It seems like we do this loop over partitions in a
Brian Wilkerson 2015/03/03 21:21:16 Sounds reasonable. Left for a later CL.
70 _partitions[i].accessedAst(target);
71 return;
72 }
73 }
74 }
75
76 /**
77 * Return the entry associated with the given [target].
78 */
79 CacheEntry get(AnalysisTarget target) {
80 int count = _partitions.length;
81 for (int i = 0; i < count; i++) {
82 if (_partitions[i].contains(target)) {
83 return _partitions[i].get(target);
84 }
85 }
86 //
87 // We should never get to this point because the last partition should
88 // always be a universal partition, except in the case of the SDK context,
89 // in which case the target should always be part of the SDK.
90 //
91 return null;
92 }
93
94 /**
95 * Return context that owns the given [target].
Paul Berry 2015/03/03 17:21:31 I'm not sure I understand what you mean by "owns".
Brian Wilkerson 2015/03/03 21:21:16 Done
96 */
97 InternalAnalysisContext getContextFor(AnalysisTarget target) {
98 int count = _partitions.length;
99 for (int i = 0; i < count; i++) {
100 if (_partitions[i].contains(target)) {
101 return _partitions[i].context;
102 }
103 }
104 //
105 // We should never get to this point because the last partition should
106 // always be a universal partition, except in the case of the SDK context,
107 // in which case the target should always be part of the SDK.
108 //
109 AnalysisEngine.instance.logger.logInformation(
Paul Berry 2015/03/03 17:21:32 I'm concerned that if we just log the error, it wo
Brian Wilkerson 2015/03/03 21:21:16 Saved for a follow-on CL.
110 'Could not find context for $target',
111 new CaughtException(new AnalysisException(), null));
112 return null;
113 }
114
115 /**
116 * Return an iterator returning all of the map entries mapping targets to
117 * cache entries.
118 */
119 MapIterator<AnalysisTarget, CacheEntry> iterator() {
120 int count = _partitions.length;
121 List<Map<AnalysisTarget, CacheEntry>> maps = new List<Map>(count);
122 for (int i = 0; i < count; i++) {
123 maps[i] = _partitions[i].map;
124 }
125 return new MultipleMapIterator<AnalysisTarget, CacheEntry>(maps);
126 }
127
128 /**
129 * Associate the given [entry] with the given [target].
130 */
131 void put(AnalysisTarget target, CacheEntry entry) {
132 entry.fixExceptionState();
133 int count = _partitions.length;
134 for (int i = 0; i < count; i++) {
135 if (_partitions[i].contains(target)) {
136 if (_TRACE_CHANGES) {
137 try {
138 CacheEntry oldEntry = _partitions[i].get(target);
139 if (oldEntry == null) {
140 AnalysisEngine.instance.logger.logInformation(
141 'Added a cache entry for $target.');
142 } else {
143 AnalysisEngine.instance.logger.logInformation(
144 'Modified the cache entry for $target.');
145 // 'Diff = ${entry.getDiff(oldEntry)}');
146 }
147 } catch (exception) {
Paul Berry 2015/03/03 17:21:31 Why would an exception ever occur here?
Brian Wilkerson 2015/03/03 21:21:17 My guess is that it was debugging code added to th
148 // Ignored
149 }
150 }
151 _partitions[i].put(target, entry);
152 return;
153 }
154 }
155 }
Paul Berry 2015/03/03 17:21:32 If we get to the end of the function without findi
Brian Wilkerson 2015/03/03 21:21:16 Added TODO.
156
157 /**
158 * Remove all information related to the given [target] from this cache.
159 */
160 void remove(AnalysisTarget target) {
161 int count = _partitions.length;
162 for (int i = 0; i < count; i++) {
163 if (_partitions[i].contains(target)) {
164 if (_TRACE_CHANGES) {
165 try {
166 AnalysisEngine.instance.logger.logInformation(
167 'Removed the cache entry for $target.');
168 } catch (exception) {
Paul Berry 2015/03/03 17:21:32 Why would an exception ever occur here?
Brian Wilkerson 2015/03/03 21:21:16 Removed
169 // Ignored
170 }
171 }
172 _partitions[i].remove(target);
173 return;
174 }
175 }
176 }
177
178 /**
179 * Record that the AST associated with the given [target] was just removed
180 * from the cache.
181 */
182 void removedAst(AnalysisTarget target) {
183 int count = _partitions.length;
184 for (int i = 0; i < count; i++) {
185 if (_partitions[i].contains(target)) {
186 _partitions[i].removedAst(target);
187 return;
188 }
189 }
190 }
191
192 /**
193 * Return the number of targets that are mapped to cache entries.
194 */
195 int size() {
196 int size = 0;
197 int count = _partitions.length;
198 for (int i = 0; i < count; i++) {
199 size += _partitions[i].size();
200 }
201 return size;
202 }
203
204 /**
205 * Record that the AST associated with the given [target] was just stored to
206 * the cache.
207 */
208 void storedAst(AnalysisTarget target) {
209 int count = _partitions.length;
210 for (int i = 0; i < count; i++) {
211 if (_partitions[i].contains(target)) {
212 _partitions[i].storedAst(target);
213 return;
214 }
215 }
216 }
217 }
218
219 /**
220 * The information cached by an analysis context about an individual target.
221 */
222 class CacheEntry {
223 /**
224 * The index of the flag indicating whether the source was explicitly added to
225 * the context or whether the source was implicitly added because it was
226 * referenced by another source.
227 */
228 static int _EXPLICITLY_ADDED_FLAG = 0;
229
230 /**
231 * The most recent time at which the state of the target matched the state
232 * represented by this entry.
233 */
234 int modificationTime = 0;
235
236 /**
237 * The exception that caused one or more values to have a state of
238 * [CacheState.ERROR].
239 */
Paul Berry 2015/03/03 17:21:32 I'm assuming that an intended invariant is that wh
Brian Wilkerson 2015/03/03 21:21:16 Yes.
240 CaughtException exception;
241
242 /**
243 * A bit-encoding of boolean flags associated with this entry's target.
244 */
245 int _flags = 0;
246
247 /**
248 * A table mapping result descriptors to the cached values of those results.
249 */
250 Map<ResultDescriptor, ResultData> _resultMap =
251 new HashMap<ResultDescriptor, ResultData>();
252
253 /**
254 * Return `true` if the source was explicitly added to the context or `false`
255 * if the source was implicitly added because it was referenced by another
256 * source.
257 */
258 bool get explicitlyAdded => _getFlag(_EXPLICITLY_ADDED_FLAG);
259
260 /**
261 * Set whether the source was explicitly added to the context to match the
262 * [explicitlyAdded] flag.
263 */
264 void set explicitlyAdded(bool explicitlyAdded) {
265 _setFlag(_EXPLICITLY_ADDED_FLAG, explicitlyAdded);
266 }
267
268 /**
269 * Return `true` if this entry contains at least one result whose value is an
270 * AST structure.
271 */
272 bool get hasAstStructure {
273 for (ResultData data in _resultMap.values) {
274 if (data.value is AstNode || data.value is XmlNode) {
275 return true;
276 }
277 }
278 return false;
279 }
280
281 /**
282 * Fix the state of the [exception] to match the current state of the entry.
283 */
284 void fixExceptionState() {
285 if (hasErrorState()) {
286 if (exception == null) {
287 //
288 // This code should never be reached, but is a fail-safe in case an
289 // exception is not recorded when it should be.
290 //
Paul Berry 2015/03/03 17:21:31 Since this should never happen, should we also add
Brian Wilkerson 2015/03/03 21:21:17 That would potentially let us know that it happene
291 String message = 'State set to ERROR without setting an exception';
292 exception = new CaughtException(new AnalysisException(message), null);
293 }
294 } else {
295 exception = null;
296 }
297 }
298
299 /**
300 * Mark any AST structures associated with this cache entry as being flushed.
301 */
302 void flushAstStructures() {
303 _resultMap.forEach((ResultDescriptor descriptor, ResultData data) {
304 if (data.value is AstNode || data.value is XmlNode) {
305 _validateStateChange(descriptor, CacheState.FLUSHED);
306 data.state = CacheState.FLUSHED;
307 data.value = descriptor.defaultValue;
308 }
309 });
Paul Berry 2015/03/03 17:21:32 To restore the invariant, we might need to set thi
Brian Wilkerson 2015/03/03 21:21:16 If the state were ERROR, then the value would be n
310 }
311
312 /**
313 * Return the state of the result represented by the given [descriptor].
314 */
315 CacheState getState(ResultDescriptor descriptor) {
316 ResultData data = _resultMap[descriptor];
317 if (data == null) {
318 return CacheState.INVALID;
319 }
320 return data.state;
321 }
322
323 /**
324 * Return the value of the result represented by the given [descriptor], or
325 * the default value for the result if this entry does not have a valid value.
326 */
327 /*<V>*/ dynamic /*V*/ getValue(ResultDescriptor /*<V>*/ descriptor) {
328 ResultData data = _resultMap[descriptor];
329 if (data == null) {
330 return descriptor.defaultValue;
331 }
332 return data.value;
333 }
334
335 /**
336 * Return `true` if the state of any data value is [CacheState.ERROR].
337 */
338 bool hasErrorState() {
339 for (ResultData data in _resultMap.values) {
340 if (data.state == CacheState.ERROR) {
341 return true;
342 }
343 }
344 return false;
345 }
346
347 /**
348 * Invalidate all of the information associated with this entry's target.
349 */
350 void invalidateAllInformation() {
351 _resultMap.clear();
Paul Berry 2015/03/03 17:21:31 To restore the invariant, we should set this.excep
Brian Wilkerson 2015/03/03 21:21:17 Done
352 }
353
354 /**
355 * Set the state of the result represented by the given [descriptor] to the
356 * given [state].
357 */
358 void setState(ResultDescriptor descriptor, CacheState state) {
359 if (state == CacheState.VALID) {
360 throw new ArgumentError('use setValue() to set the state to VALID');
361 }
362 _validateStateChange(descriptor, state);
363 if (state == CacheState.INVALID) {
364 _resultMap.remove(descriptor);
365 } else {
366 ResultData data =
367 _resultMap.putIfAbsent(descriptor, () => new ResultData(descriptor));
368 data.state = state;
369 if (state != CacheState.IN_PROCESS) {
370 //
371 // If the state is in-process, we can leave the current value in the
372 // cache for any 'get' methods to access.
373 //
374 data.value = descriptor.defaultValue;
375 }
376 }
377 }
Paul Berry 2015/03/03 17:21:31 I'm surprised this function doesn't set this.excep
Brian Wilkerson 2015/03/03 21:21:17 Then the client is expected to set the exception a
378
379 /**
380 * Set the value of the result represented by the given [descriptor] to the
381 * given [value].
382 */
383 /*<V>*/ void setValue(ResultDescriptor /*<V>*/ descriptor, dynamic /*V*/
384 value) {
385 _validateStateChange(descriptor, CacheState.VALID);
386 ResultData data =
387 _resultMap.putIfAbsent(descriptor, () => new ResultData(descriptor));
388 data.state = CacheState.VALID;
389 data.value = value == null ? descriptor.defaultValue : value;
390 }
Paul Berry 2015/03/03 17:21:31 Similar question about this.exception for this fun
Brian Wilkerson 2015/03/03 21:21:17 The current assumption is that values won't be cre
391
392 @override
393 String toString() {
394 StringBuffer buffer = new StringBuffer();
395 _writeOn(buffer);
396 return buffer.toString();
397 }
398
399 /**
400 * Return the value of the flag with the given [index].
401 */
402 bool _getFlag(int index) => BooleanArray.get(_flags, index);
403
404 /**
405 * Set the value of the flag with the given [index] to the given [value].
406 */
407 void _setFlag(int index, bool value) {
408 _flags = BooleanArray.set(_flags, index, value);
409 }
410
411 /**
412 * If the state of the value described by the given [descriptor] is changing
413 * from ERROR to anything else, capture the information. This is an attempt to
414 * discover the underlying cause of a long-standing bug.
415 */
416 void _validateStateChange(ResultDescriptor descriptor, CacheState newState) {
417 // TODO(brianwilkerson) Decide whether we still want to capture this data.
418 // if (descriptor != CONTENT) {
419 // return;
420 // }
421 // ResultData data = resultMap[CONTENT];
422 // if (data != null && data.state == CacheState.ERROR) {
423 // String message =
424 // 'contentState changing from ${data.state} to $newState';
425 // InstrumentationBuilder builder =
426 // Instrumentation.builder2('CacheEntry-validateStateChange');
427 // builder.data3('message', message);
428 // //builder.data('source', source.getFullName());
429 // builder.record(new CaughtException(new AnalysisException(message), null) );
430 // builder.log();
431 // }
432 }
433
434 /**
435 * Write a textual representation of this entry to the given [buffer]. The
436 * result should only be used for debugging purposes.
437 */
438 void _writeOn(StringBuffer buffer) {
439 buffer.write('time = ');
440 buffer.write(modificationTime);
441 List<ResultDescriptor> results = _resultMap.keys.toList();
442 results.sort(
443 (ResultDescriptor first, ResultDescriptor second) =>
444 first.toString().compareTo(second.toString()));
445 for (ResultDescriptor result in results) {
446 ResultData data = _resultMap[result];
447 buffer.write('; ');
448 buffer.write(result.toString());
449 buffer.write(' = ');
450 buffer.write(data..state);
451 }
452 }
453 }
454
455 /**
456 * A single partition in an LRU cache of information related to analysis.
457 */
458 abstract class CachePartition {
459 /**
460 * The context that owns this partition. Multiple contexts can reference a
461 * partition, but only one context can own it.
462 */
463 final InternalAnalysisContext context;
464
465 /**
466 * The maximum number of sources for which AST structures should be kept in
467 * the cache.
468 */
469 int _maxCacheSize = 0;
470
471 /**
472 * The policy used to determine which results to remove from the cache.
473 */
474 final CacheRetentionPolicy _retentionPolicy;
475
476 /**
477 * A table mapping the targets belonging to this partition to the information
478 * known about those targets.
479 */
480 HashMap<AnalysisTarget, CacheEntry> _targetMap =
481 new HashMap<AnalysisTarget, CacheEntry>();
482
483 /**
484 * A list containing the most recently accessed targets with the most recently
485 * used at the end of the list. When more targets are added than the maximum
486 * allowed then the least recently used target will be removed and will have
487 * it's cached AST structure flushed.
488 */
489 List<AnalysisTarget> _recentlyUsed = <AnalysisTarget>[];
Paul Berry 2015/03/03 17:21:32 How big is this list expected to get in typical us
Brian Wilkerson 2015/03/03 21:21:16 It's a valid concern, but we should discuss off-li
490
491 /**
492 * Initialize a newly created cache partition, belonging to the given
493 * [context]. The partition will maintain at most [_maxCacheSize] AST
494 * structures in the cache, using the [_retentionPolicy] to determine which
495 * AST structures to flush.
496 */
497 CachePartition(this.context, this._maxCacheSize, this._retentionPolicy);
498
499 /**
500 * Return the number of entries in this partition that have an AST associated
501 * with them.
502 */
503 int get astSize {
504 int astSize = 0;
505 int count = _recentlyUsed.length;
506 for (int i = 0; i < count; i++) {
507 AnalysisTarget target = _recentlyUsed[i];
508 CacheEntry entry = _targetMap[target];
509 if (entry.hasAstStructure) {
510 astSize++;
511 }
512 }
513 return astSize;
514 }
515
516 /**
517 * Return a table mapping the targets known to the context to the information
518 * known about the target.
519 *
520 * <b>Note:</b> This method is only visible for use by [AnalysisCache] and
Paul Berry 2015/03/03 17:21:32 Since AnalysisCache is in the same library, how ab
Brian Wilkerson 2015/03/03 21:21:16 A hold-over from Java. It's currently also being u
521 * should not be used for any other purpose.
522 */
523 Map<AnalysisTarget, CacheEntry> get map => _targetMap;
524
525 /**
526 * Return the maximum size of the cache.
527 */
528 int get maxCacheSize => _maxCacheSize;
529
530 /**
531 * Set the maximum size of the cache to the given [size].
532 */
533 void set maxCacheSize(int size) {
534 _maxCacheSize = size;
535 while (_recentlyUsed.length > _maxCacheSize) {
536 if (!_flushAstFromCache()) {
537 break;
538 }
539 }
540 }
541
542 /**
543 * Record that the AST associated with the given [target] was just read from
544 * the cache.
545 */
546 void accessedAst(AnalysisTarget target) {
547 if (_recentlyUsed.remove(target)) {
548 _recentlyUsed.add(target);
549 return;
550 }
551 while (_recentlyUsed.length >= _maxCacheSize) {
552 if (!_flushAstFromCache()) {
553 break;
Paul Berry 2015/03/03 17:21:32 Here's a case where I'm concerned about the invari
Brian Wilkerson 2015/03/03 21:21:15 Part of a larger discussion.
554 }
555 }
556 _recentlyUsed.add(target);
557 }
558
559 /**
560 * Return `true` if the given [target] is contained in this partition.
561 */
562 bool contains(AnalysisTarget target);
Paul Berry 2015/03/03 17:21:32 For a long time I was confused by code calling con
Brian Wilkerson 2015/03/03 21:21:16 Yes, in a future CL.
563
564 /**
565 * Return the entry associated with the given [target].
566 */
567 CacheEntry get(AnalysisTarget target) => _targetMap[target];
568
569 /**
570 * Return an iterator returning all of the map entries mapping targets to
571 * cache entries.
572 */
573 MapIterator<AnalysisTarget, CacheEntry> iterator() =>
574 new SingleMapIterator<AnalysisTarget, CacheEntry>(_targetMap);
575
576 /**
577 * Associate the given [entry] with the given [target].
578 */
579 void put(AnalysisTarget target, CacheEntry entry) {
580 entry.fixExceptionState();
581 _targetMap[target] = entry;
582 }
583
584 /**
585 * Remove all information related to the given [target] from this cache.
586 */
587 void remove(AnalysisTarget target) {
588 _recentlyUsed.remove(target);
589 _targetMap.remove(target);
590 }
591
592 /**
593 * Record that the AST associated with the given [target] was just removed
594 * from the cache.
595 */
596 void removedAst(AnalysisTarget target) {
597 _recentlyUsed.remove(target);
598 }
599
600 /**
601 * Return the number of targets that are mapped to cache entries.
602 */
603 int size() => _targetMap.length;
604
605 /**
606 * Record that the AST associated with the given [target] was just stored to
607 * the cache.
608 */
609 void storedAst(AnalysisTarget target) {
610 if (_recentlyUsed.contains(target)) {
611 return;
612 }
613 while (_recentlyUsed.length >= _maxCacheSize) {
614 if (!_flushAstFromCache()) {
615 break;
616 }
617 }
618 _recentlyUsed.add(target);
619 }
620
621 /**
622 * Attempt to flush one AST structure from the cache. Return `true` if a
623 * structure was flushed.
624 */
625 bool _flushAstFromCache() {
626 AnalysisTarget removedTarget = _removeAstToFlush();
627 if (removedTarget == null) {
628 return false;
629 }
630 CacheEntry entry = _targetMap[removedTarget];
631 entry.flushAstStructures();
632 return true;
633 }
634
635 /**
636 * Remove and return one target from the list of recently used targets whose
637 * AST structure can be flushed from the cache. The target that will be
638 * returned will be the target that has been unreferenced for the longest
639 * period of time but that is not a priority for analysis.
640 */
Paul Berry 2015/03/03 17:21:30 The doc comments should also explain when this met
Brian Wilkerson 2015/03/03 21:21:17 Done
641 AnalysisTarget _removeAstToFlush() {
642 int targetToRemove = -1;
643 for (int i = 0; i < _recentlyUsed.length; i++) {
644 AnalysisTarget target = _recentlyUsed[i];
645 RetentionPriority priority =
646 _retentionPolicy.getAstPriority(target, _targetMap[target]);
647 if (priority == RetentionPriority.LOW) {
648 return _recentlyUsed.removeAt(i);
649 } else if (priority == RetentionPriority.MEDIUM && targetToRemove < 0) {
650 targetToRemove = i;
651 }
652 }
653 if (targetToRemove < 0) {
654 // This happens if the retention policy returns a priority of HIGH for all
655 // of the targets that have been recently used. This is the case, for
656 // example, when the list of priority sources is bigger than the current
657 // cache size.
658 return null;
659 }
660 return _recentlyUsed.removeAt(targetToRemove);
661 }
662 }
663
664 /**
665 * A policy objecy that determines how important it is for data to be retained
666 * in the analysis cache.
667 */
668 abstract class CacheRetentionPolicy {
669 /**
670 * Return the priority of retaining the AST structure for the given [target]
671 * in the given [entry].
672 */
673 // TODO(brianwilkerson) Find a more general mechanism, probably based on task
674 // descriptors, to determine which data is still needed for analysis and which
675 // can be removed from the cache. Ideally we could (a) remove the need for
676 // this class and (b) be able to flush all result data (not just AST's).
677 RetentionPriority getAstPriority(AnalysisTarget target, CacheEntry entry);
678 }
679
680 /**
681 * A retention policy that will keep AST's in the cache if there is analysis
682 * information that needs to be computed for a source, where the computation is
683 * dependent on having the AST.
684 */
685 class DefaultRetentionPolicy implements CacheRetentionPolicy {
686 /**
687 * An instance of this class that can be shared.
688 */
689 static const DefaultRetentionPolicy POLICY = const DefaultRetentionPolicy();
690
691 /**
692 * Initialize a newly created instance of this class.
693 */
694 const DefaultRetentionPolicy();
695
696 // /**
697 // * Return `true` if there is analysis information in the given entry that ne eds to be
698 // * computed, where the computation is dependent on having the AST.
699 // *
700 // * @param dartEntry the entry being tested
701 // * @return `true` if there is analysis information that needs to be computed from the AST
702 // */
703 // bool astIsNeeded(DartEntry dartEntry) =>
704 // dartEntry.hasInvalidData(DartEntry.HINTS) ||
705 // dartEntry.hasInvalidData(DartEntry.LINTS) ||
706 // dartEntry.hasInvalidData(DartEntry.VERIFICATION_ERRORS) ||
707 // dartEntry.hasInvalidData(DartEntry.RESOLUTION_ERRORS);
708
709 @override
710 RetentionPriority getAstPriority(AnalysisTarget target, CacheEntry entry) {
711 // if (sourceEntry is DartEntry) {
Paul Berry 2015/03/03 17:21:31 Add a TODO comment here?
Brian Wilkerson 2015/03/03 21:21:17 Done
712 // DartEntry dartEntry = sourceEntry;
713 // if (astIsNeeded(dartEntry)) {
714 // return RetentionPriority.MEDIUM;
715 // }
716 // }
717 // return RetentionPriority.LOW;
718 return RetentionPriority.MEDIUM;
719 }
720 }
721
722 /**
723 * The data about a single analysis result that is stored in a [CacheEntry].
724 */
725 class ResultData {
Paul Berry 2015/03/03 17:21:31 Would it be beneficial to make this a generic clas
Brian Wilkerson 2015/03/03 21:21:16 Possibly. I'll look into it for a follow-on CL.
726 /**
727 * The state of the cached value.
728 */
729 CacheState state;
730
731 /**
732 * The value being cached, or the default value for the result if there is no
733 * value (for example, when the [state] is [CacheState.INVALID].
734 */
735 Object value;
736
737 /**
738 * Initialize a newly created result holder to represent the value of data
739 * described by the given [descriptor].
740 */
741 ResultData(ResultDescriptor descriptor) {
742 state = CacheState.INVALID;
743 value = descriptor.defaultValue;
744 }
745 }
746
747 /**
748 * A cache partition that contains all of the targets in the SDK.
749 */
750 class SdkCachePartition extends CachePartition {
751 /**
752 * Initialize a newly created cache partition, belonging to the given
753 * [context]. The partition will maintain at most [maxCacheSize] AST
754 * structures in the cache.
755 */
756 SdkCachePartition(InternalAnalysisContext context, int maxCacheSize)
757 : super(context, maxCacheSize, DefaultRetentionPolicy.POLICY);
758
759 @override
760 bool contains(AnalysisTarget target) => target.source.isInSystemLibrary;
761 }
762
763 /**
764 * A cache partition that contains all targets not contained in other partitions .
765 */
766 class UniversalCachePartition extends CachePartition {
767 /**
768 * Initialize a newly created cache partition, belonging to the given
769 * [context]. The partition will maintain at most [maxCacheSize] AST
770 * structures in the cache, using the [retentionPolicy] to determine which
771 * AST structures to flush.
772 */
773 UniversalCachePartition(InternalAnalysisContext context, int maxCacheSize,
774 CacheRetentionPolicy retentionPolicy)
775 : super(context, maxCacheSize, retentionPolicy);
776
777 @override
778 bool contains(AnalysisTarget target) => true;
779 }
OLDNEW
« no previous file with comments | « no previous file | pkg/analyzer/lib/src/task/driver.dart » ('j') | pkg/analyzer/lib/src/task/driver.dart » ('J')

Powered by Google App Engine
This is Rietveld 408576698