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

Side by Side Diff: pkg/analyzer/lib/src/dart/analysis/driver.dart

Issue 2450053003: Replace Stream with monitor. (Closed)
Patch Set: Created 4 years, 1 month 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
« no previous file with comments | « no previous file | no next file » | no next file with comments »
Toggle Intra-line Diffs ('i') | Expand Comments ('e') | Collapse Comments ('c') | Show Comments Hide Comments ('s')
OLDNEW
1 // Copyright (c) 2016, the Dart project authors. Please see the AUTHORS file 1 // Copyright (c) 2016, the Dart project authors. Please see the AUTHORS file
2 // for details. All rights reserved. Use of this source code is governed by a 2 // for details. All rights reserved. Use of this source code is governed by a
3 // BSD-style license that can be found in the LICENSE file. 3 // BSD-style license that can be found in the LICENSE file.
4 4
5 import 'dart:async'; 5 import 'dart:async';
6 import 'dart:collection'; 6 import 'dart:collection';
7 import 'dart:convert'; 7 import 'dart:convert';
8 8
9 import 'package:analyzer/dart/ast/ast.dart'; 9 import 'package:analyzer/dart/ast/ast.dart';
10 import 'package:analyzer/dart/ast/token.dart'; 10 import 'package:analyzer/dart/ast/token.dart';
(...skipping 140 matching lines...) Expand 10 before | Expand all | Expand 10 after
151 * It maps file paths to the unlinked API signatures. 151 * It maps file paths to the unlinked API signatures.
152 */ 152 */
153 final _fileApiSignatureMap = <String, String>{}; 153 final _fileApiSignatureMap = <String, String>{};
154 154
155 /** 155 /**
156 * Mapping from library URIs to the dependency signature of the library. 156 * Mapping from library URIs to the dependency signature of the library.
157 */ 157 */
158 final _dependencySignatureMap = <Uri, String>{}; 158 final _dependencySignatureMap = <Uri, String>{};
159 159
160 /** 160 /**
161 * TODO(scheglov) document and improve 161 * The monitor that is signalled when there is work to do.
162 */ 162 */
163 final _hasWorkStreamController = new StreamController<String>(); 163 final _Monitor _hasWork = new _Monitor();
164 164
165 AnalysisDriver(this._logger, this._resourceProvider, this._byteStore, 165 AnalysisDriver(this._logger, this._resourceProvider, this._byteStore,
166 this._contentCache, this._sourceFactory, this._analysisOptions) { 166 this._contentCache, this._sourceFactory, this._analysisOptions) {
167 _sdkBundle = _sourceFactory.dartSdk.getLinkedBundle(); 167 _sdkBundle = _sourceFactory.dartSdk.getLinkedBundle();
168 } 168 }
169 169
170 /** 170 /**
171 * Set the list of files that the driver should try to analyze sooner. 171 * Set the list of files that the driver should try to analyze sooner.
172 * 172 *
173 * Every path in the list must be absolute and normalized. 173 * Every path in the list must be absolute and normalized.
174 * 174 *
175 * The driver will produce the results through the [results] stream. The 175 * The driver will produce the results through the [results] stream. The
176 * exact order in which results are produced is not defined, neither 176 * exact order in which results are produced is not defined, neither
177 * between priority files, nor between priority and non-priority files. 177 * between priority files, nor between priority and non-priority files.
178 */ 178 */
179 void set priorityFiles(List<String> priorityPaths) { 179 void set priorityFiles(List<String> priorityPaths) {
180 // TODO(scheglov) implement 180 // TODO(scheglov) implement
181 } 181 }
182 182
183 /** 183 /**
184 * Return the [Stream] that produces [AnalysisResult]s for added files. 184 * Return the [Stream] that produces [AnalysisResult]s for added files.
185 * 185 *
186 * Analysis starts when the client starts listening to the stream, and stops 186 * Analysis starts when the client starts listening to the stream, and stops
187 * when the client cancels the subscription. 187 * when the client cancels the subscription.
Paul Berry 2016/10/31 16:40:47 It looks to me like it's not safe to call `.result
scheglov 2016/10/31 17:45:43 Yes, this is a normal Stream, not broadcast. So, o
188 * 188 *
189 * When the client starts listening, the analysis state transitions to 189 * When the client starts listening, the analysis state transitions to
190 * "analyzing" and an analysis result is produced for every added file prior 190 * "analyzing" and an analysis result is produced for every added file prior
191 * to the next time the analysis state transitions to "idle". 191 * to the next time the analysis state transitions to "idle".
192 * 192 *
193 * At least one analysis result is produced for every file passed to 193 * At least one analysis result is produced for every file passed to
194 * [addFile] or [changeFile] prior to the next time the analysis state 194 * [addFile] or [changeFile] prior to the next time the analysis state
195 * transitions to "idle". Analysis results for other files are produced 195 * transitions to "idle". Analysis results for other files are produced
196 * only if the changes affect analysis results of other files. 196 * only if the changes affect analysis results of other files.
197 * 197 *
198 * More than one result might be produced for the same file, even if the 198 * More than one result might be produced for the same file, even if the
199 * client does not change the state of the files. 199 * client does not change the state of the files.
200 * 200 *
201 * Results might be produced even for files that have never been added 201 * Results might be produced even for files that have never been added
202 * using [addFile], for example when [getResult] was called for a file. 202 * using [addFile], for example when [getResult] was called for a file.
203 */ 203 */
204 Stream<AnalysisResult> get results async* { 204 Stream<AnalysisResult> get results async* {
205 try { 205 try {
206 PerformanceLogSection analysisSection = null;
206 while (true) { 207 while (true) {
207 // TODO(scheglov) implement state transitioning 208 // TODO(scheglov) implement state transitioning
208 await for (String why in _hasWorkStreamController.stream) { 209 await _hasWork.signal;
209 _verifyUnlinkedSignatureOfChangedFiles();
210 210
211 // Analyze the first file in the general queue. 211 if (analysisSection == null) {
212 if (_filesToAnalyze.isNotEmpty) { 212 analysisSection = _logger.enter('Analyzing');
213 PerformanceLogSection analysisSection =
214 _logger.enter('Analyze ${_filesToAnalyze.length} files');
215 try {
216 // TODO(scheglov) The loop is strange for now.
217 while (_filesToAnalyze.isNotEmpty) {
218 String path = _filesToAnalyze.first;
219 _filesToAnalyze.remove(path);
220 _File file = _fileForPath(path);
221 AnalysisResult result = _computeAnalysisResult(file);
222 yield result;
223 }
224 } finally {
225 analysisSection.exit();
226 }
227 }
228 } 213 }
229 // TODO(scheglov) implement 214
215 // TODO(scheglov) verify one file at a time
216 _verifyUnlinkedSignatureOfChangedFiles();
217
218 // Analyze the first file in the general queue.
219 if (_filesToAnalyze.isNotEmpty) {
220 String path = _filesToAnalyze.first;
221 _filesToAnalyze.remove(path);
222 _File file = _fileForPath(path);
223 AnalysisResult result = _computeAnalysisResult(file);
224 yield result;
225 }
226
227 // If there is work to do, notify the monitor.
228 if (_filesToAnalyze.isNotEmpty) {
229 _hasWork.notify();
230 } else {
231 analysisSection.exit();
232 analysisSection = null;
233 }
230 } 234 }
235 // TODO(scheglov) implement
231 } finally { 236 } finally {
232 print('The stream was cancelled.'); 237 print('The stream was cancelled.');
233 } 238 }
234 } 239 }
235 240
236 /** 241 /**
237 * Add the file with the given [path] to the set of files to analyze. 242 * Add the file with the given [path] to the set of files to analyze.
238 * 243 *
239 * The [path] must be absolute and normalized. 244 * The [path] must be absolute and normalized.
240 * 245 *
241 * The results of analysis are eventually produced by the [results] stream. 246 * The results of analysis are eventually produced by the [results] stream.
242 */ 247 */
243 void addFile(String path) { 248 void addFile(String path) {
244 _explicitFiles.add(path); 249 _explicitFiles.add(path);
245 _filesToAnalyze.add(path); 250 _filesToAnalyze.add(path);
246 _hasWorkStreamController.add('do it!'); 251 _hasWork.notify();
247 } 252 }
248 253
249 /** 254 /**
250 * The file with the given [path] might have changed - updated, added or 255 * The file with the given [path] might have changed - updated, added or
251 * removed. Or not, we don't know. Or it might have, but then changed back. 256 * removed. Or not, we don't know. Or it might have, but then changed back.
252 * 257 *
253 * The [path] must be absolute and normalized. 258 * The [path] must be absolute and normalized.
254 * 259 *
255 * The [path] can be any file - explicitly or implicitly analyzed, or neither. 260 * The [path] can be any file - explicitly or implicitly analyzed, or neither.
256 * 261 *
257 * Causes the analysis state to transition to "analyzing" (if it is not in 262 * Causes the analysis state to transition to "analyzing" (if it is not in
258 * that state already). Schedules the file contents for [path] to be read 263 * that state already). Schedules the file contents for [path] to be read
259 * into the current file state prior to the next time the analysis state 264 * into the current file state prior to the next time the analysis state
260 * transitions to "idle". 265 * transitions to "idle".
261 * 266 *
262 * Invocation of this method will not prevent a [Future] returned from 267 * Invocation of this method will not prevent a [Future] returned from
263 * [getResult] from completing with a result, but the result is not 268 * [getResult] from completing with a result, but the result is not
264 * guaranteed to be consistent with the new current file state after this 269 * guaranteed to be consistent with the new current file state after this
265 * [changeFile] invocation. 270 * [changeFile] invocation.
266 */ 271 */
267 void changeFile(String path) { 272 void changeFile(String path) {
268 _filesToVerifyUnlinkedSignature.add(path); 273 _filesToVerifyUnlinkedSignature.add(path);
269 _filesToAnalyze.add(path); 274 _filesToAnalyze.add(path);
270 _hasWorkStreamController.add('do it!'); 275 _hasWork.notify();
271 } 276 }
272 277
273 /** 278 /**
274 * Return the [Future] that completes with a [AnalysisResult] for the file 279 * Return the [Future] that completes with a [AnalysisResult] for the file
275 * with the given [path]. 280 * with the given [path].
276 * 281 *
277 * The [path] must be absolute and normalized. 282 * The [path] must be absolute and normalized.
278 * 283 *
279 * The [path] can be any file - explicitly or implicitly analyzed, or neither. 284 * The [path] can be any file - explicitly or implicitly analyzed, or neither.
280 * 285 *
281 * Causes the analysis state to transition to "analyzing" (if it is not in 286 * Causes the analysis state to transition to "analyzing" (if it is not in
282 * that state already), the driver will read the file and produce the analysis 287 * that state already), the driver will read the file and produce the analysis
283 * result for it, which is consistent with the current file state (including 288 * result for it, which is consistent with the current file state (including
284 * the new state of the file), prior to the next time the analysis state 289 * the new state of the file), prior to the next time the analysis state
285 * transitions to "idle". 290 * transitions to "idle".
286 */ 291 */
287 Future<AnalysisResult> getResult(String path) { 292 Future<AnalysisResult> getResult(String path) {
288 var completer = new Completer<AnalysisResult>(); 293 var completer = new Completer<AnalysisResult>();
289 _requestedFiles 294 _requestedFiles
290 .putIfAbsent(path, () => <Completer<AnalysisResult>>[]) 295 .putIfAbsent(path, () => <Completer<AnalysisResult>>[])
291 .add(completer); 296 .add(completer);
292 _hasWorkStreamController.add(path); 297 _hasWork.notify();
293 return completer.future; 298 return completer.future;
294 } 299 }
295 300
296 /** 301 /**
297 * Remove the file with the given [path] from the list of files to analyze. 302 * Remove the file with the given [path] from the list of files to analyze.
298 * 303 *
299 * The [path] must be absolute and normalized. 304 * The [path] must be absolute and normalized.
300 * 305 *
301 * The results of analysis of the file might still be produced by the 306 * The results of analysis of the file might still be produced by the
302 * [results] stream. The driver will try to stop producing these results, 307 * [results] stream. The driver will try to stop producing these results,
(...skipping 632 matching lines...) Expand 10 before | Expand all | Expand 10 after
935 940
936 appendDependencies(this); 941 appendDependencies(this);
937 } 942 }
938 } 943 }
939 944
940 @override 945 @override
941 String toString() => uri.toString(); 946 String toString() => uri.toString();
942 } 947 }
943 948
944 /** 949 /**
950 * [_Monitor] can be used to wait for a signal.
951 *
952 * Signals are not queued, the client will receive exactly one signal
953 * regardless of the number of [notify] invocations. The [signal] is reset
954 * after completion and will not complete until [notify] is called next time.
955 */
956 class _Monitor {
957 Completer<Null> _completer = new Completer<Null>();
958
959 /**
960 * Return a [Future] that completes when [notify] is called at least once.
961 */
962 Future<Null> get signal async {
963 await _completer.future;
964 _completer = new Completer<Null>();
965 }
966
967 /**
968 * Complete the [signal] future if it is not completed yet. It is safe to
969 * call this method multiple times, but the [signal] will complete only once.
970 */
971 void notify() {
972 if (!_completer.isCompleted) {
973 _completer.complete(true);
974 }
975 }
976 }
977
978 /**
945 * TODO(scheglov) document 979 * TODO(scheglov) document
946 */ 980 */
947 class _ReferencedUris { 981 class _ReferencedUris {
948 bool isLibrary = true; 982 bool isLibrary = true;
949 final List<String> imported = <String>[]; 983 final List<String> imported = <String>[];
950 final List<String> exported = <String>[]; 984 final List<String> exported = <String>[];
951 final List<String> parted = <String>[]; 985 final List<String> parted = <String>[];
952 986
953 factory _ReferencedUris(UnlinkedUnit unit) { 987 factory _ReferencedUris(UnlinkedUnit unit) {
954 _ReferencedUris referenced = new _ReferencedUris._(); 988 _ReferencedUris referenced = new _ReferencedUris._();
955 referenced.parted.addAll(unit.publicNamespace.parts); 989 referenced.parted.addAll(unit.publicNamespace.parts);
956 for (UnlinkedImport import in unit.imports) { 990 for (UnlinkedImport import in unit.imports) {
957 if (!import.isImplicit) { 991 if (!import.isImplicit) {
958 referenced.imported.add(import.uri); 992 referenced.imported.add(import.uri);
959 } 993 }
960 } 994 }
961 for (UnlinkedExportPublic export in unit.publicNamespace.exports) { 995 for (UnlinkedExportPublic export in unit.publicNamespace.exports) {
962 referenced.exported.add(export.uri); 996 referenced.exported.add(export.uri);
963 } 997 }
964 return referenced; 998 return referenced;
965 } 999 }
966 1000
967 _ReferencedUris._(); 1001 _ReferencedUris._();
968 } 1002 }
OLDNEW
« no previous file with comments | « no previous file | no next file » | no next file with comments »

Powered by Google App Engine
This is Rietveld 408576698