Skip to content
This repository was archived by the owner on Feb 25, 2025. It is now read-only.

Commit 7764e69

Browse files
bwilkersoncommit-bot@chromium.org
authored andcommitted
Initial API to build analysis contexts (replaces ContextLocator.locateContexts)
Change-Id: If00ce6321efb6ff4da96e654cfe2a0a8501bed95 Reviewed-on: https://dart-review.googlesource.com/50323 Commit-Queue: Brian Wilkerson <[email protected]> Reviewed-by: Konstantin Shcheglov <[email protected]>
1 parent 5ea271b commit 7764e69

File tree

4 files changed

+236
-0
lines changed

4 files changed

+236
-0
lines changed
Lines changed: 42 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,42 @@
1+
// Copyright (c) 2018, the Dart project authors. Please see the AUTHORS file
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.
4+
5+
import 'package:analyzer/context/declared_variables.dart';
6+
import 'package:analyzer/dart/analysis/analysis_context.dart';
7+
import 'package:analyzer/dart/analysis/context_root.dart';
8+
import 'package:analyzer/file_system/file_system.dart';
9+
import 'package:analyzer/src/dart/analysis/context_builder.dart';
10+
import 'package:meta/meta.dart';
11+
12+
/**
13+
* A utility class used to build an analysis context based on a context root.
14+
*
15+
* Clients may not extend, implement or mix-in this class.
16+
*/
17+
abstract class ContextBuilder {
18+
/**
19+
* Initialize a newly created context builder. If a [resourceProvider] is
20+
* given, then it will be used to access the file system, otherwise the
21+
* default resource provider will be used.
22+
*/
23+
factory ContextBuilder({ResourceProvider resourceProvider}) =
24+
ContextBuilderImpl;
25+
26+
/**
27+
* Return an analysis context corresponding to the given [contextRoot].
28+
*
29+
* If a set of [declaredVariables] is provided, the values will be used to map
30+
* the the variable names found in `fromEnvironment` invocations to the
31+
* constant value that will be returned. If none is given, then no variables
32+
* will be defined.
33+
*
34+
* If an [sdkPath] is provided, and if it is a valid path to a directory
35+
* containing a valid SDK, then the SDK in the referenced directory will be
36+
* used when analyzing the code in the context.
37+
*/
38+
AnalysisContext createContext(
39+
{@required ContextRoot contextRoot,
40+
DeclaredVariables declaredVariables,
41+
String sdkPath});
42+
}
Lines changed: 101 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,101 @@
1+
// Copyright (c) 2018, the Dart project authors. Please see the AUTHORS file
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.
4+
5+
import 'package:analyzer/context/context_root.dart' as old;
6+
import 'package:analyzer/context/declared_variables.dart';
7+
import 'package:analyzer/dart/analysis/analysis_context.dart';
8+
import 'package:analyzer/dart/analysis/context_builder.dart';
9+
import 'package:analyzer/dart/analysis/context_root.dart';
10+
import 'package:analyzer/file_system/file_system.dart';
11+
import 'package:analyzer/file_system/physical_file_system.dart';
12+
import 'package:analyzer/src/context/builder.dart' as old
13+
show ContextBuilder, ContextBuilderOptions;
14+
import 'package:analyzer/src/dart/analysis/driver.dart'
15+
show AnalysisDriver, AnalysisDriverScheduler;
16+
import 'package:analyzer/src/dart/analysis/driver_based_analysis_context.dart';
17+
import 'package:analyzer/src/dart/analysis/file_state.dart'
18+
show FileContentOverlay;
19+
import 'package:analyzer/src/dart/sdk/sdk.dart';
20+
import 'package:analyzer/src/generated/sdk.dart' show DartSdkManager;
21+
import 'package:analyzer/src/generated/source.dart' show ContentCache;
22+
import 'package:front_end/src/base/performance_logger.dart' show PerformanceLog;
23+
import 'package:front_end/src/byte_store/byte_store.dart' show MemoryByteStore;
24+
import 'package:meta/meta.dart';
25+
26+
/**
27+
* An implementation of a context builder.
28+
*/
29+
class ContextBuilderImpl implements ContextBuilder {
30+
/**
31+
* The resource provider used to access the file system.
32+
*/
33+
final ResourceProvider resourceProvider;
34+
35+
/**
36+
* Initialize a newly created context builder. If a [resourceProvider] is
37+
* given, then it will be used to access the file system, otherwise the
38+
* default resource provider will be used.
39+
*/
40+
ContextBuilderImpl({ResourceProvider resourceProvider})
41+
: resourceProvider =
42+
resourceProvider ?? PhysicalResourceProvider.INSTANCE;
43+
44+
/**
45+
* Return the path to the default location of the SDK, or `null` if the sdk
46+
* cannot be found.
47+
*/
48+
String get _defaultSdkPath =>
49+
FolderBasedDartSdk.defaultSdkDirectory(resourceProvider)?.path;
50+
51+
@override
52+
AnalysisContext createContext(
53+
{@required ContextRoot contextRoot,
54+
DeclaredVariables declaredVariables,
55+
String sdkPath}) {
56+
PerformanceLog performanceLog = new PerformanceLog(new StringBuffer());
57+
AnalysisDriverScheduler scheduler =
58+
new AnalysisDriverScheduler(performanceLog);
59+
sdkPath ??= _defaultSdkPath;
60+
if (sdkPath == null) {
61+
throw new ArgumentError('Cannot find path to the SDK');
62+
}
63+
DartSdkManager sdkManager = new DartSdkManager(sdkPath, true);
64+
scheduler.start();
65+
66+
// TODO(brianwilkerson) Move the required implementation from the old
67+
// ContextBuilder to this class and remove the old class.
68+
old.ContextBuilderOptions options = new old.ContextBuilderOptions();
69+
if (declaredVariables != null) {
70+
options.declaredVariables = _toMap(declaredVariables);
71+
}
72+
options.defaultPackageFilePath = contextRoot.packagesFile?.path;
73+
74+
old.ContextBuilder builder = new old.ContextBuilder(
75+
resourceProvider, sdkManager, new ContentCache(),
76+
options: options);
77+
builder.analysisDriverScheduler = scheduler;
78+
builder.byteStore = new MemoryByteStore();
79+
builder.fileContentOverlay = new FileContentOverlay();
80+
builder.performanceLog = performanceLog;
81+
82+
old.ContextRoot oldContextRoot = new old.ContextRoot(
83+
contextRoot.root.path, contextRoot.excludedPaths.toList());
84+
AnalysisDriver driver = builder.buildDriver(oldContextRoot);
85+
DriverBasedAnalysisContext context =
86+
new DriverBasedAnalysisContext(resourceProvider, contextRoot, driver);
87+
return context;
88+
}
89+
90+
/**
91+
* Convert the [declaredVariables] into a map for use with the old context
92+
* builder.
93+
*/
94+
Map<String, String> _toMap(DeclaredVariables declaredVariables) {
95+
Map<String, String> map = <String, String>{};
96+
for (String name in declaredVariables.variableNames) {
97+
map[name] = declaredVariables.get(name);
98+
}
99+
return map;
100+
}
101+
}
Lines changed: 91 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,91 @@
1+
// Copyright (c) 2018, the Dart project authors. Please see the AUTHORS file
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.
4+
5+
import 'dart:io' as io;
6+
7+
import 'package:analyzer/context/declared_variables.dart';
8+
import 'package:analyzer/dart/analysis/analysis_context.dart';
9+
import 'package:analyzer/dart/analysis/context_root.dart';
10+
import 'package:analyzer/file_system/file_system.dart';
11+
import 'package:analyzer/src/dart/analysis/context_builder.dart';
12+
import 'package:analyzer/src/dart/analysis/context_root.dart';
13+
import 'package:analyzer/src/dart/analysis/driver_based_analysis_context.dart';
14+
import 'package:analyzer/src/test_utilities/resource_provider_mixin.dart';
15+
import 'package:test/test.dart';
16+
import 'package:test_reflective_loader/test_reflective_loader.dart';
17+
18+
import '../../context/mock_sdk.dart';
19+
20+
main() {
21+
defineReflectiveSuite(() {
22+
defineReflectiveTests(ContextBuilderImplTest);
23+
});
24+
}
25+
26+
@reflectiveTest
27+
class ContextBuilderImplTest extends Object with ResourceProviderMixin {
28+
ContextBuilderImpl contextBuilder;
29+
ContextRoot contextRoot;
30+
31+
void assertEquals(DeclaredVariables actual, DeclaredVariables expected) {
32+
Iterable<String> actualNames = actual.variableNames;
33+
Iterable<String> expectedNames = expected.variableNames;
34+
expect(actualNames, expectedNames);
35+
for (String name in expectedNames) {
36+
expect(actual.get(name), expected.get(name));
37+
}
38+
}
39+
40+
void setUp() {
41+
resourceProvider.newFolder(resourceProvider.pathContext.dirname(
42+
resourceProvider.pathContext.dirname(io.Platform.resolvedExecutable)));
43+
contextBuilder = new ContextBuilderImpl(resourceProvider: resourceProvider);
44+
String path = resourceProvider.convertPath('/temp/root');
45+
Folder folder = resourceProvider.newFolder(path);
46+
contextRoot = new ContextRootImpl(resourceProvider, folder);
47+
}
48+
49+
test_createContext_declaredVariables() {
50+
DeclaredVariables declaredVariables = new DeclaredVariables();
51+
declaredVariables.define('foo', 'true');
52+
DriverBasedAnalysisContext context = contextBuilder.createContext(
53+
contextRoot: contextRoot, declaredVariables: declaredVariables);
54+
expect(context.analysisOptions, isNotNull);
55+
expect(context.contextRoot, contextRoot);
56+
assertEquals(context.driver.declaredVariables, declaredVariables);
57+
}
58+
59+
test_createContext_declaredVariables_sdkPath() {
60+
DeclaredVariables declaredVariables = new DeclaredVariables();
61+
declaredVariables.define('bar', 'true');
62+
MockSdk sdk = new MockSdk(resourceProvider: resourceProvider);
63+
DriverBasedAnalysisContext context = contextBuilder.createContext(
64+
contextRoot: contextRoot,
65+
declaredVariables: declaredVariables,
66+
sdkPath: sdkRoot);
67+
expect(context.analysisOptions, isNotNull);
68+
expect(context.contextRoot, contextRoot);
69+
assertEquals(context.driver.declaredVariables, declaredVariables);
70+
expect(context.driver.sourceFactory.dartSdk.mapDartUri('dart:core'),
71+
sdk.mapDartUri('dart:core'));
72+
}
73+
74+
test_createContext_defaults() {
75+
AnalysisContext context =
76+
contextBuilder.createContext(contextRoot: contextRoot);
77+
expect(context.analysisOptions, isNotNull);
78+
expect(context.contextRoot, contextRoot);
79+
}
80+
81+
test_createContext_sdkPath() {
82+
String sdkPath = resourceProvider.convertPath('/path/to/sdk');
83+
resourceProvider.newFolder(sdkPath);
84+
AnalysisContext context = contextBuilder.createContext(
85+
contextRoot: contextRoot, sdkPath: sdkPath);
86+
expect(context.analysisOptions, isNotNull);
87+
expect(context.contextRoot, contextRoot);
88+
// TODO(brianwilkerson) We don't currently have a way to test whether the
89+
// sdkPath is being handled correctly.
90+
}
91+
}

pkg/analyzer/test/src/dart/analysis/test_all.dart

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -4,6 +4,7 @@
44

55
import 'package:test_reflective_loader/test_reflective_loader.dart';
66

7+
import 'context_builder_test.dart' as context_builder_test;
78
import 'context_locator_test.dart' as context_locator_test;
89
import 'context_root_test.dart' as context_root_test;
910
import 'defined_names_test.dart' as defined_names_test;
@@ -21,6 +22,7 @@ import 'session_test.dart' as session_test;
2122

2223
main() {
2324
defineReflectiveSuite(() {
25+
context_builder_test.main();
2426
context_locator_test.main();
2527
context_root_test.main();
2628
defined_names_test.main();

0 commit comments

Comments
 (0)