OLD | NEW |
---|---|
(Empty) | |
1 // Copyright (c) 2015, the Dart project authors. Please see the AUTHORS file | |
2 // for details. All rights reserved. Use of this source code is governed by a | |
3 // BSD-style license that can be found in the LICENSE file. | |
4 | |
5 library analyzer.src.task.options_work_manager; | |
6 | |
7 import 'dart:collection'; | |
8 | |
9 import 'package:analyzer/src/context/cache.dart'; | |
10 import 'package:analyzer/src/generated/engine.dart' | |
11 show | |
12 AnalysisEngine, | |
13 AnalysisErrorInfo, | |
14 AnalysisErrorInfoImpl, | |
15 AnalysisOptions, | |
16 CacheState, | |
17 InternalAnalysisContext; | |
18 import 'package:analyzer/src/generated/error.dart'; | |
19 import 'package:analyzer/src/generated/source.dart'; | |
20 import 'package:analyzer/src/task/options.dart'; | |
21 import 'package:analyzer/task/model.dart'; | |
22 | |
23 /// The manager for `.analysis_options` specific analysis. | |
24 class OptionsWorkManager implements WorkManager { | |
25 /// The context for which work is being managed. | |
26 final InternalAnalysisContext context; | |
27 | |
28 /// The options file sources. | |
29 final LinkedHashSet<Source> sourceQueue = new LinkedHashSet<Source>(); | |
30 | |
31 /// The [TargetedResult]s that should be computed with priority. | |
32 final LinkedHashSet<TargetedResult> priorityResultQueue = | |
33 new LinkedHashSet<TargetedResult>(); | |
34 | |
35 /// Initialize a newly created manager. | |
36 OptionsWorkManager(this.context) { | |
37 analysisCache.onResultInvalidated.listen(onResultInvalidated); | |
38 } | |
39 | |
40 /// Returns the correctly typed result of `context.analysisCache`. | |
41 AnalysisCache get analysisCache => context.analysisCache; | |
42 | |
43 /// Specifies that the client wants the given [result] of the given [target] | |
44 /// to be computed with priority. | |
45 void addPriorityResult(AnalysisTarget target, ResultDescriptor result) { | |
46 priorityResultQueue.add(new TargetedResult(target, result)); | |
47 } | |
48 | |
49 @override | |
50 void applyChange(List<Source> addedSources, List<Source> changedSources, | |
51 List<Source> removedSources) { | |
52 addedSources = addedSources.where(_isOptionsSource).toList(); | |
53 changedSources = changedSources.where(_isOptionsSource).toList(); | |
54 removedSources = removedSources.where(_isOptionsSource).toList(); | |
55 // source queue | |
56 sourceQueue.addAll(addedSources); | |
57 sourceQueue.addAll(changedSources); | |
58 sourceQueue.removeAll(removedSources); | |
59 } | |
60 | |
61 @override | |
62 void applyPriorityTargets(List<AnalysisTarget> targets) { | |
63 // Unschedule the old targets. | |
64 List<TargetedResult> resultsToUnschedule = <TargetedResult>[]; | |
65 for (TargetedResult result in priorityResultQueue) { | |
66 if (result.result == ANALYSIS_OPTIONS_ERRORS) { | |
67 resultsToUnschedule.add(result); | |
68 } | |
69 } | |
70 priorityResultQueue.removeAll(resultsToUnschedule); | |
71 // Schedule new targets. | |
72 for (AnalysisTarget target in targets) { | |
73 if (_isOptionsSource(target)) { | |
74 addPriorityResult(target, ANALYSIS_OPTIONS_ERRORS); | |
75 } | |
76 } | |
77 } | |
78 | |
79 @override | |
80 List<AnalysisError> getErrors(Source source) { | |
81 if (!_isOptionsSource(source)) { | |
82 return AnalysisError.NO_ERRORS; | |
83 } | |
84 // If analysis is finished, use all the errors. | |
85 if (analysisCache.getState(source, ANALYSIS_OPTIONS_ERRORS) == | |
86 CacheState.VALID) { | |
87 return analysisCache.getValue(source, ANALYSIS_OPTIONS_ERRORS); | |
88 } | |
89 // If analysis is in progress, combine all known partial results. | |
Brian Wilkerson
2015/10/20 21:35:40
Given that there are no partial results to combine
pquitslund
2015/10/20 22:15:20
Good catch. Fixed.
| |
90 List<AnalysisError> errors = <AnalysisError>[]; | |
91 errors.addAll(analysisCache.getValue(source, ANALYSIS_OPTIONS_ERRORS)); | |
92 | |
93 return errors; | |
94 } | |
95 | |
96 @override | |
97 TargetedResult getNextResult() { | |
98 // Try to find a priority result to compute. | |
99 while (priorityResultQueue.isNotEmpty) { | |
100 TargetedResult result = priorityResultQueue.first; | |
101 if (!_needsComputing(result.target, result.result)) { | |
102 priorityResultQueue.remove(result); | |
103 continue; | |
104 } | |
105 return result; | |
106 } | |
107 // Try to find a new options file to analyze. | |
108 while (sourceQueue.isNotEmpty) { | |
109 Source optionsSource = sourceQueue.first; | |
110 if (!_needsComputing(optionsSource, ANALYSIS_OPTIONS_ERRORS)) { | |
111 sourceQueue.remove(optionsSource); | |
112 continue; | |
113 } | |
114 return new TargetedResult(optionsSource, ANALYSIS_OPTIONS_ERRORS); | |
115 } | |
116 // No results to compute. | |
117 return null; | |
118 } | |
119 | |
120 @override | |
121 WorkOrderPriority getNextResultPriority() { | |
122 if (priorityResultQueue.isNotEmpty) { | |
123 return WorkOrderPriority.PRIORITY; | |
124 } | |
125 if (sourceQueue.isNotEmpty) { | |
126 return WorkOrderPriority.NORMAL; | |
127 } | |
128 return WorkOrderPriority.NONE; | |
129 } | |
130 | |
131 @override | |
132 void onAnalysisOptionsChanged() { | |
133 // Do nothing. | |
134 } | |
135 | |
136 /// Notifies the manager that a result has been invalidated. | |
137 void onResultInvalidated(InvalidatedResult event) { | |
138 ResultDescriptor descriptor = event.descriptor; | |
139 if (descriptor == ANALYSIS_OPTIONS_ERRORS) { | |
140 sourceQueue.add(event.entry.target); | |
141 } | |
142 } | |
143 | |
144 @override | |
145 void onSourceFactoryChanged() { | |
146 // Do nothing. | |
147 } | |
148 | |
149 @override | |
150 void resultsComputed( | |
151 AnalysisTarget target, Map<ResultDescriptor, dynamic> outputs) { | |
152 // Update notice. | |
153 if (_isOptionsSource(target)) { | |
154 bool shouldSetErrors = false; | |
155 outputs.forEach((ResultDescriptor descriptor, value) { | |
156 if (descriptor == ANALYSIS_OPTIONS_ERRORS) { | |
157 shouldSetErrors = true; | |
158 } | |
159 }); | |
160 if (shouldSetErrors) { | |
161 AnalysisErrorInfo info = context.getErrors(target); | |
162 context.getNotice(target).setErrors(info.errors, info.lineInfo); | |
163 } | |
164 } | |
165 } | |
166 | |
167 /// Returns `true` if the given [result] of the given [target] needs | |
168 /// computing, i.e. it is not in the valid and not in the error state. | |
169 bool _needsComputing(AnalysisTarget target, ResultDescriptor result) { | |
170 CacheState state = analysisCache.getState(target, result); | |
171 return state != CacheState.VALID && state != CacheState.ERROR; | |
172 } | |
173 | |
174 /// Return `true` if the given target is an `.analysis_options` source. | |
175 static bool _isOptionsSource(AnalysisTarget target) => target is Source && | |
176 AnalysisEngine.isAnalysisOptionsFileName(target.fullName); | |
177 } | |
OLD | NEW |