3e73e2fed4
Avoid constructing file URIs and paths directly from the host platform when analyzer code is operating on an injected ResourceProvider. Those direct conversions use the process path context, which is wrong when the provider is using a Windows path context on another host platform. Route file URI conversions through ResourceProvider, FileSource, File, and PathContext APIs instead. This keeps file names, document links, analysis options includes, navigation targets, and relative paths aligned with the active provider. Update affected tests and shared test utilities to use provider-backed URIs and paths, so they exercise the same path semantics as production code. Change-Id: Iaf7751d028273a5fa72a04d8ca60e51aee700594 Reviewed-on: https://dart-review.googlesource.com/c/sdk/+/499481 Reviewed-by: Samuel Rawlins <srawlins@google.com> Commit-Queue: Konstantin Shcheglov <scheglov@google.com> Reviewed-by: Johnni Winther <johnniwinther@google.com>
284 lines
10 KiB
Dart
284 lines
10 KiB
Dart
// Copyright (c) 2014, 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:analysis_server/protocol/protocol_generated.dart';
|
|
import 'package:analysis_server/src/protocol_server.dart';
|
|
import 'package:analyzer/file_system/file_system.dart';
|
|
import 'package:test/test.dart';
|
|
import 'package:test_reflective_loader/test_reflective_loader.dart';
|
|
|
|
import 'analysis_server_base.dart';
|
|
import 'mocks.dart';
|
|
|
|
void main() {
|
|
defineReflectiveSuite(() {
|
|
defineReflectiveTests(ExecutionDomainTest);
|
|
});
|
|
// group('ExecutionDomainHandler', () {
|
|
// var provider = MemoryResourceProvider();
|
|
// late AnalysisServer server;
|
|
// late ExecutionDomainHandler handler;
|
|
//
|
|
// setUp(() {
|
|
// server = AnalysisServer(
|
|
// MockServerChannel(),
|
|
// provider,
|
|
// AnalysisServerOptions(),
|
|
// DartSdkManager(''),
|
|
// CrashReportingAttachmentsBuilder.empty,
|
|
// InstrumentationService.NULL_SERVICE);
|
|
// handler = ExecutionDomainHandler(server, server.executionContext);
|
|
// });
|
|
//
|
|
// // `TODO`(brianwilkerson) Re-enable these tests if we re-enable the
|
|
// // execution.mapUri request.
|
|
// group('mapUri', () {
|
|
// String contextId;
|
|
//
|
|
// void createExecutionContextIdForFile(String path) {
|
|
// Request request = new ExecutionCreateContextParams(path).toRequest('0', clientUriConverter: server.uriConverter);
|
|
// Response response = handler.handleRequest(request, NotCancelableToken());
|
|
// expect(response, isResponseSuccess('0'));
|
|
// ExecutionCreateContextResult result =
|
|
// new ExecutionCreateContextResult.fromResponse(response, clientUriConverter: server.uriConverter);
|
|
// contextId = result.id;
|
|
// }
|
|
//
|
|
// setUp(() {
|
|
// Folder folder = provider.newFile('/a/b.dart', '').parent;
|
|
// server.folderMap.putIfAbsent(folder, () {
|
|
// SourceFactory factory =
|
|
// new SourceFactory([new ResourceUriResolver(provider)]);
|
|
// AnalysisContext context =
|
|
// AnalysisEngine.instance.createAnalysisContext();
|
|
// context.sourceFactory = factory;
|
|
// return context;
|
|
// });
|
|
// createExecutionContextIdForFile('/a/b.dart');
|
|
// });
|
|
//
|
|
// tearDown(() {
|
|
// Request request =
|
|
// new ExecutionDeleteContextParams(contextId).toRequest('1', clientUriConverter: server.uriConverter);
|
|
// Response response = handler.handleRequest(request, NotCancelableToken());
|
|
// expect(response, isResponseSuccess('1'));
|
|
// });
|
|
//
|
|
// group('file to URI', () {
|
|
// test('does not exist', () {
|
|
// Request request =
|
|
// new ExecutionMapUriParams(contextId, file: '/a/c.dart')
|
|
// .toRequest('2', clientUriConverter: server.uriConverter);
|
|
// Response response = handler.handleRequest(request, NotCancelableToken());
|
|
// expect(response, isResponseFailure('2'));
|
|
// });
|
|
//
|
|
// test('directory', () {
|
|
// provider.newFolder('/a/d');
|
|
// Request request =
|
|
// new ExecutionMapUriParams(contextId, file: '/a/d').toRequest('2', clientUriConverter: server.uriConverter);
|
|
// Response response = handler.handleRequest(request, NotCancelableToken());
|
|
// expect(response, isResponseFailure('2'));
|
|
// });
|
|
// });
|
|
//
|
|
// group('URI to file', () {
|
|
// test('invalid', () {
|
|
// Request request =
|
|
// new ExecutionMapUriParams(contextId, uri: 'foo:///a/b.dart')
|
|
// .toRequest('2', clientUriConverter: server.uriConverter);
|
|
// Response response = handler.handleRequest(request, NotCancelableToken());
|
|
// expect(response, isResponseFailure('2'));
|
|
// });
|
|
// });
|
|
//
|
|
// test('invalid context id', () {
|
|
// Request request =
|
|
// new ExecutionMapUriParams('xxx', uri: '').toRequest('4', clientUriConverter: server.uriConverter);
|
|
// Response response = handler.handleRequest(request, NotCancelableToken());
|
|
// expect(response, isResponseFailure('4'));
|
|
// });
|
|
//
|
|
// test('both file and uri', () {
|
|
// Request request =
|
|
// new ExecutionMapUriParams('xxx', file: '', uri: '').toRequest('5', clientUriConverter: server.uriConverter);
|
|
// Response response = handler.handleRequest(request, NotCancelableToken());
|
|
// expect(response, isResponseFailure('5'));
|
|
// });
|
|
//
|
|
// test('neither file nor uri', () {
|
|
// Request request = new ExecutionMapUriParams('xxx').toRequest('6');
|
|
// Response response = handler.handleRequest(request, NotCancelableToken());
|
|
// expect(response, isResponseFailure('6'));
|
|
// });
|
|
// });
|
|
// });
|
|
}
|
|
|
|
@reflectiveTest
|
|
class ExecutionDomainTest extends PubPackageAnalysisServerTest {
|
|
late String contextId;
|
|
|
|
@override
|
|
Future<void> setUp() async {
|
|
super.setUp();
|
|
await setRoots(included: [workspaceRootPath], excluded: []);
|
|
await _createExecutionContext(testFile);
|
|
}
|
|
|
|
@override
|
|
Future<void> tearDown() async {
|
|
await _disposeExecutionContext();
|
|
await super.tearDown();
|
|
}
|
|
|
|
Future<void> test_createAndDeleteMultipleContexts() async {
|
|
var request = ExecutionCreateContextParams(
|
|
'/a/b.dart',
|
|
).toRequest('0', clientUriConverter: server.uriConverter);
|
|
var response = await handleSuccessfulRequest(request);
|
|
expect(response, isResponseSuccess('0'));
|
|
var result = ExecutionCreateContextResult.fromResponse(
|
|
response,
|
|
clientUriConverter: server.uriConverter,
|
|
);
|
|
var id0 = result.id;
|
|
|
|
request = ExecutionCreateContextParams(
|
|
'/c/d.dart',
|
|
).toRequest('1', clientUriConverter: server.uriConverter);
|
|
response = await handleSuccessfulRequest(request);
|
|
expect(response, isResponseSuccess('1'));
|
|
result = ExecutionCreateContextResult.fromResponse(
|
|
response,
|
|
clientUriConverter: server.uriConverter,
|
|
);
|
|
var id1 = result.id;
|
|
|
|
expect(id0 == id1, isFalse);
|
|
|
|
request = ExecutionDeleteContextParams(
|
|
id0,
|
|
).toRequest('2', clientUriConverter: server.uriConverter);
|
|
response = await handleSuccessfulRequest(request);
|
|
expect(response, isResponseSuccess('2'));
|
|
|
|
request = ExecutionDeleteContextParams(
|
|
id1,
|
|
).toRequest('3', clientUriConverter: server.uriConverter);
|
|
response = await handleSuccessfulRequest(request);
|
|
expect(response, isResponseSuccess('3'));
|
|
}
|
|
|
|
Future<void> test_deleteNonExistentContext() async {
|
|
var request = ExecutionDeleteContextParams(
|
|
'13',
|
|
).toRequest('0', clientUriConverter: server.uriConverter);
|
|
var response = await handleSuccessfulRequest(request);
|
|
// TODO(brianwilkerson): It isn't currently specified to be an error if a
|
|
// client attempts to delete a context that doesn't exist. Should it be?
|
|
// expect(response, isResponseFailure('0'));
|
|
expect(response, isResponseSuccess('0'));
|
|
}
|
|
|
|
Future<void> test_getSuggestions() async {
|
|
var code = r'''
|
|
class A {
|
|
int foo;
|
|
}
|
|
|
|
void contextFunction() {
|
|
var a = A();
|
|
// context line
|
|
}
|
|
''';
|
|
|
|
var path = newFile('/test.dart', '').path;
|
|
newFile(path, code);
|
|
|
|
var request = ExecutionGetSuggestionsParams(
|
|
'a.',
|
|
2,
|
|
path,
|
|
code.indexOf('// context line'),
|
|
<RuntimeCompletionVariable>[],
|
|
).toRequest('0', clientUriConverter: server.uriConverter);
|
|
var response = await handleSuccessfulRequest(request);
|
|
|
|
var result = ExecutionGetSuggestionsResult.fromResponse(
|
|
response,
|
|
clientUriConverter: server.uriConverter,
|
|
);
|
|
// expect(result.suggestions, isNotEmpty);
|
|
//
|
|
// expect(
|
|
// result.suggestions,
|
|
// contains(
|
|
// predicate<CompletionSuggestion>((s) => s.completion == 'foo')));
|
|
|
|
// TODO(brianwilkerson): Restore the expectations above (and delete the line
|
|
// below) after the functionality has been re-enabled.
|
|
expect(result.suggestions, isEmpty);
|
|
}
|
|
|
|
Future<void> test_mapUri_file() async {
|
|
var file = newFile('/a/b.dart', '');
|
|
// map the file
|
|
var result = await _mapUri(file: file.path);
|
|
expect(result.file, isNull);
|
|
expect(result.uri, file.toUri().toString());
|
|
}
|
|
|
|
Future<void> test_mapUri_file_dartUriKind() async {
|
|
var path = (await _mapUri(uri: 'dart:async')).file;
|
|
// map file
|
|
var result = await _mapUri(file: path);
|
|
expect(result.file, isNull);
|
|
expect(result.uri, 'dart:async');
|
|
}
|
|
|
|
Future<void> test_mapUri_uri() async {
|
|
var file = newFile('/a/b.dart', '');
|
|
// map the uri
|
|
var result = await _mapUri(uri: file.toUri().toString());
|
|
expect(result.file, file.path);
|
|
expect(result.uri, isNull);
|
|
}
|
|
|
|
Future<void> _createExecutionContext(File file) async {
|
|
var request = ExecutionCreateContextParams(
|
|
file.path,
|
|
).toRequest('0', clientUriConverter: server.uriConverter);
|
|
var response = await handleSuccessfulRequest(request);
|
|
expect(response, isResponseSuccess('0'));
|
|
var result = ExecutionCreateContextResult.fromResponse(
|
|
response,
|
|
clientUriConverter: server.uriConverter,
|
|
);
|
|
contextId = result.id;
|
|
}
|
|
|
|
Future<void> _disposeExecutionContext() async {
|
|
var request = ExecutionDeleteContextParams(
|
|
contextId,
|
|
).toRequest('1', clientUriConverter: server.uriConverter);
|
|
var response = await handleSuccessfulRequest(request);
|
|
expect(response, isResponseSuccess('1'));
|
|
}
|
|
|
|
Future<ExecutionMapUriResult> _mapUri({String? file, String? uri}) async {
|
|
var request = ExecutionMapUriParams(
|
|
contextId,
|
|
file: file,
|
|
uri: uri,
|
|
).toRequest('2', clientUriConverter: server.uriConverter);
|
|
var response = await handleSuccessfulRequest(request);
|
|
expect(response, isResponseSuccess('2'));
|
|
return ExecutionMapUriResult.fromResponse(
|
|
response,
|
|
clientUriConverter: server.uriConverter,
|
|
);
|
|
}
|
|
}
|