From 0a828c749723f5752dbaf055a599536e57c2bc3c Mon Sep 17 00:00:00 2001 From: pq Date: Tue, 29 Oct 2019 13:50:27 +0000 Subject: [PATCH] context workspace caching Change-Id: Ia0c5a4446e79f48b2cbd76d84e503b03751d5b76 Reviewed-on: https://dart-review.googlesource.com/c/sdk/+/123326 Commit-Queue: Phil Quitslund Reviewed-by: Brian Wilkerson --- .../lib/dart/analysis/analysis_context.dart | 4 +++ .../driver_based_analysis_context.dart | 19 +++++++++++++ .../src/dart/analysis/library_analyzer.dart | 27 +++++++++++++------ pkg/analyzer/lib/src/generated/resolver.dart | 21 +++++++++++---- 4 files changed, 58 insertions(+), 13 deletions(-) diff --git a/pkg/analyzer/lib/dart/analysis/analysis_context.dart b/pkg/analyzer/lib/dart/analysis/analysis_context.dart index 3a77423b0e47..f4258ca2958f 100644 --- a/pkg/analyzer/lib/dart/analysis/analysis_context.dart +++ b/pkg/analyzer/lib/dart/analysis/analysis_context.dart @@ -5,6 +5,7 @@ import 'package:analyzer/dart/analysis/context_root.dart'; import 'package:analyzer/dart/analysis/session.dart'; import 'package:analyzer/src/generated/engine.dart'; +import 'package:analyzer/src/workspace/workspace.dart'; /// A representation of a body of code and the context in which the code is to /// be analyzed. @@ -44,6 +45,9 @@ abstract class AnalysisContext { @deprecated List get includedPaths; + /// Return the workspace for containing the context root. + Workspace get workspace; + /// Return the absolute, normalized paths of all of the files that are /// contained in this context. These are all of the files that are included /// directly or indirectly by one or more of the [includedPaths] and that are diff --git a/pkg/analyzer/lib/src/dart/analysis/driver_based_analysis_context.dart b/pkg/analyzer/lib/src/dart/analysis/driver_based_analysis_context.dart index 6d35e0ec975c..1ca44d2d7b26 100644 --- a/pkg/analyzer/lib/src/dart/analysis/driver_based_analysis_context.dart +++ b/pkg/analyzer/lib/src/dart/analysis/driver_based_analysis_context.dart @@ -6,8 +6,10 @@ import 'package:analyzer/dart/analysis/analysis_context.dart'; import 'package:analyzer/dart/analysis/context_root.dart'; import 'package:analyzer/dart/analysis/session.dart'; import 'package:analyzer/file_system/file_system.dart'; +import 'package:analyzer/src/context/builder.dart'; import 'package:analyzer/src/dart/analysis/driver.dart' show AnalysisDriver; import 'package:analyzer/src/generated/engine.dart' show AnalysisOptions; +import 'package:analyzer/src/workspace/workspace.dart'; /** * An analysis context whose implementation is based on an analysis driver. @@ -26,6 +28,11 @@ class DriverBasedAnalysisContext implements AnalysisContext { */ final AnalysisDriver driver; + /** + * The [Workspace] for this context, `null` if not yet created. + */ + Workspace _workspace; + /** * Initialize a newly created context that uses the given [resourceProvider] * to access the file system and that is based on the given analysis [driver]. @@ -49,6 +56,11 @@ class DriverBasedAnalysisContext implements AnalysisContext { @override List get includedPaths => contextRoot.includedPaths.toList(); + @override + Workspace get workspace { + return _workspace ??= _buildWorkspace(); + } + @deprecated @override Iterable analyzedFiles() { @@ -60,4 +72,11 @@ class DriverBasedAnalysisContext implements AnalysisContext { bool isAnalyzed(String path) { return contextRoot.isAnalyzed(path); } + + Workspace _buildWorkspace() { + String path = contextRoot.root.path; + ContextBuilder builder = ContextBuilder( + resourceProvider, null /* sdkManager */, null /* contentCache */); + return ContextBuilder.createWorkspace(resourceProvider, path, builder); + } } diff --git a/pkg/analyzer/lib/src/dart/analysis/library_analyzer.dart b/pkg/analyzer/lib/src/dart/analysis/library_analyzer.dart index 3cf2317a92d9..527a5a20f5ac 100644 --- a/pkg/analyzer/lib/src/dart/analysis/library_analyzer.dart +++ b/pkg/analyzer/lib/src/dart/analysis/library_analyzer.dart @@ -42,6 +42,7 @@ import 'package:analyzer/src/lint/linter_visitor.dart'; import 'package:analyzer/src/services/lint.dart'; import 'package:analyzer/src/summary2/linked_element_factory.dart'; import 'package:analyzer/src/task/strong/checker.dart'; +import 'package:analyzer/src/workspace/workspace.dart'; import 'package:pub_semver/pub_semver.dart'; var timerLibraryAnalyzer = Stopwatch(); @@ -323,14 +324,7 @@ class LibraryAnalyzer { var nodeRegistry = new NodeLintRegistry(_analysisOptions.enableTiming); var visitors = []; - // todo (pq): duplicates logic in resolver; de-dup, or... - // todo (pq): get workspace from analysis context - final libraryPath = _library.source.fullName; - final builder = new ContextBuilder( - _resourceProvider, null /* sdkManager */, null /* contentCache */); - final workspace = - ContextBuilder.createWorkspace(_resourceProvider, libraryPath, builder); - final workspacePackage = workspace.findPackageFor(libraryPath); + final workspacePackage = _getPackage(currentUnit.unit); var context = LinterContextImpl( allUnits, @@ -465,6 +459,23 @@ class LibraryAnalyzer { }); } + WorkspacePackage _getPackage(CompilationUnit unit) { + final libraryPath = _library.source.fullName; + Workspace workspace = + unit.declaredElement.session?.analysisContext?.workspace; + + // If there is no driver setup (as in test environments), we need to create + // a workspace ourselves. + // todo (pq): fix tests or otherwise de-dup this logic shared w/ resolver. + if (workspace == null) { + final builder = ContextBuilder( + _resourceProvider, null /* sdkManager */, null /* contentCache */); + workspace = ContextBuilder.createWorkspace( + _resourceProvider, libraryPath, builder); + } + return workspace?.findPackageFor(libraryPath); + } + /** * Return the name of the library that the given part is declared to be a * part of, or `null` if the part does not contain a part-of directive. diff --git a/pkg/analyzer/lib/src/generated/resolver.dart b/pkg/analyzer/lib/src/generated/resolver.dart index 1b8ae8228d39..a1ca7d9f4a55 100644 --- a/pkg/analyzer/lib/src/generated/resolver.dart +++ b/pkg/analyzer/lib/src/generated/resolver.dart @@ -118,11 +118,8 @@ class BestPracticesVerifier extends RecursiveAstVisitor { new _InvalidAccessVerifier(_errorReporter, _currentLibrary) { _inDeprecatedMember = _currentLibrary.hasDeprecated; String libraryPath = _currentLibrary.source.fullName; - ContextBuilder builder = new ContextBuilder( - resourceProvider, null /* sdkManager */, null /* contentCache */); - Workspace workspace = - ContextBuilder.createWorkspace(resourceProvider, libraryPath, builder); - _workspacePackage = workspace.findPackageFor(libraryPath); + _workspacePackage = _getPackage(libraryPath, resourceProvider); + _linterContext = LinterContextImpl( null /* allUnits */, new LinterContextUnit(content, unit), @@ -1335,6 +1332,20 @@ class BestPracticesVerifier extends RecursiveAstVisitor { } } + WorkspacePackage _getPackage(String root, ResourceProvider resourceProvider) { + Workspace workspace = _currentLibrary.session?.analysisContext?.workspace; + // If there is no driver setup (as in test environments), we need to create + // a workspace ourselves. + // todo (pq): fix tests or otherwise de-dup this logic shared w/ library_analyzer. + if (workspace == null) { + final builder = ContextBuilder( + resourceProvider, null /* sdkManager */, null /* contentCache */); + workspace = + ContextBuilder.createWorkspace(resourceProvider, root, builder); + } + return workspace?.findPackageFor(root); + } + bool _isLibraryInWorkspacePackage(LibraryElement library) { if (_workspacePackage == null || library == null) { // Better to not make a big claim that they _are_ in the same package,