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

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

Issue 2742343006: Formalizing the hacks letting the angular analyzer plugin run for now. (Closed)
Patch Set: Rename variable not method Created 3 years, 9 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
« no previous file with comments | « pkg/analyzer/lib/src/context/builder.dart ('k') | 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:typed_data'; 7 import 'dart:typed_data';
8 8
9 import 'package:analyzer/context/declared_variables.dart'; 9 import 'package:analyzer/context/declared_variables.dart';
10 import 'package:analyzer/dart/ast/ast.dart'; 10 import 'package:analyzer/dart/ast/ast.dart';
(...skipping 50 matching lines...) Expand 10 before | Expand all | Expand 10 after
61 * and [removeFile], the analysis state will eventually transition back to 61 * and [removeFile], the analysis state will eventually transition back to
62 * "idle" after a finite amount of processing. 62 * "idle" after a finite amount of processing.
63 * 63 *
64 * As a result of these guarantees, a client may ensure that the analysis 64 * As a result of these guarantees, a client may ensure that the analysis
65 * results are "eventually consistent" with the file system by simply calling 65 * results are "eventually consistent" with the file system by simply calling
66 * [changeFile] any time the contents of a file on the file system have changed. 66 * [changeFile] any time the contents of a file on the file system have changed.
67 * 67 *
68 * 68 *
69 * TODO(scheglov) Clean up the list of implicitly analyzed files. 69 * TODO(scheglov) Clean up the list of implicitly analyzed files.
70 */ 70 */
71 class AnalysisDriver { 71 class AnalysisDriver implements AnalysisDriverGeneric {
72 /** 72 /**
73 * The version of data format, should be incremented on every format change. 73 * The version of data format, should be incremented on every format change.
74 */ 74 */
75 static const int DATA_VERSION = 25; 75 static const int DATA_VERSION = 25;
76 76
77 /** 77 /**
78 * The number of exception contexts allowed to write. Once this field is 78 * The number of exception contexts allowed to write. Once this field is
79 * zero, we stop writing any new exception contexts in this process. 79 * zero, we stop writing any new exception contexts in this process.
80 */ 80 */
81 static int allowedNumberOfContextsToWrite = 10; 81 static int allowedNumberOfContextsToWrite = 10;
(...skipping 169 matching lines...) Expand 10 before | Expand all | Expand 10 after
251 this.name, 251 this.name,
252 SourceFactory sourceFactory, 252 SourceFactory sourceFactory,
253 this._analysisOptions, 253 this._analysisOptions,
254 {PackageBundle sdkBundle, 254 {PackageBundle sdkBundle,
255 this.analyzeWithoutTasks: true}) 255 this.analyzeWithoutTasks: true})
256 : _logger = logger, 256 : _logger = logger,
257 _sourceFactory = sourceFactory.clone(), 257 _sourceFactory = sourceFactory.clone(),
258 _sdkBundle = sdkBundle { 258 _sdkBundle = sdkBundle {
259 _testView = new AnalysisDriverTestView(this); 259 _testView = new AnalysisDriverTestView(this);
260 _createFileTracker(logger); 260 _createFileTracker(logger);
261 _scheduler._add(this); 261 _scheduler.add(this);
262 _search = new Search(this); 262 _search = new Search(this);
263 } 263 }
264 264
265 /** 265 /**
266 * Return the set of files explicitly added to analysis using [addFile]. 266 * Return the set of files explicitly added to analysis using [addFile].
267 */ 267 */
268 Set<String> get addedFiles => _fileTracker.addedFiles; 268 Set<String> get addedFiles => _fileTracker.addedFiles;
269 269
270 /** 270 /**
271 * Return the analysis options used to control analysis. 271 * Return the analysis options used to control analysis.
(...skipping 91 matching lines...) Expand 10 before | Expand all | Expand 10 after
363 * from file paths. 363 * from file paths.
364 */ 364 */
365 SourceFactory get sourceFactory => _sourceFactory; 365 SourceFactory get sourceFactory => _sourceFactory;
366 366
367 @visibleForTesting 367 @visibleForTesting
368 AnalysisDriverTestView get test => _testView; 368 AnalysisDriverTestView get test => _testView;
369 369
370 /** 370 /**
371 * Return the priority of work that the driver needs to perform. 371 * Return the priority of work that the driver needs to perform.
372 */ 372 */
373 AnalysisDriverPriority get _workPriority { 373 AnalysisDriverPriority get workPriority {
374 if (_requestedFiles.isNotEmpty) { 374 if (_requestedFiles.isNotEmpty) {
375 return AnalysisDriverPriority.interactive; 375 return AnalysisDriverPriority.interactive;
376 } 376 }
377 if (_definingClassMemberNameTasks.isNotEmpty || 377 if (_definingClassMemberNameTasks.isNotEmpty ||
378 _referencingNameTasks.isNotEmpty) { 378 _referencingNameTasks.isNotEmpty) {
379 return AnalysisDriverPriority.interactive; 379 return AnalysisDriverPriority.interactive;
380 } 380 }
381 if (_indexRequestedFiles.isNotEmpty) { 381 if (_indexRequestedFiles.isNotEmpty) {
382 return AnalysisDriverPriority.interactive; 382 return AnalysisDriverPriority.interactive;
383 } 383 }
(...skipping 542 matching lines...) Expand 10 before | Expand all | Expand 10 after
926 * in the [library], e.g. element model, errors, index, etc. 926 * in the [library], e.g. element model, errors, index, etc.
927 */ 927 */
928 String _getResolvedUnitSignature(FileState library, FileState file) { 928 String _getResolvedUnitSignature(FileState library, FileState file) {
929 ApiSignature signature = new ApiSignature(); 929 ApiSignature signature = new ApiSignature();
930 signature.addUint32List(_salt); 930 signature.addUint32List(_salt);
931 signature.addString(library.transitiveSignature); 931 signature.addString(library.transitiveSignature);
932 signature.addString(file.contentHash); 932 signature.addString(file.contentHash);
933 return signature.toHex(); 933 return signature.toHex();
934 } 934 }
935 935
936 ApiSignature getUnitKeyByPath(String path) {
937 var file = fsState.getFileForPath(path);
938 ApiSignature signature = new ApiSignature();
939 signature.addUint32List(_salt);
940 signature.addString(file.transitiveSignature);
941 return signature;
942 }
943
944 ApiSignature getResolvedUnitKeyByPath(String path) {
945 ApiSignature signature = getUnitKeyByPath(path);
946 var file = fsState.getFileForPath(path);
947 signature.addString(file.contentHash);
948 return signature;
949 }
950
936 /** 951 /**
937 * Return the lint code with the given [errorName], or `null` if there is no 952 * Return the lint code with the given [errorName], or `null` if there is no
938 * lint registered with that name or the lint is not enabled in the analysis 953 * lint registered with that name or the lint is not enabled in the analysis
939 * options. 954 * options.
940 */ 955 */
941 ErrorCode _lintCodeByUniqueName(String errorName) { 956 ErrorCode _lintCodeByUniqueName(String errorName) {
942 if (errorName.startsWith('_LintCode.')) { 957 if (errorName.startsWith('_LintCode.')) {
943 String lintName = errorName.substring(10); 958 String lintName = errorName.substring(10);
944 List<Linter> lintRules = _analysisOptions.lintRules; 959 List<Linter> lintRules = _analysisOptions.lintRules;
945 for (Linter linter in lintRules) { 960 for (Linter linter in lintRules) {
946 if (linter.name == lintName) { 961 if (linter.name == lintName) {
947 return linter.lintCode; 962 return linter.lintCode;
948 } 963 }
949 } 964 }
950 } 965 }
951 return null; 966 return null;
952 } 967 }
953 968
954 /** 969 /**
955 * Perform a single chunk of work and produce [results]. 970 * Perform a single chunk of work and produce [results].
956 */ 971 */
957 Future<Null> _performWork() async { 972 Future<Null> performWork() async {
958 if (_fileTracker.verifyChangedFilesIfNeeded()) { 973 if (_fileTracker.verifyChangedFilesIfNeeded()) {
959 return; 974 return;
960 } 975 }
961 976
962 // Analyze a requested file. 977 // Analyze a requested file.
963 if (_requestedFiles.isNotEmpty) { 978 if (_requestedFiles.isNotEmpty) {
964 String path = _requestedFiles.keys.first; 979 String path = _requestedFiles.keys.first;
965 try { 980 try {
966 AnalysisResult result = _computeAnalysisResult(path, withUnit: true); 981 AnalysisResult result = _computeAnalysisResult(path, withUnit: true);
967 // If a part without a library, delay its analysis. 982 // If a part without a library, delay its analysis.
(...skipping 238 matching lines...) Expand 10 before | Expand all | Expand 10 after
1206 1221
1207 _byteStore.put(key, bytes); 1222 _byteStore.put(key, bytes);
1208 return key; 1223 return key;
1209 } catch (_) { 1224 } catch (_) {
1210 return null; 1225 return null;
1211 } 1226 }
1212 } 1227 }
1213 } 1228 }
1214 1229
1215 /** 1230 /**
1231 * A generic schedulable interface via the AnalysisDriverScheduler. Currently
1232 * only implemented by [AnalysisDriver] and the angular plugin, at least as
1233 * a temporary measure until the official plugin API is ready (and a different
1234 * scheduler is used)
1235 */
1236 abstract class AnalysisDriverGeneric {
1237 bool get hasFilesToAnalyze;
1238 AnalysisDriverPriority get workPriority;
1239 Future<Null> performWork();
1240 }
1241
1242 /**
1216 * Priorities of [AnalysisDriver] work. The farther a priority to the beginning 1243 * Priorities of [AnalysisDriver] work. The farther a priority to the beginning
1217 * of the list, the earlier the corresponding [AnalysisDriver] should be asked 1244 * of the list, the earlier the corresponding [AnalysisDriver] should be asked
1218 * to perform work. 1245 * to perform work.
1219 */ 1246 */
1220 enum AnalysisDriverPriority { nothing, general, priority, interactive } 1247 enum AnalysisDriverPriority { nothing, general, priority, interactive }
1221 1248
1222 /** 1249 /**
1223 * Instances of this class schedule work in multiple [AnalysisDriver]s so that 1250 * Instances of this class schedule work in multiple [AnalysisDriver]s so that
1224 * work with the highest priority is performed first. 1251 * work with the highest priority is performed first.
1225 */ 1252 */
(...skipping 13 matching lines...) Expand all
1239 * be able to process `updateContent` or `setPriorityFiles` requests while 1266 * be able to process `updateContent` or `setPriorityFiles` requests while
1240 * background analysis is in progress. 1267 * background analysis is in progress.
1241 * 1268 *
1242 * The number of pumpings is arbitrary, might be changed if we see that 1269 * The number of pumpings is arbitrary, might be changed if we see that
1243 * analysis or other data processing tasks are starving. Ideally we would 1270 * analysis or other data processing tasks are starving. Ideally we would
1244 * need to run all asynchronous operations using a single global scheduler. 1271 * need to run all asynchronous operations using a single global scheduler.
1245 */ 1272 */
1246 static const int _NUMBER_OF_EVENT_QUEUE_PUMPINGS = 128; 1273 static const int _NUMBER_OF_EVENT_QUEUE_PUMPINGS = 128;
1247 1274
1248 final PerformanceLog _logger; 1275 final PerformanceLog _logger;
1249 final List<AnalysisDriver> _drivers = []; 1276 final List<AnalysisDriverGeneric> _drivers = [];
1250 final Monitor _hasWork = new Monitor(); 1277 final Monitor _hasWork = new Monitor();
1251 final StatusSupport _statusSupport = new StatusSupport(); 1278 final StatusSupport _statusSupport = new StatusSupport();
1252 1279
1253 bool _started = false; 1280 bool _started = false;
1254 1281
1255 AnalysisDriverScheduler(this._logger); 1282 AnalysisDriverScheduler(this._logger);
1256 1283
1257 /** 1284 /**
1258 * Return `true` if we are currently analyzing code. 1285 * Return `true` if we are currently analyzing code.
1259 */ 1286 */
1260 bool get isAnalyzing => _hasFilesToAnalyze; 1287 bool get isAnalyzing => _hasFilesToAnalyze;
1261 1288
1262 /** 1289 /**
1263 * Return the stream that produces [AnalysisStatus] events. 1290 * Return the stream that produces [AnalysisStatus] events.
1264 */ 1291 */
1265 Stream<AnalysisStatus> get status => _statusSupport.stream; 1292 Stream<AnalysisStatus> get status => _statusSupport.stream;
1266 1293
1267 /** 1294 /**
1268 * Return `true` if there is a driver with a file to analyze. 1295 * Return `true` if there is a driver with a file to analyze.
1269 */ 1296 */
1270 bool get _hasFilesToAnalyze { 1297 bool get _hasFilesToAnalyze {
1271 for (AnalysisDriver driver in _drivers) { 1298 for (AnalysisDriverGeneric driver in _drivers) {
1272 if (driver.hasFilesToAnalyze) { 1299 if (driver.hasFilesToAnalyze) {
1273 return true; 1300 return true;
1274 } 1301 }
1275 } 1302 }
1276 return false; 1303 return false;
1277 } 1304 }
1278 1305
1279 /** 1306 /**
1280 * Notify that there is a change to the [driver], it it might need to 1307 * Notify that there is a change to the [driver], it it might need to
1281 * perform some work. 1308 * perform some work.
1282 */ 1309 */
1283 void notify(AnalysisDriver driver) { 1310 void notify(AnalysisDriverGeneric driver) {
1284 _hasWork.notify(); 1311 _hasWork.notify();
1285 _statusSupport.preTransitionToAnalyzing(); 1312 _statusSupport.preTransitionToAnalyzing();
1286 } 1313 }
1287 1314
1288 /** 1315 /**
1289 * Start the scheduler, so that any [AnalysisDriver] created before or 1316 * Start the scheduler, so that any [AnalysisDriver] created before or
1290 * after will be asked to perform work. 1317 * after will be asked to perform work.
1291 */ 1318 */
1292 void start() { 1319 void start() {
1293 if (_started) { 1320 if (_started) {
1294 throw new StateError('The scheduler has already been started.'); 1321 throw new StateError('The scheduler has already been started.');
1295 } 1322 }
1296 _started = true; 1323 _started = true;
1297 _run(); 1324 _run();
1298 } 1325 }
1299 1326
1300 /** 1327 /**
1301 * Return a future that will be completed the next time the status is idle. 1328 * Return a future that will be completed the next time the status is idle.
1302 * 1329 *
1303 * If the status is currently idle, the returned future will be signaled 1330 * If the status is currently idle, the returned future will be signaled
1304 * immediately. 1331 * immediately.
1305 */ 1332 */
1306 Future<Null> waitForIdle() => _statusSupport.waitForIdle(); 1333 Future<Null> waitForIdle() => _statusSupport.waitForIdle();
1307 1334
1308 /** 1335 /**
1309 * Add the given [driver] and schedule it to perform its work. 1336 * Add the given [driver] and schedule it to perform its work.
1310 */ 1337 */
1311 void _add(AnalysisDriver driver) { 1338 void add(AnalysisDriverGeneric driver) {
1312 _drivers.add(driver); 1339 _drivers.add(driver);
1313 _hasWork.notify(); 1340 _hasWork.notify();
1314 } 1341 }
1315 1342
1316 /** 1343 /**
1317 * Remove the given [driver] from the scheduler, so that it will not be 1344 * Remove the given [driver] from the scheduler, so that it will not be
1318 * asked to perform any new work. 1345 * asked to perform any new work.
1319 */ 1346 */
1320 void _remove(AnalysisDriver driver) { 1347 void _remove(AnalysisDriverGeneric driver) {
1321 _drivers.remove(driver); 1348 _drivers.remove(driver);
1322 _hasWork.notify(); 1349 _hasWork.notify();
1323 } 1350 }
1324 1351
1325 /** 1352 /**
1326 * Run infinitely analysis cycle, selecting the drivers with the highest 1353 * Run infinitely analysis cycle, selecting the drivers with the highest
1327 * priority first. 1354 * priority first.
1328 */ 1355 */
1329 Future<Null> _run() async { 1356 Future<Null> _run() async {
1330 Stopwatch timer = new Stopwatch()..start(); 1357 Stopwatch timer = new Stopwatch()..start();
1331 PerformanceLogSection analysisSection; 1358 PerformanceLogSection analysisSection;
1332 while (true) { 1359 while (true) {
1333 // Pump the event queue. 1360 // Pump the event queue.
1334 if (timer.elapsedMilliseconds > _MS_BEFORE_PUMPING_EVENT_QUEUE) { 1361 if (timer.elapsedMilliseconds > _MS_BEFORE_PUMPING_EVENT_QUEUE) {
1335 await _pumpEventQueue(_NUMBER_OF_EVENT_QUEUE_PUMPINGS); 1362 await _pumpEventQueue(_NUMBER_OF_EVENT_QUEUE_PUMPINGS);
1336 timer.reset(); 1363 timer.reset();
1337 } 1364 }
1338 1365
1339 await _hasWork.signal; 1366 await _hasWork.signal;
1340 1367
1341 // Transition to analyzing if there are files to analyze. 1368 // Transition to analyzing if there are files to analyze.
1342 if (_hasFilesToAnalyze) { 1369 if (_hasFilesToAnalyze) {
1343 _statusSupport.transitionToAnalyzing(); 1370 _statusSupport.transitionToAnalyzing();
1344 analysisSection ??= _logger.enter('Analyzing'); 1371 analysisSection ??= _logger.enter('Analyzing');
1345 } 1372 }
1346 1373
1347 // Find the driver with the highest priority. 1374 // Find the driver with the highest priority.
1348 AnalysisDriver bestDriver; 1375 AnalysisDriverGeneric bestDriver;
1349 AnalysisDriverPriority bestPriority = AnalysisDriverPriority.nothing; 1376 AnalysisDriverPriority bestPriority = AnalysisDriverPriority.nothing;
1350 for (AnalysisDriver driver in _drivers) { 1377 for (AnalysisDriver driver in _drivers) {
1351 AnalysisDriverPriority priority = driver._workPriority; 1378 AnalysisDriverPriority priority = driver.workPriority;
1352 if (priority.index > bestPriority.index) { 1379 if (priority.index > bestPriority.index) {
1353 bestDriver = driver; 1380 bestDriver = driver;
1354 bestPriority = priority; 1381 bestPriority = priority;
1355 } 1382 }
1356 } 1383 }
1357 1384
1358 // Transition to idle if no files to analyze. 1385 // Transition to idle if no files to analyze.
1359 if (!_hasFilesToAnalyze) { 1386 if (!_hasFilesToAnalyze) {
1360 _statusSupport.transitionToIdle(); 1387 _statusSupport.transitionToIdle();
1361 analysisSection?.exit(); 1388 analysisSection?.exit();
1362 analysisSection = null; 1389 analysisSection = null;
1363 } 1390 }
1364 1391
1365 // Continue to sleep if no work to do. 1392 // Continue to sleep if no work to do.
1366 if (bestPriority == AnalysisDriverPriority.nothing) { 1393 if (bestPriority == AnalysisDriverPriority.nothing) {
1367 continue; 1394 continue;
1368 } 1395 }
1369 1396
1370 // Ask the driver to perform a chunk of work. 1397 // Ask the driver to perform a chunk of work.
1371 await bestDriver._performWork(); 1398 await bestDriver.performWork();
1372 1399
1373 // Schedule one more cycle. 1400 // Schedule one more cycle.
1374 _hasWork.notify(); 1401 _hasWork.notify();
1375 } 1402 }
1376 } 1403 }
1377 1404
1378 /** 1405 /**
1379 * Returns a [Future] that completes after performing [times] pumpings of 1406 * Returns a [Future] that completes after performing [times] pumpings of
1380 * the event queue. 1407 * the event queue.
1381 */ 1408 */
(...skipping 519 matching lines...) Expand 10 before | Expand all | Expand 10 after
1901 libraryDeclarations.add(new TopLevelDeclarationInSource( 1928 libraryDeclarations.add(new TopLevelDeclarationInSource(
1902 file.source, declaration, isExported)); 1929 file.source, declaration, isExported));
1903 } 1930 }
1904 } 1931 }
1905 } 1932 }
1906 1933
1907 // We're not done yet. 1934 // We're not done yet.
1908 return false; 1935 return false;
1909 } 1936 }
1910 } 1937 }
OLDNEW
« no previous file with comments | « pkg/analyzer/lib/src/context/builder.dart ('k') | no next file » | no next file with comments »

Powered by Google App Engine
This is Rietveld 408576698