| OLD | NEW |
| 1 // Copyright (c) 2014, the Dart project authors. Please see the AUTHORS file | 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 | 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 library analysis.server; | 5 library analysis.server; |
| 6 | 6 |
| 7 import 'dart:async'; | 7 import 'dart:async'; |
| 8 import 'dart:collection'; | 8 import 'dart:collection'; |
| 9 import 'dart:core' hide Resource; | 9 import 'dart:core' hide Resource; |
| 10 import 'dart:math' show max; | 10 import 'dart:math' show max; |
| (...skipping 21 matching lines...) Expand all Loading... |
| 32 import 'package:analyzer/src/generated/ast.dart'; | 32 import 'package:analyzer/src/generated/ast.dart'; |
| 33 import 'package:analyzer/src/generated/engine.dart'; | 33 import 'package:analyzer/src/generated/engine.dart'; |
| 34 import 'package:analyzer/src/generated/java_engine.dart'; | 34 import 'package:analyzer/src/generated/java_engine.dart'; |
| 35 import 'package:analyzer/src/generated/java_io.dart'; | 35 import 'package:analyzer/src/generated/java_io.dart'; |
| 36 import 'package:analyzer/src/generated/sdk.dart'; | 36 import 'package:analyzer/src/generated/sdk.dart'; |
| 37 import 'package:analyzer/src/generated/source.dart'; | 37 import 'package:analyzer/src/generated/source.dart'; |
| 38 import 'package:analyzer/src/generated/source_io.dart'; | 38 import 'package:analyzer/src/generated/source_io.dart'; |
| 39 import 'package:analyzer/src/generated/utilities_general.dart'; | 39 import 'package:analyzer/src/generated/utilities_general.dart'; |
| 40 import 'package:analyzer/src/task/dart.dart'; | 40 import 'package:analyzer/src/task/dart.dart'; |
| 41 import 'package:analyzer/src/util/glob.dart'; | 41 import 'package:analyzer/src/util/glob.dart'; |
| 42 import 'package:analyzer/task/dart.dart'; |
| 42 import 'package:plugin/plugin.dart'; | 43 import 'package:plugin/plugin.dart'; |
| 43 | 44 |
| 44 typedef void OptionUpdater(AnalysisOptionsImpl options); | 45 typedef void OptionUpdater(AnalysisOptionsImpl options); |
| 45 | 46 |
| 46 /** | 47 /** |
| 47 * Enum representing reasons why analysis might be done for a given file. | 48 * Enum representing reasons why analysis might be done for a given file. |
| 48 */ | 49 */ |
| 49 class AnalysisDoneReason { | 50 class AnalysisDoneReason { |
| 50 /** | 51 /** |
| 51 * Analysis of the file completed successfully. | 52 * Analysis of the file completed successfully. |
| (...skipping 24 matching lines...) Expand all Loading... |
| 76 * The version of the analysis server. The value should be replaced | 77 * The version of the analysis server. The value should be replaced |
| 77 * automatically during the build. | 78 * automatically during the build. |
| 78 */ | 79 */ |
| 79 static final String VERSION = '1.15.0'; | 80 static final String VERSION = '1.15.0'; |
| 80 | 81 |
| 81 /** | 82 /** |
| 82 * The number of milliseconds to perform operations before inserting | 83 * The number of milliseconds to perform operations before inserting |
| 83 * a 1 millisecond delay so that the VM and dart:io can deliver content | 84 * a 1 millisecond delay so that the VM and dart:io can deliver content |
| 84 * to stdin. This should be removed once the underlying problem is fixed. | 85 * to stdin. This should be removed once the underlying problem is fixed. |
| 85 */ | 86 */ |
| 86 static int performOperationDelayFreqency = 25; | 87 static int performOperationDelayFrequency = 25; |
| 87 | 88 |
| 88 /** | 89 /** |
| 89 * The options of this server instance. | 90 * The options of this server instance. |
| 90 */ | 91 */ |
| 91 AnalysisServerOptions options; | 92 AnalysisServerOptions options; |
| 92 | 93 |
| 93 /** | 94 /** |
| 94 * The channel from which requests are received and to which responses should | 95 * The channel from which requests are received and to which responses should |
| 95 * be sent. | 96 * be sent. |
| 96 */ | 97 */ |
| (...skipping 250 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 347 _onFileAnalyzedController = new StreamController.broadcast(); | 348 _onFileAnalyzedController = new StreamController.broadcast(); |
| 348 _onPriorityChangeController = | 349 _onPriorityChangeController = |
| 349 new StreamController<PriorityChangeEvent>.broadcast(); | 350 new StreamController<PriorityChangeEvent>.broadcast(); |
| 350 running = true; | 351 running = true; |
| 351 onAnalysisStarted.first.then((_) { | 352 onAnalysisStarted.first.then((_) { |
| 352 onAnalysisComplete.then((_) { | 353 onAnalysisComplete.then((_) { |
| 353 performanceAfterStartup = new ServerPerformance(); | 354 performanceAfterStartup = new ServerPerformance(); |
| 354 _performance = performanceAfterStartup; | 355 _performance = performanceAfterStartup; |
| 355 }); | 356 }); |
| 356 }); | 357 }); |
| 358 _setupIndexInvalidation(); |
| 357 Notification notification = | 359 Notification notification = |
| 358 new ServerConnectedParams(VERSION).toNotification(); | 360 new ServerConnectedParams(VERSION).toNotification(); |
| 359 channel.sendNotification(notification); | 361 channel.sendNotification(notification); |
| 360 channel.listen(handleRequest, onDone: done, onError: error); | 362 channel.listen(handleRequest, onDone: done, onError: error); |
| 361 handlers = serverPlugin.createDomains(this); | 363 handlers = serverPlugin.createDomains(this); |
| 362 sdkManager = new DartSdkManager(defaultSdkCreator); | 364 sdkManager = new DartSdkManager(defaultSdkCreator); |
| 363 } | 365 } |
| 364 | 366 |
| 365 /** | 367 /** |
| 366 * Return the [AnalysisContext]s that are being used to analyze the analysis | 368 * Return the [AnalysisContext]s that are being used to analyze the analysis |
| (...skipping 301 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 668 Source source = contextSource.source; | 670 Source source = contextSource.source; |
| 669 if (context == null) { | 671 if (context == null) { |
| 670 return null; | 672 return null; |
| 671 } | 673 } |
| 672 if (!context.exists(source)) { | 674 if (!context.exists(source)) { |
| 673 return null; | 675 return null; |
| 674 } | 676 } |
| 675 return context.getErrors(source); | 677 return context.getErrors(source); |
| 676 } | 678 } |
| 677 | 679 |
| 678 // TODO(brianwilkerson) Add the following method after 'prioritySources' has | |
| 679 // been added to InternalAnalysisContext. | |
| 680 // /** | |
| 681 // * Return a list containing the full names of all of the sources that are | |
| 682 // * priority sources. | |
| 683 // */ | |
| 684 // List<String> getPriorityFiles() { | |
| 685 // List<String> priorityFiles = new List<String>(); | |
| 686 // folderMap.values.forEach((ContextDirectory directory) { | |
| 687 // InternalAnalysisContext context = directory.context; | |
| 688 // context.prioritySources.forEach((Source source) { | |
| 689 // priorityFiles.add(source.fullName); | |
| 690 // }); | |
| 691 // }); | |
| 692 // return priorityFiles; | |
| 693 // } | |
| 694 | |
| 695 /** | 680 /** |
| 696 * Returns resolved [AstNode]s at the given [offset] of the given [file]. | 681 * Returns resolved [AstNode]s at the given [offset] of the given [file]. |
| 697 * | 682 * |
| 698 * May be empty, but not `null`. | 683 * May be empty, but not `null`. |
| 699 */ | 684 */ |
| 700 List<AstNode> getNodesAtOffset(String file, int offset) { | 685 List<AstNode> getNodesAtOffset(String file, int offset) { |
| 701 List<CompilationUnit> units = getResolvedCompilationUnits(file); | 686 List<CompilationUnit> units = getResolvedCompilationUnits(file); |
| 702 List<AstNode> nodes = <AstNode>[]; | 687 List<AstNode> nodes = <AstNode>[]; |
| 703 for (CompilationUnit unit in units) { | 688 for (CompilationUnit unit in units) { |
| 704 AstNode node = new NodeLocator(offset).searchWithin(unit); | 689 AstNode node = new NodeLocator(offset).searchWithin(unit); |
| 705 if (node != null) { | 690 if (node != null) { |
| 706 nodes.add(node); | 691 nodes.add(node); |
| 707 } | 692 } |
| 708 } | 693 } |
| 709 return nodes; | 694 return nodes; |
| 710 } | 695 } |
| 711 | 696 |
| 697 // TODO(brianwilkerson) Add the following method after 'prioritySources' has |
| 698 // been added to InternalAnalysisContext. |
| 699 // /** |
| 700 // * Return a list containing the full names of all of the sources that are |
| 701 // * priority sources. |
| 702 // */ |
| 703 // List<String> getPriorityFiles() { |
| 704 // List<String> priorityFiles = new List<String>(); |
| 705 // folderMap.values.forEach((ContextDirectory directory) { |
| 706 // InternalAnalysisContext context = directory.context; |
| 707 // context.prioritySources.forEach((Source source) { |
| 708 // priorityFiles.add(source.fullName); |
| 709 // }); |
| 710 // }); |
| 711 // return priorityFiles; |
| 712 // } |
| 713 |
| 712 /** | 714 /** |
| 713 * Returns resolved [CompilationUnit]s of the Dart file with the given [path]. | 715 * Returns resolved [CompilationUnit]s of the Dart file with the given [path]. |
| 714 * | 716 * |
| 715 * May be empty, but not `null`. | 717 * May be empty, but not `null`. |
| 716 */ | 718 */ |
| 717 List<CompilationUnit> getResolvedCompilationUnits(String path) { | 719 List<CompilationUnit> getResolvedCompilationUnits(String path) { |
| 718 List<CompilationUnit> units = <CompilationUnit>[]; | 720 List<CompilationUnit> units = <CompilationUnit>[]; |
| 719 ContextSourcePair contextSource = getContextSourcePair(path); | 721 ContextSourcePair contextSource = getContextSourcePair(path); |
| 720 // prepare AnalysisContext | 722 // prepare AnalysisContext |
| 721 AnalysisContext context = contextSource.context; | 723 AnalysisContext context = contextSource.context; |
| (...skipping 723 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 1445 * is fixed. Currently, the VM and dart:io do not deliver content | 1447 * is fixed. Currently, the VM and dart:io do not deliver content |
| 1446 * on stdin in a timely manner if the event loop is busy. | 1448 * on stdin in a timely manner if the event loop is busy. |
| 1447 * To work around this problem, we delay for 1 millisecond | 1449 * To work around this problem, we delay for 1 millisecond |
| 1448 * every 25 milliseconds. | 1450 * every 25 milliseconds. |
| 1449 * | 1451 * |
| 1450 * To disable this workaround and see the underlying problem, | 1452 * To disable this workaround and see the underlying problem, |
| 1451 * set performOperationDelayFreqency to zero | 1453 * set performOperationDelayFreqency to zero |
| 1452 */ | 1454 */ |
| 1453 int now = new DateTime.now().millisecondsSinceEpoch; | 1455 int now = new DateTime.now().millisecondsSinceEpoch; |
| 1454 if (now > _nextPerformOperationDelayTime && | 1456 if (now > _nextPerformOperationDelayTime && |
| 1455 performOperationDelayFreqency > 0) { | 1457 performOperationDelayFrequency > 0) { |
| 1456 _nextPerformOperationDelayTime = now + performOperationDelayFreqency; | 1458 _nextPerformOperationDelayTime = now + performOperationDelayFrequency; |
| 1457 new Future.delayed(new Duration(milliseconds: 1), performOperation); | 1459 new Future.delayed(new Duration(milliseconds: 1), performOperation); |
| 1458 } else { | 1460 } else { |
| 1459 new Future(performOperation); | 1461 new Future(performOperation); |
| 1460 } | 1462 } |
| 1461 performOperationPending = true; | 1463 performOperationPending = true; |
| 1462 } | 1464 } |
| 1465 |
| 1466 /** |
| 1467 * Listen for context events and invalidate index. |
| 1468 * |
| 1469 * It is possible that this method will do more in the future, e.g. listening |
| 1470 * for summary information and linking pre-indexed packages into the index, |
| 1471 * but for now we only invalidate project specific index information. |
| 1472 */ |
| 1473 void _setupIndexInvalidation() { |
| 1474 if (index2 == null) { |
| 1475 return; |
| 1476 } |
| 1477 onContextsChanged.listen((ContextsChangedEvent event) { |
| 1478 for (AnalysisContext context in event.added) { |
| 1479 context |
| 1480 .onResultChanged(RESOLVED_UNIT) |
| 1481 .listen((ResultChangedEvent event) { |
| 1482 if (event.wasInvalidated) { |
| 1483 LibrarySpecificUnit target = event.target; |
| 1484 index2.removeUnit(event.context, target.library, target.unit); |
| 1485 } |
| 1486 }); |
| 1487 } |
| 1488 for (AnalysisContext context in event.removed) { |
| 1489 index2.removeContext(context); |
| 1490 } |
| 1491 }); |
| 1492 } |
| 1463 } | 1493 } |
| 1464 | 1494 |
| 1465 class AnalysisServerOptions { | 1495 class AnalysisServerOptions { |
| 1466 bool enableIncrementalResolutionApi = false; | 1496 bool enableIncrementalResolutionApi = false; |
| 1467 bool enableIncrementalResolutionValidation = false; | 1497 bool enableIncrementalResolutionValidation = false; |
| 1468 bool noErrorNotification = false; | 1498 bool noErrorNotification = false; |
| 1469 bool noIndex = false; | 1499 bool noIndex = false; |
| 1470 bool useAnalysisHighlight2 = false; | 1500 bool useAnalysisHighlight2 = false; |
| 1471 String fileReadMode = 'as-is'; | 1501 String fileReadMode = 'as-is'; |
| 1472 } | 1502 } |
| (...skipping 182 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 1655 * The maximum latency (milliseconds) for all recorded requests. | 1685 * The maximum latency (milliseconds) for all recorded requests. |
| 1656 */ | 1686 */ |
| 1657 int maxLatency = 0; | 1687 int maxLatency = 0; |
| 1658 | 1688 |
| 1659 /** | 1689 /** |
| 1660 * The number of requests with latency > 150 milliseconds. | 1690 * The number of requests with latency > 150 milliseconds. |
| 1661 */ | 1691 */ |
| 1662 int slowRequestCount = 0; | 1692 int slowRequestCount = 0; |
| 1663 | 1693 |
| 1664 /** | 1694 /** |
| 1665 * Log performation information about the given request. | 1695 * Log performance information about the given request. |
| 1666 */ | 1696 */ |
| 1667 void logRequest(Request request) { | 1697 void logRequest(Request request) { |
| 1668 ++requestCount; | 1698 ++requestCount; |
| 1669 if (request.clientRequestTime != null) { | 1699 if (request.clientRequestTime != null) { |
| 1670 int latency = | 1700 int latency = |
| 1671 new DateTime.now().millisecondsSinceEpoch - request.clientRequestTime; | 1701 new DateTime.now().millisecondsSinceEpoch - request.clientRequestTime; |
| 1672 requestLatency += latency; | 1702 requestLatency += latency; |
| 1673 maxLatency = max(maxLatency, latency); | 1703 maxLatency = max(maxLatency, latency); |
| 1674 if (latency > 150) { | 1704 if (latency > 150) { |
| 1675 ++slowRequestCount; | 1705 ++slowRequestCount; |
| (...skipping 48 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 1724 /** | 1754 /** |
| 1725 * The [PerformanceTag] for time spent in server request handlers. | 1755 * The [PerformanceTag] for time spent in server request handlers. |
| 1726 */ | 1756 */ |
| 1727 static PerformanceTag serverRequests = new PerformanceTag('serverRequests'); | 1757 static PerformanceTag serverRequests = new PerformanceTag('serverRequests'); |
| 1728 | 1758 |
| 1729 /** | 1759 /** |
| 1730 * The [PerformanceTag] for time spent in split store microtasks. | 1760 * The [PerformanceTag] for time spent in split store microtasks. |
| 1731 */ | 1761 */ |
| 1732 static PerformanceTag splitStore = new PerformanceTag('splitStore'); | 1762 static PerformanceTag splitStore = new PerformanceTag('splitStore'); |
| 1733 } | 1763 } |
| OLD | NEW |