diff --git a/pkg/analysis_server/lib/protocol/protocol_constants.dart b/pkg/analysis_server/lib/protocol/protocol_constants.dart index 02de8b57230..d7651acbf06 100644 --- a/pkg/analysis_server/lib/protocol/protocol_constants.dart +++ b/pkg/analysis_server/lib/protocol/protocol_constants.dart @@ -238,6 +238,7 @@ const String SEARCH_REQUEST_FIND_TOP_LEVEL_DECLARATIONS = const String SEARCH_REQUEST_FIND_TOP_LEVEL_DECLARATIONS_PATTERN = 'pattern'; const String SEARCH_REQUEST_GET_ELEMENT_DECLARATIONS = 'search.getElementDeclarations'; +const String SEARCH_REQUEST_GET_ELEMENT_DECLARATIONS_FILE = 'file'; const String SEARCH_REQUEST_GET_ELEMENT_DECLARATIONS_MAX_RESULTS = 'maxResults'; const String SEARCH_REQUEST_GET_ELEMENT_DECLARATIONS_PATTERN = 'pattern'; const String SEARCH_REQUEST_GET_TYPE_HIERARCHY = 'search.getTypeHierarchy'; diff --git a/pkg/analysis_server/lib/protocol/protocol_generated.dart b/pkg/analysis_server/lib/protocol/protocol_generated.dart index 07bc62954dc..54ffbeec7b9 100644 --- a/pkg/analysis_server/lib/protocol/protocol_generated.dart +++ b/pkg/analysis_server/lib/protocol/protocol_generated.dart @@ -15557,6 +15557,7 @@ class SearchFindTopLevelDeclarationsResult implements ResponseResult { * search.getElementDeclarations params * * { + * "file": optional FilePath * "pattern": optional String * "maxResults": optional int * } @@ -15564,10 +15565,26 @@ class SearchFindTopLevelDeclarationsResult implements ResponseResult { * Clients may not extend, implement or mix-in this class. */ class SearchGetElementDeclarationsParams implements RequestParams { + String _file; + String _pattern; int _maxResults; + /** + * If this field is provided, return only declarations in this file. If this + * field is missing, return declarations in all files. + */ + String get file => _file; + + /** + * If this field is provided, return only declarations in this file. If this + * field is missing, return declarations in all files. + */ + void set file(String value) { + this._file = value; + } + /** * The regular expression used to match the names of declarations. If this * field is missing, return all declarations. @@ -15596,7 +15613,9 @@ class SearchGetElementDeclarationsParams implements RequestParams { this._maxResults = value; } - SearchGetElementDeclarationsParams({String pattern, int maxResults}) { + SearchGetElementDeclarationsParams( + {String file, String pattern, int maxResults}) { + this.file = file; this.pattern = pattern; this.maxResults = maxResults; } @@ -15607,6 +15626,10 @@ class SearchGetElementDeclarationsParams implements RequestParams { json = {}; } if (json is Map) { + String file; + if (json.containsKey("file")) { + file = jsonDecoder.decodeString(jsonPath + ".file", json["file"]); + } String pattern; if (json.containsKey("pattern")) { pattern = @@ -15618,7 +15641,7 @@ class SearchGetElementDeclarationsParams implements RequestParams { jsonDecoder.decodeInt(jsonPath + ".maxResults", json["maxResults"]); } return new SearchGetElementDeclarationsParams( - pattern: pattern, maxResults: maxResults); + file: file, pattern: pattern, maxResults: maxResults); } else { throw jsonDecoder.mismatch( jsonPath, "search.getElementDeclarations params", json); @@ -15633,6 +15656,9 @@ class SearchGetElementDeclarationsParams implements RequestParams { @override Map toJson() { Map result = {}; + if (file != null) { + result["file"] = file; + } if (pattern != null) { result["pattern"] = pattern; } @@ -15653,7 +15679,9 @@ class SearchGetElementDeclarationsParams implements RequestParams { @override bool operator ==(other) { if (other is SearchGetElementDeclarationsParams) { - return pattern == other.pattern && maxResults == other.maxResults; + return file == other.file && + pattern == other.pattern && + maxResults == other.maxResults; } return false; } @@ -15661,6 +15689,7 @@ class SearchGetElementDeclarationsParams implements RequestParams { @override int get hashCode { int hash = 0; + hash = JenkinsSmiHash.combine(hash, file.hashCode); hash = JenkinsSmiHash.combine(hash, pattern.hashCode); hash = JenkinsSmiHash.combine(hash, maxResults.hashCode); return JenkinsSmiHash.finish(hash); diff --git a/pkg/analysis_server/lib/src/search/search_domain.dart b/pkg/analysis_server/lib/src/search/search_domain.dart index ecdce2a0a99..d3ffa605a9a 100644 --- a/pkg/analysis_server/lib/src/search/search_domain.dart +++ b/pkg/analysis_server/lib/src/search/search_domain.dart @@ -180,8 +180,9 @@ class SearchDomainHandler implements protocol.RequestHandler { int remainingMaxResults = params.maxResults; for (var driver in server.driverMap.values.toList()) { - var driverDeclarations = - await driver.search.declarations(regExp, remainingMaxResults, files); + var driverDeclarations = await driver.search.declarations( + regExp, remainingMaxResults, files, + onlyForFile: params.file); declarations.addAll(driverDeclarations); if (remainingMaxResults != null) { diff --git a/pkg/analysis_server/test/integration/support/integration_test_methods.dart b/pkg/analysis_server/test/integration/support/integration_test_methods.dart index f1c05fc93d4..cf284ec6f05 100644 --- a/pkg/analysis_server/test/integration/support/integration_test_methods.dart +++ b/pkg/analysis_server/test/integration/support/integration_test_methods.dart @@ -1201,6 +1201,11 @@ abstract class IntegrationTestMixin { * * Parameters * + * file: FilePath (optional) + * + * If this field is provided, return only declarations in this file. If + * this field is missing, return declarations in all files. + * * pattern: String (optional) * * The regular expression used to match the names of declarations. If this @@ -1222,9 +1227,9 @@ abstract class IntegrationTestMixin { * The list of the paths of files with declarations. */ Future sendSearchGetElementDeclarations( - {String pattern, int maxResults}) async { + {String file, String pattern, int maxResults}) async { var params = new SearchGetElementDeclarationsParams( - pattern: pattern, maxResults: maxResults) + file: file, pattern: pattern, maxResults: maxResults) .toJson(); var result = await server.send("search.getElementDeclarations", params); ResponseDecoder decoder = new ResponseDecoder(null); diff --git a/pkg/analysis_server/test/integration/support/protocol_matchers.dart b/pkg/analysis_server/test/integration/support/protocol_matchers.dart index 6a6dc6a3ed5..966801efacb 100644 --- a/pkg/analysis_server/test/integration/support/protocol_matchers.dart +++ b/pkg/analysis_server/test/integration/support/protocol_matchers.dart @@ -2683,13 +2683,18 @@ final Matcher isSearchFindTopLevelDeclarationsResult = new LazyMatcher(() => * search.getElementDeclarations params * * { + * "file": optional FilePath * "pattern": optional String * "maxResults": optional int * } */ final Matcher isSearchGetElementDeclarationsParams = new LazyMatcher(() => new MatchesJsonObject("search.getElementDeclarations params", null, - optionalFields: {"pattern": isString, "maxResults": isInt})); + optionalFields: { + "file": isFilePath, + "pattern": isString, + "maxResults": isInt + })); /** * search.getElementDeclarations result diff --git a/pkg/analysis_server/test/search/declarations_test.dart b/pkg/analysis_server/test/search/declarations_test.dart index 4feda64fbf8..71bf567f971 100644 --- a/pkg/analysis_server/test/search/declarations_test.dart +++ b/pkg/analysis_server/test/search/declarations_test.dart @@ -126,6 +126,21 @@ class D {} } } + test_onlyForFile() async { + var a = newFile(join(testFolder, 'a.dart'), content: 'class A {}').path; + newFile(join(testFolder, 'b.dart'), content: 'class B {}').path; + + await _getDeclarations(file: a); + + expect(declarationsResult.files, [a]); + expect(declarationsResult.declarations, hasLength(1)); + + var declaration = declarationsResult.declarations[0]; + expect(declaration.name, 'A'); + expect(declaration.kind, ElementKind.CLASS); + expect(declarationsResult.files[declaration.fileIndex], a); + } + test_parameters() async { addTestFile(r''' void f(bool a, String b) {} @@ -170,9 +185,10 @@ typedef tf2 = int Function(T tp, S sp); assertHas('tf2', ElementKind.FUNCTION_TYPE_ALIAS); } - Future _getDeclarations({String pattern, int maxResults}) async { + Future _getDeclarations( + {String file, String pattern, int maxResults}) async { Request request = new SearchGetElementDeclarationsParams( - pattern: pattern, maxResults: maxResults) + file: file, pattern: pattern, maxResults: maxResults) .toRequest('0'); Response response = await waitResponse(request); diff --git a/pkg/analysis_server/tool/spec/generated/java/AnalysisServer.java b/pkg/analysis_server/tool/spec/generated/java/AnalysisServer.java index f1f240163d0..e551044bc63 100644 --- a/pkg/analysis_server/tool/spec/generated/java/AnalysisServer.java +++ b/pkg/analysis_server/tool/spec/generated/java/AnalysisServer.java @@ -734,12 +734,14 @@ public interface AnalysisServer { * * Return top-level and class member declarations. * + * @param file If this field is provided, return only declarations in this file. If this field is + * missing, return declarations in all files. * @param pattern The regular expression used to match the names of declarations. If this field is * missing, return all declarations. * @param maxResults The maximum number of declarations to return. If this field is missing, return * all matching declarations. */ - public void search_getElementDeclarations(String pattern, int maxResults, GetElementDeclarationsConsumer consumer); + public void search_getElementDeclarations(String file, String pattern, int maxResults, GetElementDeclarationsConsumer consumer); /** * {@code search.getTypeHierarchy} diff --git a/pkg/analysis_server/tool/spec/spec_input.html b/pkg/analysis_server/tool/spec/spec_input.html index 5be66aea9e6..92aeb4f7a49 100644 --- a/pkg/analysis_server/tool/spec/spec_input.html +++ b/pkg/analysis_server/tool/spec/spec_input.html @@ -1579,6 +1579,13 @@ Return top-level and class member declarations.

+ + FilePath +

+ If this field is provided, return only declarations in this file. + If this field is missing, return declarations in all files. +

+
String

diff --git a/pkg/analyzer/lib/src/dart/analysis/search.dart b/pkg/analyzer/lib/src/dart/analysis/search.dart index 6b8d5e36082..00b550c58dc 100644 --- a/pkg/analyzer/lib/src/dart/analysis/search.dart +++ b/pkg/analyzer/lib/src/dart/analysis/search.dart @@ -118,7 +118,8 @@ class Search { * we just want reduce amount of data, not to make it absolute minimum. */ Future> declarations( - RegExp regExp, int maxResults, List files) async { + RegExp regExp, int maxResults, List files, + {String onlyForFile}) async { List declarations = []; UnlinkedUnit unlinkedUnit; @@ -179,6 +180,10 @@ class Search { try { for (String path in _driver.addedFiles) { + if (onlyForFile != null && path != onlyForFile) { + continue; + } + FileState file = _driver.fsState.getFileForPath(path); int fileIndex; diff --git a/pkg/analyzer/test/src/dart/analysis/search_test.dart b/pkg/analyzer/test/src/dart/analysis/search_test.dart index d2a4e23f537..933ade73115 100644 --- a/pkg/analyzer/test/src/dart/analysis/search_test.dart +++ b/pkg/analyzer/test/src/dart/analysis/search_test.dart @@ -157,20 +157,23 @@ class C {} expect(declarations, hasLength(2)); } - test_declarations_regExp() async { - await _resolveTestUnit(''' -class A {} -class B {} -class C {} -class D {} -'''); + test_declarations_onlyForFile() async { + var a = _p('/test/lib/a.dart'); + var b = _p('/test/lib/b.dart'); + provider.newFile(a, 'class A {}'); + provider.newFile(b, 'class B {}'); + + driver.addFile(a); + driver.addFile(b); + var files = []; List declarations = - await driver.search.declarations(new RegExp(r'[A-C]'), null, files); - _assertHasDeclaration(declarations, 'A', DeclarationKind.CLASS); + await driver.search.declarations(null, null, files, onlyForFile: b); + + expect(files, [b]); + + _assertNoDeclaration(declarations, 'A'); _assertHasDeclaration(declarations, 'B', DeclarationKind.CLASS); - _assertHasDeclaration(declarations, 'C', DeclarationKind.CLASS); - _assertNoDeclaration(declarations, 'D'); } test_declarations_parameters() async { @@ -211,6 +214,22 @@ typedef F(int a); expect(declaration.parameters, '(int a)'); } + test_declarations_regExp() async { + await _resolveTestUnit(''' +class A {} +class B {} +class C {} +class D {} +'''); + var files = []; + List declarations = + await driver.search.declarations(new RegExp(r'[A-C]'), null, files); + _assertHasDeclaration(declarations, 'A', DeclarationKind.CLASS); + _assertHasDeclaration(declarations, 'B', DeclarationKind.CLASS); + _assertHasDeclaration(declarations, 'C', DeclarationKind.CLASS); + _assertNoDeclaration(declarations, 'D'); + } + test_declarations_top() async { await _resolveTestUnit(''' int get g => 0;