diff --git a/pkg/analysis_server/doc/api.html b/pkg/analysis_server/doc/api.html index 38a28ab9735..9f6e6d98a67 100644 --- a/pkg/analysis_server/doc/api.html +++ b/pkg/analysis_server/doc/api.html @@ -43,7 +43,7 @@ dt.typeDefinition {

Analysis Server API Specification

-

Version 1.7.0

+

Version 1.8.0

This document contains a specification of the API provided by the analysis server. The API in this document is currently under @@ -384,6 +384,8 @@ dt.typeDefinition { + + @@ -506,6 +508,10 @@ dt.typeDefinition { Return library dependency information for use in client-side indexing and package URI resolution.

+

+ Clients that are only using the libraries field should consider using the + analyzedFiles notification instead. +

Returns

libraries ( List<FilePath> )
@@ -705,6 +711,30 @@ dt.typeDefinition { or the empty map is specified, that indicates that the normal pubspec.yaml mechanism should always be used.

+
analysis.setGeneralSubscriptions (#)
request: {
+  "id": String
+  "method": "analysis.setGeneralSubscriptions"
+  "params": {
+    "subscriptions": List<GeneralAnalysisService>
+  }
+}

response: {
+  "id": String
+  "error": optional RequestError
+}
+

+ Subscribe for general services (that is, services that are not + specific to individual files). All previous subscriptions are replaced + by the given set of services. +

+

+ It is an error if any of the elements in the list are not valid + services. If there is an error, then the current subscriptions will + remain unchanged. +

+ +

Parameters

subscriptions ( List<GeneralAnalysisService> )
+ +

A list of the services being subscribed to.

analysis.setPriorityFiles (#)
request: {
   "id": String
   "method": "analysis.setPriorityFiles"
@@ -757,11 +787,11 @@ dt.typeDefinition {
   "error": optional RequestError
 }

- Subscribe for services. All previous subscriptions are - replaced by the current set of subscriptions. If a given - service is not included as a key in the map then no files - will be subscribed to the service, exactly as if the service - had been included in the map with an explicit empty list of + Subscribe for services that are specific to individual files. + All previous subscriptions are replaced by the current set of + subscriptions. If a given service is not included as a key in the map + then no files will be subscribed to the service, exactly as if the + service had been included in the map with an explicit empty list of files.

@@ -849,7 +879,27 @@ dt.typeDefinition {

The options that are to be used to control analysis.

-

Notifications

analysis.errors (#)
notification: {
+          

Notifications

analysis.analyzedFiles (#)
notification: {
+  "event": "analysis.analyzedFiles"
+  "params": {
+    "directories": List<FilePath>
+  }
+}
+

+ Reports the paths of the files that are being analyzed. +

+

+ This notification is not subscribed to by default. Clients can + subscribe by including the value "ANALYZED_FILES" in the list + of services passed in an analysis.setGeneralSubscriptions request. +

+ +

Parameters

directories ( List<FilePath> )
+ +

+ A list of the paths of the files that are being analyzed. +

+
analysis.errors (#)
notification: {
   "event": "analysis.errors"
   "params": {
     "file": FilePath
@@ -2148,6 +2198,7 @@ dt.typeDefinition {
       
       
       
+      
       
       
     
AddContentOverlay: object
@@ -2283,11 +2334,17 @@ dt.typeDefinition {

AnalysisService: String

- An enumeration of the services provided by the analysis - domain. + An enumeration of the services provided by the analysis domain that + are related to a specific list of files.

-
FOLDING
HIGHLIGHTS
INVALIDATE
NAVIGATION
OCCURRENCES
OUTLINE
OVERRIDES
AnalysisStatus: object
+
FOLDING
HIGHLIGHTS
INVALIDATE
+ +

+ This service is not currently implemented and will become a + GeneralAnalysisService in a future release. +

+
NAVIGATION
OCCURRENCES
OUTLINE
OVERRIDES
AnalysisStatus: object

An indication of the current state of analysis.

@@ -2633,7 +2690,13 @@ dt.typeDefinition {

The length of the region to be folded.

-
HighlightRegion: object
+
GeneralAnalysisService: String
+

+ An enumeration of the services provided by the analysis domain that are + general in nature (that is, are not specific to some list of files). +

+ +
ANALYZED_FILES
HighlightRegion: object

A description of a region that could have special highlighting associated with it. diff --git a/pkg/analysis_server/lib/src/analysis_server.dart b/pkg/analysis_server/lib/src/analysis_server.dart index 1d810078038..1f4aa91dfcf 100644 --- a/pkg/analysis_server/lib/src/analysis_server.dart +++ b/pkg/analysis_server/lib/src/analysis_server.dart @@ -72,7 +72,7 @@ class AnalysisServer { * The version of the analysis server. The value should be replaced * automatically during the build. */ - static final String VERSION = '1.7.0'; + static final String VERSION = '1.8.0'; /** * The number of milliseconds to perform operations before inserting @@ -163,6 +163,12 @@ class AnalysisServer { */ Set serverServices = new HashSet(); + /** + * A set of the [GeneralAnalysisService]s to send notifications for. + */ + Set generalAnalysisServices = + new HashSet(); + /** * A table mapping [AnalysisService]s to the file paths for which these * notifications should be sent. @@ -761,6 +767,10 @@ class AnalysisServer { ServerPerformanceStatistics.intertask.makeCurrent(); _schedulePerformOperation(); } else { + if (generalAnalysisServices + .contains(GeneralAnalysisService.ANALYZED_FILES)) { + sendAnalysisNotificationAnalyzedFiles(this); + } sendStatusNotification(null); if (_onAnalysisCompleteCompleter != null) { _onAnalysisCompleteCompleter.complete(); @@ -949,6 +959,21 @@ class AnalysisServer { this.analysisServices = subscriptions; } + /** + * Implementation for `analysis.setGeneralSubscriptions`. + */ + void setGeneralAnalysisSubscriptions( + List subscriptions) { + Set newServices = subscriptions.toSet(); + if (newServices.contains(GeneralAnalysisService.ANALYZED_FILES) && + !generalAnalysisServices + .contains(GeneralAnalysisService.ANALYZED_FILES) && + isAnalysisComplete()) { + sendAnalysisNotificationAnalyzedFiles(this); + } + generalAnalysisServices = newServices; + } + /** * Set the priority files to the given [files]. */ diff --git a/pkg/analysis_server/lib/src/constants.dart b/pkg/analysis_server/lib/src/constants.dart index 63dc2970d58..b4acd97b546 100644 --- a/pkg/analysis_server/lib/src/constants.dart +++ b/pkg/analysis_server/lib/src/constants.dart @@ -28,6 +28,8 @@ const String ANALYSIS_GET_LIBRARY_DEPENDENCIES = const String ANALYSIS_GET_NAVIGATION = 'analysis.getNavigation'; const String ANALYSIS_REANALYZE = 'analysis.reanalyze'; const String ANALYSIS_SET_ANALYSIS_ROOTS = 'analysis.setAnalysisRoots'; +const String ANALYSIS_SET_GENERAL_SUBSCRIPTIONS = + 'analysis.setGeneralSubscriptions'; const String ANALYSIS_SET_PRIORITY_FILES = 'analysis.setPriorityFiles'; const String ANALYSIS_SET_SUBSCRIPTIONS = 'analysis.setSubscriptions'; const String ANALYSIS_UPDATE_CONTENT = 'analysis.updateContent'; @@ -36,6 +38,7 @@ const String ANALYSIS_UPDATE_OPTIONS = 'analysis.updateOptions'; // // Analysis notifications // +const String ANALYSIS_ANALYZED_FILES = 'analysis.analyzedFiles'; const String ANALYSIS_ERRORS = 'analysis.errors'; const String ANALYSIS_HIGHLIGHTS = 'analysis.highlights'; const String ANALYSIS_NAVIGATION = 'analysis.navigation'; diff --git a/pkg/analysis_server/lib/src/domain_analysis.dart b/pkg/analysis_server/lib/src/domain_analysis.dart index 8a574069958..42afae33f24 100644 --- a/pkg/analysis_server/lib/src/domain_analysis.dart +++ b/pkg/analysis_server/lib/src/domain_analysis.dart @@ -168,6 +168,8 @@ class AnalysisDomainHandler implements RequestHandler { return reanalyze(request); } else if (requestName == ANALYSIS_SET_ANALYSIS_ROOTS) { return setAnalysisRoots(request); + } else if (requestName == ANALYSIS_SET_GENERAL_SUBSCRIPTIONS) { + return setGeneralSubscriptions(request); } else if (requestName == ANALYSIS_SET_PRIORITY_FILES) { return setPriorityFiles(request); } else if (requestName == ANALYSIS_SET_SUBSCRIPTIONS) { @@ -218,6 +220,16 @@ class AnalysisDomainHandler implements RequestHandler { return new AnalysisSetAnalysisRootsResult().toResponse(request.id); } + /** + * Implement the 'analysis.setGeneralSubscriptions' request. + */ + Response setGeneralSubscriptions(Request request) { + AnalysisSetGeneralSubscriptionsParams params = + new AnalysisSetGeneralSubscriptionsParams.fromRequest(request); + server.setGeneralAnalysisSubscriptions(params.subscriptions); + return new AnalysisSetGeneralSubscriptionsResult().toResponse(request.id); + } + /** * Implement the 'analysis.setPriorityFiles' request. */ diff --git a/pkg/analysis_server/lib/src/generated_protocol.dart b/pkg/analysis_server/lib/src/generated_protocol.dart index 66e92bad330..b85b9b841b2 100644 --- a/pkg/analysis_server/lib/src/generated_protocol.dart +++ b/pkg/analysis_server/lib/src/generated_protocol.dart @@ -1581,6 +1581,105 @@ class AnalysisSetAnalysisRootsResult { } } +/** + * analysis.setGeneralSubscriptions params + * + * { + * "subscriptions": List + * } + */ +class AnalysisSetGeneralSubscriptionsParams implements HasToJson { + List _subscriptions; + + /** + * A list of the services being subscribed to. + */ + List get subscriptions => _subscriptions; + + /** + * A list of the services being subscribed to. + */ + void set subscriptions(List value) { + assert(value != null); + this._subscriptions = value; + } + + AnalysisSetGeneralSubscriptionsParams(List subscriptions) { + this.subscriptions = subscriptions; + } + + factory AnalysisSetGeneralSubscriptionsParams.fromJson(JsonDecoder jsonDecoder, String jsonPath, Object json) { + if (json == null) { + json = {}; + } + if (json is Map) { + List subscriptions; + if (json.containsKey("subscriptions")) { + subscriptions = jsonDecoder._decodeList(jsonPath + ".subscriptions", json["subscriptions"], (String jsonPath, Object json) => new GeneralAnalysisService.fromJson(jsonDecoder, jsonPath, json)); + } else { + throw jsonDecoder.missingKey(jsonPath, "subscriptions"); + } + return new AnalysisSetGeneralSubscriptionsParams(subscriptions); + } else { + throw jsonDecoder.mismatch(jsonPath, "analysis.setGeneralSubscriptions params"); + } + } + + factory AnalysisSetGeneralSubscriptionsParams.fromRequest(Request request) { + return new AnalysisSetGeneralSubscriptionsParams.fromJson( + new RequestDecoder(request), "params", request._params); + } + + Map toJson() { + Map result = {}; + result["subscriptions"] = subscriptions.map((GeneralAnalysisService value) => value.toJson()).toList(); + return result; + } + + Request toRequest(String id) { + return new Request(id, "analysis.setGeneralSubscriptions", toJson()); + } + + @override + String toString() => JSON.encode(toJson()); + + @override + bool operator==(other) { + if (other is AnalysisSetGeneralSubscriptionsParams) { + return _listEqual(subscriptions, other.subscriptions, (GeneralAnalysisService a, GeneralAnalysisService b) => a == b); + } + return false; + } + + @override + int get hashCode { + int hash = 0; + hash = _JenkinsSmiHash.combine(hash, subscriptions.hashCode); + return _JenkinsSmiHash.finish(hash); + } +} +/** + * analysis.setGeneralSubscriptions result + */ +class AnalysisSetGeneralSubscriptionsResult { + Response toResponse(String id) { + return new Response(id, result: null); + } + + @override + bool operator==(other) { + if (other is AnalysisSetGeneralSubscriptionsResult) { + return true; + } + return false; + } + + @override + int get hashCode { + return 386759562; + } +} + /** * analysis.setPriorityFiles params * @@ -2012,6 +2111,84 @@ class AnalysisUpdateOptionsResult { } } +/** + * analysis.analyzedFiles params + * + * { + * "directories": List + * } + */ +class AnalysisAnalyzedFilesParams implements HasToJson { + List _directories; + + /** + * A list of the paths of the files that are being analyzed. + */ + List get directories => _directories; + + /** + * A list of the paths of the files that are being analyzed. + */ + void set directories(List value) { + assert(value != null); + this._directories = value; + } + + AnalysisAnalyzedFilesParams(List directories) { + this.directories = directories; + } + + factory AnalysisAnalyzedFilesParams.fromJson(JsonDecoder jsonDecoder, String jsonPath, Object json) { + if (json == null) { + json = {}; + } + if (json is Map) { + List directories; + if (json.containsKey("directories")) { + directories = jsonDecoder._decodeList(jsonPath + ".directories", json["directories"], jsonDecoder._decodeString); + } else { + throw jsonDecoder.missingKey(jsonPath, "directories"); + } + return new AnalysisAnalyzedFilesParams(directories); + } else { + throw jsonDecoder.mismatch(jsonPath, "analysis.analyzedFiles params"); + } + } + + factory AnalysisAnalyzedFilesParams.fromNotification(Notification notification) { + return new AnalysisAnalyzedFilesParams.fromJson( + new ResponseDecoder(null), "params", notification._params); + } + + Map toJson() { + Map result = {}; + result["directories"] = directories; + return result; + } + + Notification toNotification() { + return new Notification("analysis.analyzedFiles", toJson()); + } + + @override + String toString() => JSON.encode(toJson()); + + @override + bool operator==(other) { + if (other is AnalysisAnalyzedFilesParams) { + return _listEqual(directories, other.directories, (String a, String b) => a == b); + } + return false; + } + + @override + int get hashCode { + int hash = 0; + hash = _JenkinsSmiHash.combine(hash, directories.hashCode); + return _JenkinsSmiHash.finish(hash); + } +} + /** * analysis.errors params * @@ -7455,6 +7632,10 @@ class AnalysisService implements Enum { static const HIGHLIGHTS = const AnalysisService._("HIGHLIGHTS"); + /** + * This service is not currently implemented and will become a + * GeneralAnalysisService in a future release. + */ static const INVALIDATE = const AnalysisService._("INVALIDATE"); static const NAVIGATION = const AnalysisService._("NAVIGATION"); @@ -9163,6 +9344,50 @@ class FoldingRegion implements HasToJson { } } +/** + * GeneralAnalysisService + * + * enum { + * ANALYZED_FILES + * } + */ +class GeneralAnalysisService implements Enum { + static const ANALYZED_FILES = const GeneralAnalysisService._("ANALYZED_FILES"); + + /** + * A list containing all of the enum values that are defined. + */ + static const List VALUES = const [ANALYZED_FILES]; + + final String name; + + const GeneralAnalysisService._(this.name); + + factory GeneralAnalysisService(String name) { + switch (name) { + case "ANALYZED_FILES": + return ANALYZED_FILES; + } + throw new Exception('Illegal enum value: $name'); + } + + factory GeneralAnalysisService.fromJson(JsonDecoder jsonDecoder, String jsonPath, Object json) { + if (json is String) { + try { + return new GeneralAnalysisService(json); + } catch(_) { + // Fall through + } + } + throw jsonDecoder.mismatch(jsonPath, "GeneralAnalysisService"); + } + + @override + String toString() => "GeneralAnalysisService.$name"; + + String toJson() => name; +} + /** * HighlightRegion * diff --git a/pkg/analysis_server/lib/src/operation/operation_analysis.dart b/pkg/analysis_server/lib/src/operation/operation_analysis.dart index ebe71e73998..228e0ae5c38 100644 --- a/pkg/analysis_server/lib/src/operation/operation_analysis.dart +++ b/pkg/analysis_server/lib/src/operation/operation_analysis.dart @@ -12,6 +12,7 @@ import 'package:analysis_server/src/computer/computer_outline.dart'; import 'package:analysis_server/src/computer/computer_overrides.dart'; import 'package:analysis_server/src/operation/operation.dart'; import 'package:analysis_server/src/protocol_server.dart' as protocol; +import 'package:analysis_server/src/services/dependencies/library_dependencies.dart'; import 'package:analysis_server/src/services/index/index.dart'; import 'package:analyzer/src/generated/ast.dart'; import 'package:analyzer/src/generated/engine.dart'; @@ -98,6 +99,17 @@ void scheduleNotificationOperations(AnalysisServer server, String file, } } +void sendAnalysisNotificationAnalyzedFiles(AnalysisServer server) { + _sendNotification(server, () { + LibraryDependencyCollector collector = + new LibraryDependencyCollector(server.getAnalysisContexts().toList()); + Set directories = collector.collectLibraryDependencies(); + protocol.AnalysisAnalyzedFilesParams params = + new protocol.AnalysisAnalyzedFilesParams(directories.toList()); + server.sendNotification(params.toNotification()); + }); +} + void sendAnalysisNotificationErrors(AnalysisServer server, String file, LineInfo lineInfo, List errors) { _sendNotification(server, () { diff --git a/pkg/analysis_server/test/analysis/notification_analyzedFiles_test.dart b/pkg/analysis_server/test/analysis/notification_analyzedFiles_test.dart new file mode 100644 index 00000000000..2cf16065912 --- /dev/null +++ b/pkg/analysis_server/test/analysis/notification_analyzedFiles_test.dart @@ -0,0 +1,66 @@ +// 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. + +library test.analysis.notification.analyzedDirectories; + +import 'dart:async'; + +import 'package:analysis_server/src/constants.dart'; +import 'package:analysis_server/src/protocol.dart'; +import 'package:test_reflective_loader/test_reflective_loader.dart'; +import 'package:unittest/unittest.dart'; + +import '../analysis_abstract.dart'; + +main() { + groupSep = ' | '; + defineReflectiveTests(AnalysisNotificationAnalyzedFilesTest); +} + +@reflectiveTest +class AnalysisNotificationAnalyzedFilesTest extends AbstractAnalysisTest { + List analyzedFiles; + + void assertHasFile(String filePath) { + expect(analyzedFiles, contains(filePath)); + } + + Future prepareAnalyzedFiles() { + addGeneralAnalysisSubscription(GeneralAnalysisService.ANALYZED_FILES); + return waitForTasksFinished(); + } + + void processNotification(Notification notification) { + if (notification.event == ANALYSIS_ANALYZED_FILES) { + AnalysisAnalyzedFilesParams params = + new AnalysisAnalyzedFilesParams.fromNotification(notification); + analyzedFiles = params.directories; + } + } + + void setUp() { + super.setUp(); + createProject(); + } + + test_afterAnalysis() { + addTestFile(''' +class A {} +'''); + return waitForTasksFinished().then((_) { + return prepareAnalyzedFiles().then((_) { + assertHasFile(testFile); + }); + }); + } + + test_definedInInterface_ofInterface() { + addTestFile(''' +class A {} +'''); + return prepareAnalyzedFiles().then((_) { + assertHasFile(testFile); + }); + } +} diff --git a/pkg/analysis_server/test/analysis/test_all.dart b/pkg/analysis_server/test/analysis/test_all.dart index b28a687eb62..d6ce22ea91f 100644 --- a/pkg/analysis_server/test/analysis/test_all.dart +++ b/pkg/analysis_server/test/analysis/test_all.dart @@ -8,6 +8,8 @@ import 'package:unittest/unittest.dart'; import 'get_errors_test.dart' as get_errors_test; import 'get_hover_test.dart' as get_hover_test; import 'get_navigation_test.dart' as get_navigation_test; +import 'notification_analyzedFiles_test.dart' + as notification_analyzedFiles_test; import 'notification_errors_test.dart' as notification_errors_test; import 'notification_highlights_test.dart' as notification_highlights_test; import 'notification_navigation_test.dart' as notification_navigation_test; @@ -25,6 +27,7 @@ main() { get_errors_test.main(); get_hover_test.main(); get_navigation_test.main(); + notification_analyzedFiles_test.main(); notification_errors_test.main(); notification_highlights_test.main(); notification_navigation_test.main(); diff --git a/pkg/analysis_server/test/analysis_abstract.dart b/pkg/analysis_server/test/analysis_abstract.dart index 2efad959487..753a2f5fe33 100644 --- a/pkg/analysis_server/test/analysis_abstract.dart +++ b/pkg/analysis_server/test/analysis_abstract.dart @@ -46,6 +46,8 @@ class AbstractAnalysisTest { RequestHandler handler; final List serverErrors = []; + final List generalServices = + []; final Map> analysisSubscriptions = {}; String projectPath = '/project'; @@ -74,6 +76,13 @@ class AbstractAnalysisTest { return path; } + void addGeneralAnalysisSubscription(GeneralAnalysisService service) { + generalServices.add(service); + Request request = new AnalysisSetGeneralSubscriptionsParams(generalServices) + .toRequest('0'); + handleSuccessfulRequest(request); + } + String addTestFile(String content) { addFile(testFile, content); this.testCode = content; diff --git a/pkg/analysis_server/test/integration/integration_test_methods.dart b/pkg/analysis_server/test/integration/integration_test_methods.dart index 5794acb52c9..4da1b0c6807 100644 --- a/pkg/analysis_server/test/integration/integration_test_methods.dart +++ b/pkg/analysis_server/test/integration/integration_test_methods.dart @@ -240,6 +240,9 @@ abstract class IntegrationTestMixin { * Return library dependency information for use in client-side indexing and * package URI resolution. * + * Clients that are only using the libraries field should consider using the + * analyzedFiles notification instead. + * * Returns * * libraries ( List ) @@ -412,6 +415,30 @@ abstract class IntegrationTestMixin { }); } + /** + * Subscribe for general services (that is, services that are not specific to + * individual files). All previous subscriptions are replaced by the given + * set of services. + * + * It is an error if any of the elements in the list are not valid services. + * If there is an error, then the current subscriptions will remain + * unchanged. + * + * Parameters + * + * subscriptions ( List ) + * + * A list of the services being subscribed to. + */ + Future sendAnalysisSetGeneralSubscriptions(List subscriptions) { + var params = new AnalysisSetGeneralSubscriptionsParams(subscriptions).toJson(); + return server.send("analysis.setGeneralSubscriptions", params) + .then((result) { + expect(result, isNull); + return null; + }); + } + /** * Set the priority files to the files in the given list. A priority file is * a file that is given priority when scheduling which analysis work to do @@ -447,11 +474,11 @@ abstract class IntegrationTestMixin { } /** - * Subscribe for services. All previous subscriptions are replaced by the - * current set of subscriptions. If a given service is not included as a key - * in the map then no files will be subscribed to the service, exactly as if - * the service had been included in the map with an explicit empty list of - * files. + * Subscribe for services that are specific to individual files. All previous + * subscriptions are replaced by the current set of subscriptions. If a given + * service is not included as a key in the map then no files will be + * subscribed to the service, exactly as if the service had been included in + * the map with an explicit empty list of files. * * Note that this request determines the set of requested subscriptions. The * actual set of subscriptions at any given time is the intersection of this @@ -535,6 +562,26 @@ abstract class IntegrationTestMixin { }); } + /** + * Reports the paths of the files that are being analyzed. + * + * This notification is not subscribed to by default. Clients can subscribe + * by including the value "ANALYZED_FILES" in the list of services passed in + * an analysis.setGeneralSubscriptions request. + * + * Parameters + * + * directories ( List ) + * + * A list of the paths of the files that are being analyzed. + */ + Stream onAnalysisAnalyzedFiles; + + /** + * Stream controller for [onAnalysisAnalyzedFiles]. + */ + StreamController _onAnalysisAnalyzedFiles; + /** * Reports the errors associated with a given file. The set of errors * included in the notification is always a complete list that supersedes any @@ -1512,6 +1559,8 @@ abstract class IntegrationTestMixin { onServerError = _onServerError.stream.asBroadcastStream(); _onServerStatus = new StreamController(sync: true); onServerStatus = _onServerStatus.stream.asBroadcastStream(); + _onAnalysisAnalyzedFiles = new StreamController(sync: true); + onAnalysisAnalyzedFiles = _onAnalysisAnalyzedFiles.stream.asBroadcastStream(); _onAnalysisErrors = new StreamController(sync: true); onAnalysisErrors = _onAnalysisErrors.stream.asBroadcastStream(); _onAnalysisFlushResults = new StreamController(sync: true); @@ -1557,6 +1606,10 @@ abstract class IntegrationTestMixin { expect(params, isServerStatusParams); _onServerStatus.add(new ServerStatusParams.fromJson(decoder, 'params', params)); break; + case "analysis.analyzedFiles": + expect(params, isAnalysisAnalyzedFilesParams); + _onAnalysisAnalyzedFiles.add(new AnalysisAnalyzedFilesParams.fromJson(decoder, 'params', params)); + break; case "analysis.errors": expect(params, isAnalysisErrorsParams); _onAnalysisErrors.add(new AnalysisErrorsParams.fromJson(decoder, 'params', params)); diff --git a/pkg/analysis_server/test/integration/protocol_matchers.dart b/pkg/analysis_server/test/integration/protocol_matchers.dart index fbb40a8f7b9..944edb6364c 100644 --- a/pkg/analysis_server/test/integration/protocol_matchers.dart +++ b/pkg/analysis_server/test/integration/protocol_matchers.dart @@ -242,6 +242,23 @@ final Matcher isAnalysisSetAnalysisRootsParams = new LazyMatcher(() => new Match */ final Matcher isAnalysisSetAnalysisRootsResult = isNull; +/** + * analysis.setGeneralSubscriptions params + * + * { + * "subscriptions": List + * } + */ +final Matcher isAnalysisSetGeneralSubscriptionsParams = new LazyMatcher(() => new MatchesJsonObject( + "analysis.setGeneralSubscriptions params", { + "subscriptions": isListOf(isGeneralAnalysisService) + })); + +/** + * analysis.setGeneralSubscriptions result + */ +final Matcher isAnalysisSetGeneralSubscriptionsResult = isNull; + /** * analysis.setPriorityFiles params * @@ -314,6 +331,18 @@ final Matcher isAnalysisUpdateOptionsParams = new LazyMatcher(() => new MatchesJ */ final Matcher isAnalysisUpdateOptionsResult = isNull; +/** + * analysis.analyzedFiles params + * + * { + * "directories": List + * } + */ +final Matcher isAnalysisAnalyzedFilesParams = new LazyMatcher(() => new MatchesJsonObject( + "analysis.analyzedFiles params", { + "directories": isListOf(isFilePath) + })); + /** * analysis.errors params * @@ -1344,6 +1373,17 @@ final Matcher isFoldingRegion = new LazyMatcher(() => new MatchesJsonObject( "length": isInt })); +/** + * GeneralAnalysisService + * + * enum { + * ANALYZED_FILES + * } + */ +final Matcher isGeneralAnalysisService = new MatchesEnum("GeneralAnalysisService", [ + "ANALYZED_FILES" +]); + /** * HighlightRegion * diff --git a/pkg/analysis_server/tool/spec/generated/java/AnalysisServer.java b/pkg/analysis_server/tool/spec/generated/java/AnalysisServer.java index c6debb704c7..c398e4df2b0 100644 --- a/pkg/analysis_server/tool/spec/generated/java/AnalysisServer.java +++ b/pkg/analysis_server/tool/spec/generated/java/AnalysisServer.java @@ -86,6 +86,9 @@ public interface AnalysisServer { * * Return library dependency information for use in client-side indexing and package URI * resolution. + * + * Clients that are only using the libraries field should consider using the analyzedFiles + * notification instead. */ public void analysis_getLibraryDependencies(GetLibraryDependenciesConsumer consumer); @@ -169,6 +172,19 @@ public interface AnalysisServer { */ public void analysis_setAnalysisRoots(List included, List excluded, Map packageRoots); + /** + * {@code analysis.setGeneralSubscriptions} + * + * Subscribe for general services (that is, services that are not specific to individual files). + * All previous subscriptions are replaced by the given set of services. + * + * It is an error if any of the elements in the list are not valid services. If there is an error, + * then the current subscriptions will remain unchanged. + * + * @param subscriptions A list of the services being subscribed to. + */ + public void analysis_setGeneralSubscriptions(List subscriptions); + /** * {@code analysis.setPriorityFiles} * @@ -195,10 +211,10 @@ public interface AnalysisServer { /** * {@code analysis.setSubscriptions} * - * Subscribe for services. All previous subscriptions are replaced by the current set of - * subscriptions. If a given service is not included as a key in the map then no files will be - * subscribed to the service, exactly as if the service had been included in the map with an - * explicit empty list of files. + * Subscribe for services that are specific to individual files. All previous subscriptions are + * replaced by the current set of subscriptions. If a given service is not included as a key in the + * map then no files will be subscribed to the service, exactly as if the service had been included + * in the map with an explicit empty list of files. * * Note that this request determines the set of requested subscriptions. The actual set of * subscriptions at any given time is the intersection of this set with the set of files currently diff --git a/pkg/analysis_server/tool/spec/generated/java/types/AnalysisService.java b/pkg/analysis_server/tool/spec/generated/java/types/AnalysisService.java index 94c5418b46b..ca3b8e92d59 100644 --- a/pkg/analysis_server/tool/spec/generated/java/types/AnalysisService.java +++ b/pkg/analysis_server/tool/spec/generated/java/types/AnalysisService.java @@ -17,7 +17,8 @@ package org.dartlang.analysis.server.protocol; /** - * An enumeration of the services provided by the analysis domain. + * An enumeration of the services provided by the analysis domain that are related to a specific + * list of files. * * @coverage dart.server.generated.types */ @@ -27,6 +28,10 @@ public class AnalysisService { public static final String HIGHLIGHTS = "HIGHLIGHTS"; + /** + * This service is not currently implemented and will become a GeneralAnalysisService in a future + * release. + */ public static final String INVALIDATE = "INVALIDATE"; public static final String NAVIGATION = "NAVIGATION"; diff --git a/pkg/analysis_server/tool/spec/generated/java/types/GeneralAnalysisService.java b/pkg/analysis_server/tool/spec/generated/java/types/GeneralAnalysisService.java new file mode 100644 index 00000000000..a1f0071385c --- /dev/null +++ b/pkg/analysis_server/tool/spec/generated/java/types/GeneralAnalysisService.java @@ -0,0 +1,29 @@ +/* + * Copyright (c) 2014, the Dart project authors. + * + * Licensed under the Eclipse Public License v1.0 (the "License"); you may not use this file except + * in compliance with the License. You may obtain a copy of the License at + * + * http://www.eclipse.org/legal/epl-v10.html + * + * Unless required by applicable law or agreed to in writing, software distributed under the License + * is distributed on an "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express + * or implied. See the License for the specific language governing permissions and limitations under + * the License. + * + * This file has been automatically generated. Please do not edit it manually. + * To regenerate the file, use the script "pkg/analysis_server/tool/spec/generate_files". + */ +package org.dartlang.analysis.server.protocol; + +/** + * An enumeration of the services provided by the analysis domain that are general in nature (that + * is, are not specific to some list of files). + * + * @coverage dart.server.generated.types + */ +public class GeneralAnalysisService { + + public static final String ANALYZED_FILES = "ANALYZED_FILES"; + +} diff --git a/pkg/analysis_server/tool/spec/spec_input.html b/pkg/analysis_server/tool/spec/spec_input.html index b88c8ac7ae8..3db0e472d36 100644 --- a/pkg/analysis_server/tool/spec/spec_input.html +++ b/pkg/analysis_server/tool/spec/spec_input.html @@ -5,7 +5,7 @@

Analysis Server API Specification

-

Version 1.7.0

+

Version 1.8.0

This document contains a specification of the API provided by the analysis server. The API in this document is currently under @@ -396,6 +396,10 @@ Return library dependency information for use in client-side indexing and package URI resolution.

+

+ Clients that are only using the libraries field should consider using the + analyzedFiles notification instead. +

FilePath @@ -591,6 +595,24 @@ + +

+ Subscribe for general services (that is, services that are not + specific to individual files). All previous subscriptions are replaced + by the given set of services. +

+

+ It is an error if any of the elements in the list are not valid + services. If there is an error, then the current subscriptions will + remain unchanged. +

+ + + GeneralAnalysisService +

A list of the services being subscribed to.

+
+
+

Set the priority files to the files in the given list. A @@ -628,11 +650,11 @@

- Subscribe for services. All previous subscriptions are - replaced by the current set of subscriptions. If a given - service is not included as a key in the map then no files - will be subscribed to the service, exactly as if the service - had been included in the map with an explicit empty list of + Subscribe for services that are specific to individual files. + All previous subscriptions are replaced by the current set of + subscriptions. If a given service is not included as a key in the map + then no files will be subscribed to the service, exactly as if the + service had been included in the map with an explicit empty list of files.

@@ -724,6 +746,24 @@ + +

+ Reports the paths of the files that are being analyzed. +

+

+ This notification is not subscribed to by default. Clients can + subscribe by including the value "ANALYZED_FILES" in the list + of services passed in an analysis.setGeneralSubscriptions request. +

+ + + FilePath +

+ A list of the paths of the files that are being analyzed. +

+
+
+

Reports the errors associated with a given file. The set of @@ -2002,13 +2042,19 @@

- An enumeration of the services provided by the analysis - domain. + An enumeration of the services provided by the analysis domain that + are related to a specific list of files.

FOLDING HIGHLIGHTS - INVALIDATE + + INVALIDATE +

+ This service is not currently implemented and will become a + GeneralAnalysisService in a future release. +

+
NAVIGATION OCCURRENCES OUTLINE @@ -2461,6 +2507,15 @@ + +

+ An enumeration of the services provided by the analysis domain that are + general in nature (that is, are not specific to some list of files). +

+ + ANALYZED_FILES + +

A description of a region that could have special highlighting