Proposed replacement for SourceFactory
Change-Id: Iadcb71a4f9682d4cb9636aea6bb0b91f3bf040f9
Reviewed-on: https://dart-review.googlesource.com/58160
Commit-Queue: Brian Wilkerson <brianwilkerson@google.com>
Reviewed-by: Konstantin Shcheglov <scheglov@google.com>
diff --git a/pkg/analysis_server/lib/src/computer/import_elements_computer.dart b/pkg/analysis_server/lib/src/computer/import_elements_computer.dart
index c1be612..b2997da 100644
--- a/pkg/analysis_server/lib/src/computer/import_elements_computer.dart
+++ b/pkg/analysis_server/lib/src/computer/import_elements_computer.dart
@@ -6,6 +6,7 @@
import 'package:analysis_server/protocol/protocol_generated.dart';
import 'package:analyzer/dart/analysis/results.dart';
+import 'package:analyzer/dart/analysis/uri_converter.dart';
import 'package:analyzer/dart/ast/ast.dart';
import 'package:analyzer/dart/ast/ast_factory.dart';
import 'package:analyzer/dart/ast/token.dart';
@@ -53,7 +54,7 @@
List<ImportedElements> filteredImportedElements =
_filterImportedElements(importedElementsList);
LibraryElement libraryElement = libraryResult.libraryElement;
- SourceFactory sourceFactory = libraryResult.session.sourceFactory;
+ UriConverter uriConverter = libraryResult.session.uriConverter;
List<ImportDirective> existingImports = <ImportDirective>[];
for (var directive in libraryResult.unit.directives) {
if (directive is ImportDirective) {
@@ -73,7 +74,7 @@
// so we need to add an import.
//
File importedFile = resourceProvider.getFile(importedElements.path);
- Uri uri = sourceFactory.restoreUri(importedFile.createSource());
+ Uri uri = uriConverter.pathToUri(importedFile.path);
Source importedSource = importedFile.createSource(uri);
String importUri =
_getLibrarySourceUri(libraryElement, importedSource);
diff --git a/pkg/analyzer/lib/dart/analysis/session.dart b/pkg/analyzer/lib/dart/analysis/session.dart
index dd8c595..3c4d9cf 100644
--- a/pkg/analyzer/lib/dart/analysis/session.dart
+++ b/pkg/analyzer/lib/dart/analysis/session.dart
@@ -5,6 +5,7 @@
import 'dart:async';
import 'package:analyzer/dart/analysis/results.dart';
+import 'package:analyzer/dart/analysis/uri_converter.dart';
import 'package:analyzer/dart/element/element.dart';
import 'package:analyzer/exception/exception.dart';
import 'package:analyzer/file_system/file_system.dart';
@@ -29,7 +30,10 @@
/**
* Return the source factory used to resolve URIs.
+ *
+ * Deprecated: Use the methods on [uriConverter] instead.
*/
+ @deprecated
SourceFactory get sourceFactory;
/**
@@ -44,6 +48,11 @@
Future<TypeSystem> get typeSystem;
/**
+ * Return the URI converter used to convert between URI's and file paths.
+ */
+ UriConverter get uriConverter;
+
+ /**
* Return a future that will complete with information about the errors
* contained in the file with the given absolute, normalized [path].
*
diff --git a/pkg/analyzer/lib/dart/analysis/uri_converter.dart b/pkg/analyzer/lib/dart/analysis/uri_converter.dart
new file mode 100644
index 0000000..ec1ed8d
--- /dev/null
+++ b/pkg/analyzer/lib/dart/analysis/uri_converter.dart
@@ -0,0 +1,30 @@
+// 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.
+
+/**
+ * A utility class used to convert between URIs and absolute file paths.
+ */
+abstract class UriConverter {
+ /**
+ * Return the URI that should be used to reference the file at the absolute
+ * [path], or `null` if there is no valid way to reference the file in this
+ * converter’s context. The file at that path is not required to exist.
+ *
+ * If a [containingPath] is provided and both the [path] and [containingPath]
+ * are within the root of this converter’s context, then the returned URI will
+ * be a relative path. Otherwise, the returned URI will be an absolute URI.
+ *
+ * Throws an `ArgumentError` if the [path] is `null` or is not a valid
+ * absolute file path.
+ */
+ Uri pathToUri(String path, {String containingPath});
+
+ /**
+ * Return the absolute path of the file to which the absolute [uri] resolves,
+ * or `null` if the [uri] cannot be resolved in this converter’s context.
+ *
+ * Throws an `ArgumentError` if the [uri] is `null` or is not an absolute URI.
+ */
+ String uriToPath(Uri uri);
+}
diff --git a/pkg/analyzer/lib/src/dart/analysis/session.dart b/pkg/analyzer/lib/src/dart/analysis/session.dart
index f627fa8..1a420e1 100644
--- a/pkg/analyzer/lib/src/dart/analysis/session.dart
+++ b/pkg/analyzer/lib/src/dart/analysis/session.dart
@@ -6,10 +6,12 @@
import 'package:analyzer/dart/analysis/results.dart';
import 'package:analyzer/dart/analysis/session.dart';
+import 'package:analyzer/dart/analysis/uri_converter.dart';
import 'package:analyzer/dart/element/element.dart';
import 'package:analyzer/file_system/file_system.dart';
import 'package:analyzer/src/dart/analysis/driver.dart' as driver;
import 'package:analyzer/src/dart/analysis/top_level_declaration.dart';
+import 'package:analyzer/src/dart/analysis/uri_converter.dart';
import 'package:analyzer/src/generated/resolver.dart';
import 'package:analyzer/src/generated/source.dart';
@@ -33,6 +35,11 @@
TypeSystem _typeSystem;
/**
+ * The URI converter used to convert between URI's and file paths.
+ */
+ UriConverter _uriConverter;
+
+ /**
* The cache of libraries for URIs.
*/
final Map<String, LibraryElement> _uriToLibraryCache = {};
@@ -73,6 +80,11 @@
}
@override
+ UriConverter get uriConverter {
+ return _uriConverter ??= new DriverBasedUriConverter(_driver);
+ }
+
+ @override
Future<ErrorsResult> getErrors(String path) {
_checkConsistency();
return _driver.getErrors(path);
diff --git a/pkg/analyzer/lib/src/dart/analysis/uri_converter.dart b/pkg/analyzer/lib/src/dart/analysis/uri_converter.dart
new file mode 100644
index 0000000..df11c02
--- /dev/null
+++ b/pkg/analyzer/lib/src/dart/analysis/uri_converter.dart
@@ -0,0 +1,47 @@
+// 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/dart/analysis/uri_converter.dart';
+import 'package:analyzer/file_system/file_system.dart';
+import 'package:analyzer/src/dart/analysis/driver.dart';
+import 'package:analyzer/src/generated/source.dart';
+import 'package:path/src/context.dart';
+
+/**
+ * An implementation of a URI converter based on an analysis driver.
+ */
+class DriverBasedUriConverter implements UriConverter {
+ /**
+ * The driver associated with the context in which the conversion will occur.
+ */
+ final AnalysisDriver driver;
+
+ /**
+ * Initialize a newly created URI converter to use the given [context] and
+ * [driver] to perform the conversions.
+ */
+ DriverBasedUriConverter(this.driver);
+
+ @override
+ Uri pathToUri(String path, {String containingPath}) {
+ ResourceProvider provider = driver.resourceProvider;
+ if (containingPath != null) {
+ Context context = provider.pathContext;
+ String root = driver.contextRoot.root;
+ if (context.isWithin(root, path) &&
+ context.isWithin(root, containingPath)) {
+ String relativePath =
+ context.relative(path, from: context.dirname(containingPath));
+ if (context.isRelative(relativePath)) {
+ return new Uri.file(relativePath);
+ }
+ }
+ }
+ Source source = provider.getFile(path).createSource();
+ return driver.sourceFactory.restoreUri(source);
+ }
+
+ @override
+ String uriToPath(Uri uri) => driver.sourceFactory.forUri2(uri).fullName;
+}
diff --git a/pkg/analyzer/test/src/dart/analysis/test_all.dart b/pkg/analyzer/test/src/dart/analysis/test_all.dart
index f452ede..cd75df1 100644
--- a/pkg/analyzer/test/src/dart/analysis/test_all.dart
+++ b/pkg/analyzer/test/src/dart/analysis/test_all.dart
@@ -4,10 +4,10 @@
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;
+import 'context_builder_test.dart' as context_builder;
+import 'context_locator_test.dart' as context_locator;
+import 'context_root_test.dart' as context_root;
+import 'defined_names_test.dart' as defined_names;
import 'driver_kernel_test.dart' as driver_kernel;
import 'driver_resolution_kernel_test.dart' as driver_resolution_kernel;
import 'driver_resolution_test.dart' as driver_resolution;
@@ -16,16 +16,17 @@
import 'index_test.dart' as index;
import 'mutex_test.dart' as mutex;
import 'referenced_names_test.dart' as referenced_names;
-import 'search_test.dart' as search_test;
-import 'session_helper_test.dart' as session_helper_test;
-import 'session_test.dart' as session_test;
+import 'search_test.dart' as search;
+import 'session_helper_test.dart' as session_helper;
+import 'session_test.dart' as session;
+import 'uri_converter_test.dart' as uri_converter;
main() {
defineReflectiveSuite(() {
- context_builder_test.main();
- context_locator_test.main();
- context_root_test.main();
- defined_names_test.main();
+ context_builder.main();
+ context_locator.main();
+ context_root.main();
+ defined_names.main();
driver.main();
driver_kernel.main();
driver_resolution.main();
@@ -34,8 +35,9 @@
index.main();
mutex.main();
referenced_names.main();
- search_test.main();
- session_helper_test.main();
- session_test.main();
+ search.main();
+ session_helper.main();
+ session.main();
+ uri_converter.main();
}, name: 'analysis');
}
diff --git a/pkg/analyzer/test/src/dart/analysis/uri_converter_test.dart b/pkg/analyzer/test/src/dart/analysis/uri_converter_test.dart
new file mode 100644
index 0000000..45fad90
--- /dev/null
+++ b/pkg/analyzer/test/src/dart/analysis/uri_converter_test.dart
@@ -0,0 +1,104 @@
+// 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/file_system/file_system.dart';
+import 'package:analyzer/file_system/memory_file_system.dart';
+import 'package:analyzer/src/context/context_root.dart';
+import 'package:analyzer/src/dart/analysis/driver.dart';
+import 'package:analyzer/src/dart/analysis/uri_converter.dart';
+import 'package:analyzer/src/generated/source.dart';
+import 'package:analyzer/src/source/package_map_resolver.dart';
+import 'package:test/test.dart';
+import 'package:test_reflective_loader/test_reflective_loader.dart';
+
+import '../../context/mock_sdk.dart';
+
+main() {
+ defineReflectiveSuite(() {
+ defineReflectiveTests(DriverBasedUriConverterTest);
+ });
+}
+
+@reflectiveTest
+class DriverBasedUriConverterTest {
+ MemoryResourceProvider resourceProvider;
+ DriverBasedUriConverter uriConverter;
+
+ void setUp() {
+ resourceProvider = new MemoryResourceProvider();
+ Folder packageFolder = resourceProvider.newFolder('/packages/bar/lib');
+
+ SourceFactory sourceFactory = new SourceFactory([
+ new DartUriResolver(new MockSdk(resourceProvider: resourceProvider)),
+ new PackageMapUriResolver(resourceProvider, {
+ 'foo': [resourceProvider.newFolder('/packages/foo/lib')],
+ 'bar': [packageFolder],
+ }),
+ new ResourceUriResolver(resourceProvider),
+ ], null, resourceProvider);
+
+ ContextRoot contextRoot = new ContextRoot(packageFolder.path, [],
+ pathContext: resourceProvider.pathContext);
+
+ MockAnalysisDriver driver = new MockAnalysisDriver();
+ driver.resourceProvider = resourceProvider;
+ driver.sourceFactory = sourceFactory;
+ driver.contextRoot = contextRoot;
+
+ uriConverter = new DriverBasedUriConverter(driver);
+ }
+
+ test_pathToUri_dart() {
+ expect(
+ uriConverter
+ .pathToUri(resourceProvider.convertPath('/sdk/lib/core/core.dart')),
+ Uri.parse('dart:core'));
+ }
+
+ test_pathToUri_notRelative() {
+ expect(
+ uriConverter.pathToUri(
+ resourceProvider.convertPath('/packages/foo/lib/foo.dart'),
+ containingPath:
+ resourceProvider.convertPath('/packages/bar/lib/bar.dart')),
+ Uri.parse('package:foo/foo.dart'));
+ }
+
+ test_pathToUri_package() {
+ expect(
+ uriConverter.pathToUri(
+ resourceProvider.convertPath('/packages/foo/lib/foo.dart')),
+ Uri.parse('package:foo/foo.dart'));
+ }
+
+ test_pathToUri_relative() {
+ expect(
+ uriConverter.pathToUri(
+ resourceProvider.convertPath('/packages/bar/lib/src/baz.dart'),
+ containingPath:
+ resourceProvider.convertPath('/packages/bar/lib/bar.dart')),
+ Uri.parse('src/baz.dart'));
+ }
+
+ test_uriToPath_dart() {
+ expect(uriConverter.uriToPath(Uri.parse('dart:core')),
+ resourceProvider.convertPath('/sdk/lib/core/core.dart'));
+ }
+
+ test_uriToPath_package() {
+ expect(uriConverter.uriToPath(Uri.parse('package:foo/foo.dart')),
+ resourceProvider.convertPath('/packages/foo/lib/foo.dart'));
+ }
+}
+
+class MockAnalysisDriver implements AnalysisDriver {
+ ResourceProvider resourceProvider;
+ SourceFactory sourceFactory;
+ ContextRoot contextRoot;
+
+ @override
+ dynamic noSuchMethod(Invocation invocation) {
+ fail('Unexpected invocation of ${invocation.memberName}');
+ }
+}