Initial API to build analysis contexts (replaces ContextLocator.locateContexts)
Change-Id: If00ce6321efb6ff4da96e654cfe2a0a8501bed95 Reviewed-on: https://dart-review.googlesource.com/50323 Commit-Queue: Brian Wilkerson <brianwilkerson@google.com> Reviewed-by: Konstantin Shcheglov <scheglov@google.com>
This commit is contained in:
committed by
commit-bot@chromium.org
parent
5ea271bb01
commit
7764e6962e
@@ -0,0 +1,42 @@
|
||||
// Copyright (c) 2018, the Dart project authors. Please see the AUTHORS file
|
||||
// for details. All rights reserved. Use of this source code is governed by a
|
||||
// BSD-style license that can be found in the LICENSE file.
|
||||
|
||||
import 'package:analyzer/context/declared_variables.dart';
|
||||
import 'package:analyzer/dart/analysis/analysis_context.dart';
|
||||
import 'package:analyzer/dart/analysis/context_root.dart';
|
||||
import 'package:analyzer/file_system/file_system.dart';
|
||||
import 'package:analyzer/src/dart/analysis/context_builder.dart';
|
||||
import 'package:meta/meta.dart';
|
||||
|
||||
/**
|
||||
* A utility class used to build an analysis context based on a context root.
|
||||
*
|
||||
* Clients may not extend, implement or mix-in this class.
|
||||
*/
|
||||
abstract class ContextBuilder {
|
||||
/**
|
||||
* Initialize a newly created context builder. If a [resourceProvider] is
|
||||
* given, then it will be used to access the file system, otherwise the
|
||||
* default resource provider will be used.
|
||||
*/
|
||||
factory ContextBuilder({ResourceProvider resourceProvider}) =
|
||||
ContextBuilderImpl;
|
||||
|
||||
/**
|
||||
* Return an analysis context corresponding to the given [contextRoot].
|
||||
*
|
||||
* If a set of [declaredVariables] is provided, the values will be used to map
|
||||
* the the variable names found in `fromEnvironment` invocations to the
|
||||
* constant value that will be returned. If none is given, then no variables
|
||||
* will be defined.
|
||||
*
|
||||
* If an [sdkPath] is provided, and if it is a valid path to a directory
|
||||
* containing a valid SDK, then the SDK in the referenced directory will be
|
||||
* used when analyzing the code in the context.
|
||||
*/
|
||||
AnalysisContext createContext(
|
||||
{@required ContextRoot contextRoot,
|
||||
DeclaredVariables declaredVariables,
|
||||
String sdkPath});
|
||||
}
|
||||
@@ -0,0 +1,101 @@
|
||||
// Copyright (c) 2018, the Dart project authors. Please see the AUTHORS file
|
||||
// for details. All rights reserved. Use of this source code is governed by a
|
||||
// BSD-style license that can be found in the LICENSE file.
|
||||
|
||||
import 'package:analyzer/context/context_root.dart' as old;
|
||||
import 'package:analyzer/context/declared_variables.dart';
|
||||
import 'package:analyzer/dart/analysis/analysis_context.dart';
|
||||
import 'package:analyzer/dart/analysis/context_builder.dart';
|
||||
import 'package:analyzer/dart/analysis/context_root.dart';
|
||||
import 'package:analyzer/file_system/file_system.dart';
|
||||
import 'package:analyzer/file_system/physical_file_system.dart';
|
||||
import 'package:analyzer/src/context/builder.dart' as old
|
||||
show ContextBuilder, ContextBuilderOptions;
|
||||
import 'package:analyzer/src/dart/analysis/driver.dart'
|
||||
show AnalysisDriver, AnalysisDriverScheduler;
|
||||
import 'package:analyzer/src/dart/analysis/driver_based_analysis_context.dart';
|
||||
import 'package:analyzer/src/dart/analysis/file_state.dart'
|
||||
show FileContentOverlay;
|
||||
import 'package:analyzer/src/dart/sdk/sdk.dart';
|
||||
import 'package:analyzer/src/generated/sdk.dart' show DartSdkManager;
|
||||
import 'package:analyzer/src/generated/source.dart' show ContentCache;
|
||||
import 'package:front_end/src/base/performance_logger.dart' show PerformanceLog;
|
||||
import 'package:front_end/src/byte_store/byte_store.dart' show MemoryByteStore;
|
||||
import 'package:meta/meta.dart';
|
||||
|
||||
/**
|
||||
* An implementation of a context builder.
|
||||
*/
|
||||
class ContextBuilderImpl implements ContextBuilder {
|
||||
/**
|
||||
* The resource provider used to access the file system.
|
||||
*/
|
||||
final ResourceProvider resourceProvider;
|
||||
|
||||
/**
|
||||
* Initialize a newly created context builder. If a [resourceProvider] is
|
||||
* given, then it will be used to access the file system, otherwise the
|
||||
* default resource provider will be used.
|
||||
*/
|
||||
ContextBuilderImpl({ResourceProvider resourceProvider})
|
||||
: resourceProvider =
|
||||
resourceProvider ?? PhysicalResourceProvider.INSTANCE;
|
||||
|
||||
/**
|
||||
* Return the path to the default location of the SDK, or `null` if the sdk
|
||||
* cannot be found.
|
||||
*/
|
||||
String get _defaultSdkPath =>
|
||||
FolderBasedDartSdk.defaultSdkDirectory(resourceProvider)?.path;
|
||||
|
||||
@override
|
||||
AnalysisContext createContext(
|
||||
{@required ContextRoot contextRoot,
|
||||
DeclaredVariables declaredVariables,
|
||||
String sdkPath}) {
|
||||
PerformanceLog performanceLog = new PerformanceLog(new StringBuffer());
|
||||
AnalysisDriverScheduler scheduler =
|
||||
new AnalysisDriverScheduler(performanceLog);
|
||||
sdkPath ??= _defaultSdkPath;
|
||||
if (sdkPath == null) {
|
||||
throw new ArgumentError('Cannot find path to the SDK');
|
||||
}
|
||||
DartSdkManager sdkManager = new DartSdkManager(sdkPath, true);
|
||||
scheduler.start();
|
||||
|
||||
// TODO(brianwilkerson) Move the required implementation from the old
|
||||
// ContextBuilder to this class and remove the old class.
|
||||
old.ContextBuilderOptions options = new old.ContextBuilderOptions();
|
||||
if (declaredVariables != null) {
|
||||
options.declaredVariables = _toMap(declaredVariables);
|
||||
}
|
||||
options.defaultPackageFilePath = contextRoot.packagesFile?.path;
|
||||
|
||||
old.ContextBuilder builder = new old.ContextBuilder(
|
||||
resourceProvider, sdkManager, new ContentCache(),
|
||||
options: options);
|
||||
builder.analysisDriverScheduler = scheduler;
|
||||
builder.byteStore = new MemoryByteStore();
|
||||
builder.fileContentOverlay = new FileContentOverlay();
|
||||
builder.performanceLog = performanceLog;
|
||||
|
||||
old.ContextRoot oldContextRoot = new old.ContextRoot(
|
||||
contextRoot.root.path, contextRoot.excludedPaths.toList());
|
||||
AnalysisDriver driver = builder.buildDriver(oldContextRoot);
|
||||
DriverBasedAnalysisContext context =
|
||||
new DriverBasedAnalysisContext(resourceProvider, contextRoot, driver);
|
||||
return context;
|
||||
}
|
||||
|
||||
/**
|
||||
* Convert the [declaredVariables] into a map for use with the old context
|
||||
* builder.
|
||||
*/
|
||||
Map<String, String> _toMap(DeclaredVariables declaredVariables) {
|
||||
Map<String, String> map = <String, String>{};
|
||||
for (String name in declaredVariables.variableNames) {
|
||||
map[name] = declaredVariables.get(name);
|
||||
}
|
||||
return map;
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,91 @@
|
||||
// Copyright (c) 2018, the Dart project authors. Please see the AUTHORS file
|
||||
// for details. All rights reserved. Use of this source code is governed by a
|
||||
// BSD-style license that can be found in the LICENSE file.
|
||||
|
||||
import 'dart:io' as io;
|
||||
|
||||
import 'package:analyzer/context/declared_variables.dart';
|
||||
import 'package:analyzer/dart/analysis/analysis_context.dart';
|
||||
import 'package:analyzer/dart/analysis/context_root.dart';
|
||||
import 'package:analyzer/file_system/file_system.dart';
|
||||
import 'package:analyzer/src/dart/analysis/context_builder.dart';
|
||||
import 'package:analyzer/src/dart/analysis/context_root.dart';
|
||||
import 'package:analyzer/src/dart/analysis/driver_based_analysis_context.dart';
|
||||
import 'package:analyzer/src/test_utilities/resource_provider_mixin.dart';
|
||||
import 'package:test/test.dart';
|
||||
import 'package:test_reflective_loader/test_reflective_loader.dart';
|
||||
|
||||
import '../../context/mock_sdk.dart';
|
||||
|
||||
main() {
|
||||
defineReflectiveSuite(() {
|
||||
defineReflectiveTests(ContextBuilderImplTest);
|
||||
});
|
||||
}
|
||||
|
||||
@reflectiveTest
|
||||
class ContextBuilderImplTest extends Object with ResourceProviderMixin {
|
||||
ContextBuilderImpl contextBuilder;
|
||||
ContextRoot contextRoot;
|
||||
|
||||
void assertEquals(DeclaredVariables actual, DeclaredVariables expected) {
|
||||
Iterable<String> actualNames = actual.variableNames;
|
||||
Iterable<String> expectedNames = expected.variableNames;
|
||||
expect(actualNames, expectedNames);
|
||||
for (String name in expectedNames) {
|
||||
expect(actual.get(name), expected.get(name));
|
||||
}
|
||||
}
|
||||
|
||||
void setUp() {
|
||||
resourceProvider.newFolder(resourceProvider.pathContext.dirname(
|
||||
resourceProvider.pathContext.dirname(io.Platform.resolvedExecutable)));
|
||||
contextBuilder = new ContextBuilderImpl(resourceProvider: resourceProvider);
|
||||
String path = resourceProvider.convertPath('/temp/root');
|
||||
Folder folder = resourceProvider.newFolder(path);
|
||||
contextRoot = new ContextRootImpl(resourceProvider, folder);
|
||||
}
|
||||
|
||||
test_createContext_declaredVariables() {
|
||||
DeclaredVariables declaredVariables = new DeclaredVariables();
|
||||
declaredVariables.define('foo', 'true');
|
||||
DriverBasedAnalysisContext context = contextBuilder.createContext(
|
||||
contextRoot: contextRoot, declaredVariables: declaredVariables);
|
||||
expect(context.analysisOptions, isNotNull);
|
||||
expect(context.contextRoot, contextRoot);
|
||||
assertEquals(context.driver.declaredVariables, declaredVariables);
|
||||
}
|
||||
|
||||
test_createContext_declaredVariables_sdkPath() {
|
||||
DeclaredVariables declaredVariables = new DeclaredVariables();
|
||||
declaredVariables.define('bar', 'true');
|
||||
MockSdk sdk = new MockSdk(resourceProvider: resourceProvider);
|
||||
DriverBasedAnalysisContext context = contextBuilder.createContext(
|
||||
contextRoot: contextRoot,
|
||||
declaredVariables: declaredVariables,
|
||||
sdkPath: sdkRoot);
|
||||
expect(context.analysisOptions, isNotNull);
|
||||
expect(context.contextRoot, contextRoot);
|
||||
assertEquals(context.driver.declaredVariables, declaredVariables);
|
||||
expect(context.driver.sourceFactory.dartSdk.mapDartUri('dart:core'),
|
||||
sdk.mapDartUri('dart:core'));
|
||||
}
|
||||
|
||||
test_createContext_defaults() {
|
||||
AnalysisContext context =
|
||||
contextBuilder.createContext(contextRoot: contextRoot);
|
||||
expect(context.analysisOptions, isNotNull);
|
||||
expect(context.contextRoot, contextRoot);
|
||||
}
|
||||
|
||||
test_createContext_sdkPath() {
|
||||
String sdkPath = resourceProvider.convertPath('/path/to/sdk');
|
||||
resourceProvider.newFolder(sdkPath);
|
||||
AnalysisContext context = contextBuilder.createContext(
|
||||
contextRoot: contextRoot, sdkPath: sdkPath);
|
||||
expect(context.analysisOptions, isNotNull);
|
||||
expect(context.contextRoot, contextRoot);
|
||||
// TODO(brianwilkerson) We don't currently have a way to test whether the
|
||||
// sdkPath is being handled correctly.
|
||||
}
|
||||
}
|
||||
@@ -4,6 +4,7 @@
|
||||
|
||||
import 'package:test_reflective_loader/test_reflective_loader.dart';
|
||||
|
||||
import 'context_builder_test.dart' as context_builder_test;
|
||||
import 'context_locator_test.dart' as context_locator_test;
|
||||
import 'context_root_test.dart' as context_root_test;
|
||||
import 'defined_names_test.dart' as defined_names_test;
|
||||
@@ -21,6 +22,7 @@ import 'session_test.dart' as session_test;
|
||||
|
||||
main() {
|
||||
defineReflectiveSuite(() {
|
||||
context_builder_test.main();
|
||||
context_locator_test.main();
|
||||
context_root_test.main();
|
||||
defined_names_test.main();
|
||||
|
||||
Reference in New Issue
Block a user