Initial implementation of copy/paste support

R=devoncarew@google.com

Review-Url: https://codereview.chromium.org/2972833002 .
This commit is contained in:
Brian Wilkerson 2017-07-05 14:02:05 -07:00
parent 56f07cf770
commit d9754a58e9
18 changed files with 391 additions and 119 deletions

View file

@ -3945,6 +3945,12 @@ a:focus, a:hover {
which does not match a file currently subject to
analysis.
</p>
</dd><dt class="value">IMPORT_ELEMENTS_INVALID_FILE</dt><dd>
<p>
An "edit.importElements" request specified a FilePath that does not
match a file currently subject to analysis.
</p>
</dd><dt class="value">INVALID_ANALYSIS_ROOT</dt><dd>
<p>

View file

@ -468,6 +468,16 @@ class Response {
error: new RequestError(RequestErrorCode.GET_ERRORS_INVALID_FILE,
'Error during `analysis.getErrors`: invalid file.'));
/**
* Initialize a newly created instance to represent the
* GET_IMPORTED_ELEMENTS_INVALID_FILE error condition.
*/
Response.getImportedElementsInvalidFile(Request request)
: this(request.id,
error: new RequestError(
RequestErrorCode.GET_IMPORTED_ELEMENTS_INVALID_FILE,
'Error during `analysis.getImportedElements`: invalid file.'));
/**
* Initialize a newly created instance to represent the
* GET_NAVIGATION_INVALID_FILE error condition.
@ -488,6 +498,16 @@ class Response {
RequestErrorCode.GET_REACHABLE_SOURCES_INVALID_FILE,
'Error during `analysis.getReachableSources`: invalid file.'));
/**
* Initialize a newly created instance to represent the
* IMPORT_ELEMENTS_INVALID_FILE error condition.
*/
Response.importElementsInvalidFile(Request request)
: this(request.id,
error: new RequestError(
RequestErrorCode.IMPORT_ELEMENTS_INVALID_FILE,
'Error during `edit.importElements`: invalid file.'));
/**
* Initialize a newly created instance to represent an error condition caused
* by an analysis.reanalyze [request] that specifies an analysis root that is

View file

@ -83,7 +83,6 @@ const String ANALYSIS_REQUEST_UPDATE_OPTIONS = 'analysis.updateOptions';
const String ANALYSIS_REQUEST_UPDATE_OPTIONS_OPTIONS = 'options';
const String ANALYSIS_RESPONSE_GET_ERRORS_ERRORS = 'errors';
const String ANALYSIS_RESPONSE_GET_HOVER_HOVERS = 'hovers';
const String ANALYSIS_RESPONSE_GET_IMPORTED_ELEMENTS_COMPLETE = 'complete';
const String ANALYSIS_RESPONSE_GET_IMPORTED_ELEMENTS_ELEMENTS = 'elements';
const String ANALYSIS_RESPONSE_GET_LIBRARY_DEPENDENCIES_LIBRARIES = 'libraries';
const String ANALYSIS_RESPONSE_GET_LIBRARY_DEPENDENCIES_PACKAGE_MAP =
@ -179,7 +178,6 @@ const String EDIT_RESPONSE_GET_REFACTORING_POTENTIAL_EDITS = 'potentialEdits';
const String EDIT_RESPONSE_GET_STATEMENT_COMPLETION_CHANGE = 'change';
const String EDIT_RESPONSE_GET_STATEMENT_COMPLETION_WHITESPACE_ONLY =
'whitespaceOnly';
const String EDIT_RESPONSE_IMPORT_ELEMENTS_COMPLETE = 'complete';
const String EDIT_RESPONSE_IMPORT_ELEMENTS_EDITS = 'edits';
const String EDIT_RESPONSE_IS_POSTFIX_COMPLETION_APPLICABLE_VALUE = 'value';
const String EDIT_RESPONSE_LIST_POSTFIX_COMPLETION_TEMPLATES_TEMPLATES =

View file

@ -1044,7 +1044,6 @@ class AnalysisGetImportedElementsParams implements RequestParams {
*
* {
* "elements": List<ImportedElements>
* "complete": bool
* }
*
* Clients may not extend, implement or mix-in this class.
@ -1052,8 +1051,6 @@ class AnalysisGetImportedElementsParams implements RequestParams {
class AnalysisGetImportedElementsResult implements ResponseResult {
List<ImportedElements> _elements;
bool _complete;
/**
* The information about the elements that are referenced in the specified
* region of the specified file that come from imported libraries.
@ -1069,29 +1066,8 @@ class AnalysisGetImportedElementsResult implements ResponseResult {
this._elements = value;
}
/**
* True if all of the elements that are referenced in the specified region
* are included in the list of elements. The list of elements will be
* incomplete if there is an error in the specified region that prevents an
* identifier from being resolved to a single element.
*/
bool get complete => _complete;
/**
* True if all of the elements that are referenced in the specified region
* are included in the list of elements. The list of elements will be
* incomplete if there is an error in the specified region that prevents an
* identifier from being resolved to a single element.
*/
void set complete(bool value) {
assert(value != null);
this._complete = value;
}
AnalysisGetImportedElementsResult(
List<ImportedElements> elements, bool complete) {
AnalysisGetImportedElementsResult(List<ImportedElements> elements) {
this.elements = elements;
this.complete = complete;
}
factory AnalysisGetImportedElementsResult.fromJson(
@ -1110,14 +1086,7 @@ class AnalysisGetImportedElementsResult implements ResponseResult {
} else {
throw jsonDecoder.mismatch(jsonPath, "elements");
}
bool complete;
if (json.containsKey("complete")) {
complete =
jsonDecoder.decodeBool(jsonPath + ".complete", json["complete"]);
} else {
throw jsonDecoder.mismatch(jsonPath, "complete");
}
return new AnalysisGetImportedElementsResult(elements, complete);
return new AnalysisGetImportedElementsResult(elements);
} else {
throw jsonDecoder.mismatch(
jsonPath, "analysis.getImportedElements result", json);
@ -1136,7 +1105,6 @@ class AnalysisGetImportedElementsResult implements ResponseResult {
Map<String, dynamic> result = {};
result["elements"] =
elements.map((ImportedElements value) => value.toJson()).toList();
result["complete"] = complete;
return result;
}
@ -1152,8 +1120,7 @@ class AnalysisGetImportedElementsResult implements ResponseResult {
bool operator ==(other) {
if (other is AnalysisGetImportedElementsResult) {
return listEqual(elements, other.elements,
(ImportedElements a, ImportedElements b) => a == b) &&
complete == other.complete;
(ImportedElements a, ImportedElements b) => a == b);
}
return false;
}
@ -1162,7 +1129,6 @@ class AnalysisGetImportedElementsResult implements ResponseResult {
int get hashCode {
int hash = 0;
hash = JenkinsSmiHash.combine(hash, elements.hashCode);
hash = JenkinsSmiHash.combine(hash, complete.hashCode);
return JenkinsSmiHash.finish(hash);
}
}
@ -7717,7 +7683,6 @@ class EditImportElementsParams implements RequestParams {
*
* {
* "edits": List<SourceEdit>
* "complete": bool
* }
*
* Clients may not extend, implement or mix-in this class.
@ -7725,8 +7690,6 @@ class EditImportElementsParams implements RequestParams {
class EditImportElementsResult implements ResponseResult {
List<SourceEdit> _edits;
bool _complete;
/**
* The edit(s) to be applied in order to make the specified elements
* accessible.
@ -7742,30 +7705,8 @@ class EditImportElementsResult implements ResponseResult {
this._edits = value;
}
/**
* True if all of the elements that are to be made accessible would be
* accessible if the edits were applied. The edits will not be complete, for
* example, if one of the libraries cannot be referenced in the target
* library or if one of the element names is already imported from a
* different library.
*/
bool get complete => _complete;
/**
* True if all of the elements that are to be made accessible would be
* accessible if the edits were applied. The edits will not be complete, for
* example, if one of the libraries cannot be referenced in the target
* library or if one of the element names is already imported from a
* different library.
*/
void set complete(bool value) {
assert(value != null);
this._complete = value;
}
EditImportElementsResult(List<SourceEdit> edits, bool complete) {
EditImportElementsResult(List<SourceEdit> edits) {
this.edits = edits;
this.complete = complete;
}
factory EditImportElementsResult.fromJson(
@ -7784,14 +7725,7 @@ class EditImportElementsResult implements ResponseResult {
} else {
throw jsonDecoder.mismatch(jsonPath, "edits");
}
bool complete;
if (json.containsKey("complete")) {
complete =
jsonDecoder.decodeBool(jsonPath + ".complete", json["complete"]);
} else {
throw jsonDecoder.mismatch(jsonPath, "complete");
}
return new EditImportElementsResult(edits, complete);
return new EditImportElementsResult(edits);
} else {
throw jsonDecoder.mismatch(jsonPath, "edit.importElements result", json);
}
@ -7808,7 +7742,6 @@ class EditImportElementsResult implements ResponseResult {
Map<String, dynamic> toJson() {
Map<String, dynamic> result = {};
result["edits"] = edits.map((SourceEdit value) => value.toJson()).toList();
result["complete"] = complete;
return result;
}
@ -7824,8 +7757,7 @@ class EditImportElementsResult implements ResponseResult {
bool operator ==(other) {
if (other is EditImportElementsResult) {
return listEqual(
edits, other.edits, (SourceEdit a, SourceEdit b) => a == b) &&
complete == other.complete;
edits, other.edits, (SourceEdit a, SourceEdit b) => a == b);
}
return false;
}
@ -7834,7 +7766,6 @@ class EditImportElementsResult implements ResponseResult {
int get hashCode {
int hash = 0;
hash = JenkinsSmiHash.combine(hash, edits.hashCode);
hash = JenkinsSmiHash.combine(hash, complete.hashCode);
return JenkinsSmiHash.finish(hash);
}
}
@ -12638,6 +12569,7 @@ class RequestError implements HasToJson {
* GET_IMPORTED_ELEMENTS_INVALID_FILE
* GET_NAVIGATION_INVALID_FILE
* GET_REACHABLE_SOURCES_INVALID_FILE
* IMPORT_ELEMENTS_INVALID_FILE
* INVALID_ANALYSIS_ROOT
* INVALID_EXECUTION_CONTEXT
* INVALID_FILE_PATH_FORMAT
@ -12721,6 +12653,13 @@ class RequestErrorCode implements Enum {
static const RequestErrorCode GET_REACHABLE_SOURCES_INVALID_FILE =
const RequestErrorCode._("GET_REACHABLE_SOURCES_INVALID_FILE");
/**
* An "edit.importElements" request specified a FilePath that does not match
* a file currently subject to analysis.
*/
static const RequestErrorCode IMPORT_ELEMENTS_INVALID_FILE =
const RequestErrorCode._("IMPORT_ELEMENTS_INVALID_FILE");
/**
* A path passed as an argument to a request (such as analysis.reanalyze) is
* required to be an analysis root, but isn't.
@ -12853,6 +12792,7 @@ class RequestErrorCode implements Enum {
GET_IMPORTED_ELEMENTS_INVALID_FILE,
GET_NAVIGATION_INVALID_FILE,
GET_REACHABLE_SOURCES_INVALID_FILE,
IMPORT_ELEMENTS_INVALID_FILE,
INVALID_ANALYSIS_ROOT,
INVALID_EXECUTION_CONTEXT,
INVALID_FILE_PATH_FORMAT,
@ -12896,6 +12836,8 @@ class RequestErrorCode implements Enum {
return GET_NAVIGATION_INVALID_FILE;
case "GET_REACHABLE_SOURCES_INVALID_FILE":
return GET_REACHABLE_SOURCES_INVALID_FILE;
case "IMPORT_ELEMENTS_INVALID_FILE":
return IMPORT_ELEMENTS_INVALID_FILE;
case "INVALID_ANALYSIS_ROOT":
return INVALID_ANALYSIS_ROOT;
case "INVALID_EXECUTION_CONTEXT":

View file

@ -0,0 +1,56 @@
// Copyright (c) 2017, 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:analyzer/dart/analysis/results.dart';
import 'package:analyzer/dart/analysis/session.dart';
import 'package:analyzer/dart/element/element.dart';
import 'package:analyzer_plugin/protocol/protocol_common.dart';
import 'package:analyzer_plugin/utilities/change_builder/change_builder_dart.dart';
/**
* An object used to compute the edits required to ensure that a list of
* elements is imported into a given library.
*/
class ImportElementsComputer {
/**
* The analysis session used to compute the unit.
*/
final AnalysisSession session;
/**
* The library element representing the library to which the imports are to be
* added.
*/
final LibraryElement libraryElement;
/**
* The path of the defining compilation unit of the library.
*/
final String path;
/**
* The elements that are to be imported into the library.
*/
final List<ImportedElements> elements;
/**
* Initialize a newly created computer to compute the edits required to ensure
* that the given list of [elements] is imported into a given [library].
*/
ImportElementsComputer(ResolveResult result, this.path, this.elements)
: session = result.session,
libraryElement = result.libraryElement;
/**
* Compute and return the list of edits.
*/
List<SourceEdit> compute() {
DartChangeBuilder builder = new DartChangeBuilder(session);
builder.addFileEdit(path, (DartFileEditBuilder builder) {
// TODO(brianwilkerson) Implement this.
});
return <SourceEdit>[]; // builder.sourceChange
}
}

View file

@ -0,0 +1,43 @@
// Copyright (c) 2017, 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:analyzer/dart/ast/ast.dart';
/**
* An object used to compute the list of elements referenced within a given
* region of a compilation unit that are imported into the compilation unit's
* library.
*/
class ImportedElementsComputer {
/**
* The compilation unit in which the elements are referenced.
*/
final CompilationUnit unit;
/**
* The offset of the region containing the references to be returned.
*/
final int offset;
/**
* The length of the region containing the references to be returned.
*/
final int length;
/**
* Initialize a newly created computer to compute the list of imported
* elements referenced in the given [unit] within the region with the given
* [offset] and [length].
*/
ImportedElementsComputer(this.unit, this.offset, this.length);
/**
* Compute and return the list of imported elements.
*/
List<ImportedElements> compute() {
// TODO(brianwilkerson) Implement this.
return <ImportedElements>[];
}
}

View file

@ -9,6 +9,7 @@ import 'package:analysis_server/plugin/analysis/analysis_domain.dart';
import 'package:analysis_server/protocol/protocol_constants.dart';
import 'package:analysis_server/src/analysis_server.dart';
import 'package:analysis_server/src/computer/computer_hover.dart';
import 'package:analysis_server/src/computer/imported_elements_computer.dart';
import 'package:analysis_server/src/domain_abstract.dart';
import 'package:analysis_server/src/domains/analysis/navigation.dart';
import 'package:analysis_server/src/domains/analysis/navigation_dart.dart';
@ -99,6 +100,32 @@ class AnalysisDomainHandler extends AbstractRequestHandler {
new AnalysisGetHoverResult(hovers).toResponse(request.id));
}
/**
* Implement the `analysis.getImportedElements` request.
*/
Future<Null> getImportedElements(Request request) async {
AnalysisGetImportedElementsParams params =
new AnalysisGetImportedElementsParams.fromRequest(request);
//
// Prepare the resolved unit.
//
AnalysisResult result = await server.getAnalysisResult(params.file);
if (result == null) {
server.sendResponse(new Response.getImportedElementsInvalidFile(request));
}
//
// Compute the list of imported elements.
//
List<ImportedElements> elements =
new ImportedElementsComputer(result.unit, params.offset, params.length)
.compute();
//
// Send the response.
//
server.sendResponse(
new AnalysisGetImportedElementsResult(elements).toResponse(request.id));
}
/**
* Implement the `analysis.getLibraryDependencies` request.
*/
@ -216,6 +243,9 @@ class AnalysisDomainHandler extends AbstractRequestHandler {
} else if (requestName == ANALYSIS_REQUEST_GET_HOVER) {
getHover(request);
return Response.DELAYED_RESPONSE;
} else if (requestName == ANALYSIS_REQUEST_GET_IMPORTED_ELEMENTS) {
getImportedElements(request);
return Response.DELAYED_RESPONSE;
} else if (requestName == ANALYSIS_REQUEST_GET_LIBRARY_DEPENDENCIES) {
return getLibraryDependencies(request);
} else if (requestName == ANALYSIS_REQUEST_GET_NAVIGATION) {

View file

@ -11,6 +11,7 @@ import 'package:analysis_server/plugin/edit/fix/fix_dart.dart';
import 'package:analysis_server/protocol/protocol_constants.dart';
import 'package:analysis_server/src/analysis_server.dart';
import 'package:analysis_server/src/collections.dart';
import 'package:analysis_server/src/computer/import_elements_computer.dart';
import 'package:analysis_server/src/domain_abstract.dart';
import 'package:analysis_server/src/plugin/plugin_manager.dart';
import 'package:analysis_server/src/plugin/result_converter.dart';
@ -350,6 +351,9 @@ class EditDomainHandler extends AbstractRequestHandler {
return Response.DELAYED_RESPONSE;
} else if (requestName == EDIT_REQUEST_GET_REFACTORING) {
return _getRefactoring(request);
} else if (requestName == EDIT_REQUEST_IMPORT_ELEMENTS) {
importElements(request);
return Response.DELAYED_RESPONSE;
} else if (requestName == EDIT_REQUEST_ORGANIZE_DIRECTIVES) {
organizeDirectives(request);
return Response.DELAYED_RESPONSE;
@ -376,6 +380,32 @@ class EditDomainHandler extends AbstractRequestHandler {
return null;
}
/**
* Implement the `edit.importElements` request.
*/
Future<Null> importElements(Request request) async {
EditImportElementsParams params =
new EditImportElementsParams.fromRequest(request);
//
// Prepare the resolved unit.
//
AnalysisResult result = await server.getAnalysisResult(params.file);
if (result == null) {
server.sendResponse(new Response.importElementsInvalidFile(request));
}
//
// Compute the edits required to import the required elements.
//
List<SourceEdit> edits =
new ImportElementsComputer(result, params.file, params.elements)
.compute();
//
// Send the response.
//
server.sendResponse(
new EditImportElementsResult(edits).toResponse(request.id));
}
Future isPostfixCompletionApplicable(Request request) async {
var params = new EditGetPostfixCompletionParams.fromRequest(request);
bool value = false;

View file

@ -0,0 +1,76 @@
// Copyright (c) 2017, 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:async';
import 'package:analysis_server/protocol/protocol_generated.dart';
import 'package:test/test.dart';
import 'package:test_reflective_loader/test_reflective_loader.dart';
import '../support/integration_tests.dart';
main() {
defineReflectiveSuite(() {
defineReflectiveTests(AnalysisGetImportedElementsIntegrationTest);
});
}
@reflectiveTest
class AnalysisGetImportedElementsIntegrationTest
extends AbstractAnalysisServerIntegrationTest {
/**
* Pathname of the file containing Dart code.
*/
String pathname;
/**
* Dart code under test.
*/
final String text = r'''
main() {}
''';
/**
* Check that an analysis.getImportedElements request on the region starting
* with the first character that matches [target] and having the given
* [length] matches the given list of [expected] imported elements.
*/
checkElements(
String target, int length, List<ImportedElements> expected) async {
int offset = text.indexOf(target);
AnalysisGetImportedElementsResult result =
await sendAnalysisGetImportedElements(pathname, offset, length);
expect(result.elements, hasLength(expected.length));
// TODO(brianwilkerson) Finish implementing this.
}
/**
* Check that an analysis.getImportedElements request on the region matching
* [target] produces an empty list of elements.
*/
Future<Null> checkNoElements(String target) async {
int offset = text.indexOf(target);
AnalysisGetImportedElementsResult result =
await sendAnalysisGetImportedElements(pathname, offset, target.length);
expect(result.elements, hasLength(0));
}
setUp() {
return super.setUp().then((_) {
pathname = sourcePath('test.dart');
});
}
test_getImportedElements() async {
writeFile(pathname, text);
standardAnalysisSetup();
await analysisFinished;
List<Future> tests = [];
tests.add(checkNoElements('main() {}'));
return Future.wait(tests);
}
}

View file

@ -9,6 +9,7 @@ import 'error_test.dart' as error_test;
import 'get_errors_nonStandard_sdk.dart' as get_errors_nonStandard_sdk;
import 'get_errors_test.dart' as get_errors_test;
import 'get_hover_test.dart' as get_hover_test;
import 'get_imported_elements_test.dart' as get_imported_elements_test;
import 'get_library_dependencies_test.dart' as get_library_dependencies_test;
import 'get_navigation_test.dart' as get_navigation_test;
import 'get_reachable_sources_test.dart' as get_reachable_sources_test;
@ -41,6 +42,7 @@ main() {
get_errors_nonStandard_sdk.main();
get_library_dependencies_test.main();
get_hover_test.main();
get_imported_elements_test.main();
get_navigation_test.main();
get_reachable_sources_test.main();
highlights_test.main();

View file

@ -4,7 +4,7 @@ server calls. This file is validated by `coverage_test.dart`.
## analysis domain
- [x] analysis.getErrors
- [x] analysis.getHover
- [ ] analysis.getImportedElements
- [x] analysis.getImportedElements
- [x] analysis.getLibraryDependencies (failing - see #29310)
- [x] analysis.getNavigation (failing - see #28799)
- [x] analysis.getReachableSources (failing - see #29311)
@ -31,7 +31,7 @@ server calls. This file is validated by `coverage_test.dart`.
- [x] edit.getPostfixCompletion
- [x] edit.getRefactoring
- [x] edit.getStatementCompletion
- [ ] edit.importElements
- [x] edit.importElements
- [x] edit.isPostfixCompletionApplicable
- [x] edit.listPostfixCompletionTemplates
- [x] edit.sortMembers

View file

@ -0,0 +1,73 @@
// Copyright (c) 2017, 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:async';
import 'package:analysis_server/protocol/protocol_generated.dart';
import 'package:analyzer_plugin/protocol/protocol_common.dart';
import 'package:test/test.dart';
import 'package:test_reflective_loader/test_reflective_loader.dart';
import '../support/integration_tests.dart';
main() {
defineReflectiveSuite(() {
defineReflectiveTests(AnalysisGetImportElementsIntegrationTest);
});
}
@reflectiveTest
class AnalysisGetImportElementsIntegrationTest
extends AbstractAnalysisServerIntegrationTest {
/**
* Pathname of the file containing Dart code.
*/
String pathname;
/**
* Dart code under test.
*/
final String text = r'''
''';
/**
* Check that an edit.importElements request with the given list of [elements]
* produces the [expected] list of edits.
*/
checkEdits(List<ImportedElements> elements, List<SourceEdit> expected) async {
EditImportElementsResult result =
await sendEditImportElements(pathname, elements);
expect(result.edits, hasLength(expected.length));
// TODO(brianwilkerson) Finish implementing this.
}
/**
* Check that an edit.importElements request with the given list of [elements]
* produces no edits.
*/
Future<Null> checkNoEdits(List<ImportedElements> elements) async {
EditImportElementsResult result =
await sendEditImportElements(pathname, <ImportedElements>[]);
expect(result.edits, hasLength(0));
}
setUp() {
return super.setUp().then((_) {
pathname = sourcePath('test.dart');
});
}
test_getImportedElements() async {
writeFile(pathname, text);
standardAnalysisSetup();
await analysisFinished;
List<Future> tests = [];
// Test that an empty list of elements produces no edits.
tests.add(checkNoEdits(<ImportedElements>[]));
return Future.wait(tests);
}
}

View file

@ -9,9 +9,10 @@ import 'get_assists_test.dart' as get_assists_test;
import 'get_available_refactorings_test.dart'
as get_available_refactorings_test;
import 'get_fixes_test.dart' as get_fixes_test;
import 'get_refactoring_test.dart' as get_refactoring_test;
import 'get_postfix_completion_test.dart' as get_postfix_completion_test;
import 'get_refactoring_test.dart' as get_refactoring_test;
import 'get_statement_completion_test.dart' as get_statement_completion_test;
import 'import_elements_test.dart' as import_elements_test;
import 'is_postfix_completion_applicable_test.dart'
as is_postfix_completion_applicable_test;
import 'list_postfix_completion_templates_test.dart'
@ -28,6 +29,7 @@ main() {
get_refactoring_test.main();
get_postfix_completion_test.main();
get_statement_completion_test.main();
import_elements_test.main();
is_postfix_completion_applicable_test.main();
list_postfix_completion_templates_test.main();
organize_directives_test.main();

View file

@ -265,13 +265,6 @@ abstract class IntegrationTestMixin {
*
* The information about the elements that are referenced in the specified
* region of the specified file that come from imported libraries.
*
* complete: bool
*
* True if all of the elements that are referenced in the specified region
* are included in the list of elements. The list of elements will be
* incomplete if there is an error in the specified region that prevents an
* identifier from being resolved to a single element.
*/
Future<AnalysisGetImportedElementsResult> sendAnalysisGetImportedElements(
String file, int offset, int length) async {
@ -1625,6 +1618,11 @@ abstract class IntegrationTestMixin {
* that all of the elements in the specified list of imported elements are
* accessible within the library.
*
* If a request is made for a file that does not exist, or that is not
* currently subject to analysis (e.g. because it is not associated with any
* analysis root specified via analysis.setAnalysisRoots), an error of type
* IMPORT_ELEMENTS_INVALID_FILE will be generated.
*
* Parameters
*
* file: FilePath
@ -1641,14 +1639,6 @@ abstract class IntegrationTestMixin {
*
* The edit(s) to be applied in order to make the specified elements
* accessible.
*
* complete: bool
*
* True if all of the elements that are to be made accessible would be
* accessible if the edits were applied. The edits will not be complete,
* for example, if one of the libraries cannot be referenced in the target
* library or if one of the element names is already imported from a
* different library.
*/
Future<EditImportElementsResult> sendEditImportElements(
String file, List<ImportedElements> elements) async {

View file

@ -1030,6 +1030,7 @@ final Matcher isRequestError = new LazyMatcher(() => new MatchesJsonObject(
* GET_IMPORTED_ELEMENTS_INVALID_FILE
* GET_NAVIGATION_INVALID_FILE
* GET_REACHABLE_SOURCES_INVALID_FILE
* IMPORT_ELEMENTS_INVALID_FILE
* INVALID_ANALYSIS_ROOT
* INVALID_EXECUTION_CONTEXT
* INVALID_FILE_PATH_FORMAT
@ -1058,6 +1059,7 @@ final Matcher isRequestErrorCode = new MatchesEnum("RequestErrorCode", [
"GET_IMPORTED_ELEMENTS_INVALID_FILE",
"GET_NAVIGATION_INVALID_FILE",
"GET_REACHABLE_SOURCES_INVALID_FILE",
"IMPORT_ELEMENTS_INVALID_FILE",
"INVALID_ANALYSIS_ROOT",
"INVALID_EXECUTION_CONTEXT",
"INVALID_FILE_PATH_FORMAT",
@ -1312,12 +1314,11 @@ final Matcher isAnalysisGetImportedElementsParams = new LazyMatcher(() =>
*
* {
* "elements": List<ImportedElements>
* "complete": bool
* }
*/
final Matcher isAnalysisGetImportedElementsResult = new LazyMatcher(() =>
new MatchesJsonObject("analysis.getImportedElements result",
{"elements": isListOf(isImportedElements), "complete": isBool}));
{"elements": isListOf(isImportedElements)}));
/**
* analysis.getLibraryDependencies params
@ -1988,12 +1989,11 @@ final Matcher isEditImportElementsParams = new LazyMatcher(() =>
*
* {
* "edits": List<SourceEdit>
* "complete": bool
* }
*/
final Matcher isEditImportElementsResult = new LazyMatcher(() =>
new MatchesJsonObject("edit.importElements result",
{"edits": isListOf(isSourceEdit), "complete": isBool}));
new MatchesJsonObject(
"edit.importElements result", {"edits": isListOf(isSourceEdit)}));
/**
* edit.isPostfixCompletionApplicable params

View file

@ -502,6 +502,10 @@ public interface AnalysisServer {
* Return a list of edits that would need to be applied in order to ensure that all of the elements
* in the specified list of imported elements are accessible within the library.
*
* If a request is made for a file that does not exist, or that is not currently subject to
* analysis (e.g. because it is not associated with any analysis root specified via
* analysis.setAnalysisRoots), an error of type IMPORT_ELEMENTS_INVALID_FILE will be generated.
*
* @param file The file in which the specified elements are to be made accessible.
* @param elements The elements to be made accessible in the specified file.
*/

View file

@ -75,6 +75,12 @@ public class RequestErrorCode {
*/
public static final String GET_REACHABLE_SOURCES_INVALID_FILE = "GET_REACHABLE_SOURCES_INVALID_FILE";
/**
* An "edit.importElements" request specified a FilePath that does not match a file currently
* subject to analysis.
*/
public static final String IMPORT_ELEMENTS_INVALID_FILE = "IMPORT_ELEMENTS_INVALID_FILE";
/**
* A path passed as an argument to a request (such as analysis.reanalyze) is required to be an
* analysis root, but isn't.

View file

@ -475,15 +475,6 @@
libraries.
</p>
</field>
<field name="complete">
<ref>bool</ref>
<p>
True if all of the elements that are referenced in the specified
region are included in the list of elements. The list of elements will
be incomplete if there is an error in the specified region that
prevents an identifier from being resolved to a single element.
</p>
</field>
</result>
</request>
<request method="getLibraryDependencies">
@ -2083,6 +2074,12 @@
that all of the elements in the specified list of imported elements are
accessible within the library.
</p>
<p>
If a request is made for a file that does not exist, or that is not
currently subject to analysis (e.g. because it is not associated with any
analysis root specified via analysis.setAnalysisRoots), an error of type
<tt>IMPORT_ELEMENTS_INVALID_FILE</tt> will be generated.
</p>
<params>
<field name="file">
<ref>FilePath</ref>
@ -2109,16 +2106,6 @@
accessible.
</p>
</field>
<field name="complete">
<ref>bool</ref>
<p>
True if all of the elements that are to be made accessible would be
accessible if the edits were applied. The edits will not be complete,
for example, if one of the libraries cannot be referenced in the
target library or if one of the element names is already imported from
a different library.
</p>
</field>
</result>
</request>
<request method="sortMembers">
@ -3148,6 +3135,13 @@
analysis.
</p>
</value>
<value>
<code>IMPORT_ELEMENTS_INVALID_FILE</code>
<p>
An "edit.importElements" request specified a FilePath that does not
match a file currently subject to analysis.
</p>
</value>
<value>
<code>INVALID_ANALYSIS_ROOT</code>
<p>