Add OCCURRENCES_CONTRIBUTOR_EXTENSION_POINT_ID.
R=brianwilkerson@google.com BUG= Review URL: https://codereview.chromium.org//1337143002 .
This commit is contained in:
+1
-1
@@ -2,7 +2,7 @@
|
||||
// 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 analysis_server.analysis.navigation.navigation_core;
|
||||
library analysis_server.analysis.navigation_core;
|
||||
|
||||
import 'package:analysis_server/src/protocol.dart'
|
||||
show ElementKind, Location, NavigationRegion, NavigationTarget;
|
||||
@@ -0,0 +1,35 @@
|
||||
// Copyright (c) 2015, 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 analysis_server.analysis.occurrences_core;
|
||||
|
||||
import 'package:analysis_server/src/protocol.dart' show Element, Occurrences;
|
||||
import 'package:analyzer/src/generated/engine.dart' show AnalysisContext;
|
||||
import 'package:analyzer/src/generated/source.dart' show Source;
|
||||
|
||||
/**
|
||||
* An object used to produce occurrences.
|
||||
*
|
||||
* Clients are expected to subtype this class when implementing plugins.
|
||||
*/
|
||||
abstract class OccurrencesContributor {
|
||||
/**
|
||||
* Contribute occurrences into the given [collector].
|
||||
* The [context] can be used to get analysis results.
|
||||
*/
|
||||
void computeOccurrences(
|
||||
OccurrencesCollector collector, AnalysisContext context, Source source);
|
||||
}
|
||||
|
||||
/**
|
||||
* An object that [OccurrencesContributor]s use to record occurrences into.
|
||||
*
|
||||
* Clients are not expected to subtype this class.
|
||||
*/
|
||||
abstract class OccurrencesCollector {
|
||||
/**
|
||||
* Record a new element occurrences.
|
||||
*/
|
||||
void addOccurrences(Occurrences occurrences);
|
||||
}
|
||||
@@ -8,7 +8,7 @@
|
||||
*/
|
||||
library analysis_server.plugin.navigation;
|
||||
|
||||
import 'package:analysis_server/analysis/navigation/navigation_core.dart';
|
||||
import 'package:analysis_server/analysis/navigation_core.dart';
|
||||
import 'package:analysis_server/src/plugin/server_plugin.dart';
|
||||
import 'package:plugin/plugin.dart';
|
||||
|
||||
|
||||
@@ -0,0 +1,22 @@
|
||||
// Copyright (c) 2015, 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.
|
||||
|
||||
/**
|
||||
* Support for client code that extends the analysis server by adding new
|
||||
* occurrences contributors.
|
||||
*/
|
||||
library analysis_server.plugin.occurrences;
|
||||
|
||||
import 'package:analysis_server/analysis/occurrences_core.dart';
|
||||
import 'package:analysis_server/src/plugin/server_plugin.dart';
|
||||
import 'package:plugin/plugin.dart';
|
||||
|
||||
/**
|
||||
* The identifier of the extension point that allows plugins to register
|
||||
* element occurrences. The object used as an extension must be
|
||||
* a [OccurrencesContributor].
|
||||
*/
|
||||
final String OCCURRENCES_CONTRIBUTOR_EXTENSION_POINT_ID = Plugin.join(
|
||||
ServerPlugin.UNIQUE_IDENTIFIER,
|
||||
ServerPlugin.OCCURRENCES_CONTRIBUTOR_EXTENSION_POINT);
|
||||
@@ -975,7 +975,7 @@ class AnalysisServer {
|
||||
sendAnalysisNotificationNavigation(this, context, source);
|
||||
break;
|
||||
case AnalysisService.OCCURRENCES:
|
||||
sendAnalysisNotificationOccurrences(this, file, dartUnit);
|
||||
sendAnalysisNotificationOccurrences(this, context, source);
|
||||
break;
|
||||
case AnalysisService.OUTLINE:
|
||||
AnalysisContext context = dartUnit.element.context;
|
||||
|
||||
@@ -1,78 +0,0 @@
|
||||
// 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 computer.occurrences;
|
||||
|
||||
import 'dart:collection';
|
||||
|
||||
import 'package:analysis_server/src/protocol_server.dart' as protocol;
|
||||
import 'package:analyzer/src/generated/ast.dart';
|
||||
import 'package:analyzer/src/generated/element.dart';
|
||||
|
||||
/**
|
||||
* A computer for elements occurrences in a Dart [CompilationUnit].
|
||||
*/
|
||||
class DartUnitOccurrencesComputer {
|
||||
final CompilationUnit _unit;
|
||||
|
||||
final Map<Element, List<int>> _elementsOffsets =
|
||||
new HashMap<Element, List<int>>();
|
||||
|
||||
DartUnitOccurrencesComputer(this._unit);
|
||||
|
||||
/**
|
||||
* Returns the computed occurrences, not `null`.
|
||||
*/
|
||||
List<protocol.Occurrences> compute() {
|
||||
_unit.accept(new _DartUnitOccurrencesComputerVisitor(this));
|
||||
List<protocol.Occurrences> occurrences = <protocol.Occurrences>[];
|
||||
_elementsOffsets.forEach((engineElement, offsets) {
|
||||
var serverElement = protocol.newElement_fromEngine(engineElement);
|
||||
var length = engineElement.displayName.length;
|
||||
occurrences.add(new protocol.Occurrences(serverElement, offsets, length));
|
||||
});
|
||||
return occurrences;
|
||||
}
|
||||
|
||||
void _addOccurrence(Element element, int offset) {
|
||||
element = _canonicalizeElement(element);
|
||||
if (element == null || element == DynamicElementImpl.instance) {
|
||||
return;
|
||||
}
|
||||
List<int> offsets = _elementsOffsets[element];
|
||||
if (offsets == null) {
|
||||
offsets = <int>[];
|
||||
_elementsOffsets[element] = offsets;
|
||||
}
|
||||
offsets.add(offset);
|
||||
}
|
||||
|
||||
Element _canonicalizeElement(Element element) {
|
||||
if (element is FieldFormalParameterElement) {
|
||||
element = (element as FieldFormalParameterElement).field;
|
||||
}
|
||||
if (element is PropertyAccessorElement) {
|
||||
element = (element as PropertyAccessorElement).variable;
|
||||
}
|
||||
if (element is Member) {
|
||||
element = (element as Member).baseElement;
|
||||
}
|
||||
return element;
|
||||
}
|
||||
}
|
||||
|
||||
class _DartUnitOccurrencesComputerVisitor extends RecursiveAstVisitor {
|
||||
final DartUnitOccurrencesComputer computer;
|
||||
|
||||
_DartUnitOccurrencesComputerVisitor(this.computer);
|
||||
|
||||
@override
|
||||
visitSimpleIdentifier(SimpleIdentifier node) {
|
||||
Element element = node.bestElement;
|
||||
if (element != null) {
|
||||
computer._addOccurrence(element, node.offset);
|
||||
}
|
||||
return super.visitSimpleIdentifier(node);
|
||||
}
|
||||
}
|
||||
@@ -14,7 +14,10 @@ import 'package:analysis_server/src/constants.dart';
|
||||
import 'package:analysis_server/src/context_manager.dart';
|
||||
import 'package:analysis_server/src/domains/analysis/navigation.dart';
|
||||
import 'package:analysis_server/src/operation/operation_analysis.dart'
|
||||
show NavigationOperation, sendAnalysisNotificationNavigation;
|
||||
show
|
||||
NavigationOperation,
|
||||
OccurrencesOperation,
|
||||
sendAnalysisNotificationNavigation;
|
||||
import 'package:analysis_server/src/protocol_server.dart';
|
||||
import 'package:analysis_server/src/services/dependencies/library_dependencies.dart';
|
||||
import 'package:analyzer/file_system/file_system.dart';
|
||||
@@ -352,6 +355,9 @@ class AnalysisDomainImpl implements AnalysisDomain {
|
||||
if (service == AnalysisService.NAVIGATION) {
|
||||
server.scheduleOperation(new NavigationOperation(context, source));
|
||||
}
|
||||
if (service == AnalysisService.OCCURRENCES) {
|
||||
server.scheduleOperation(new OccurrencesOperation(context, source));
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
@@ -1,4 +1,4 @@
|
||||
// Copyright (c) 2014, the Dart project authors. Please see the AUTHORS file
|
||||
// Copyright (c) 2015, 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.
|
||||
|
||||
@@ -6,7 +6,7 @@ library domains.analysis.navigation;
|
||||
|
||||
import 'dart:collection';
|
||||
|
||||
import 'package:analysis_server/analysis/navigation/navigation_core.dart';
|
||||
import 'package:analysis_server/analysis/navigation_core.dart';
|
||||
import 'package:analysis_server/src/analysis_server.dart';
|
||||
import 'package:analysis_server/src/collections.dart';
|
||||
import 'package:analysis_server/src/protocol_server.dart' as protocol;
|
||||
|
||||
@@ -1,10 +1,10 @@
|
||||
// Copyright (c) 2014, the Dart project authors. Please see the AUTHORS file
|
||||
// Copyright (c) 2015, 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 domains.analysis.navigation_dart;
|
||||
|
||||
import 'package:analysis_server/analysis/navigation/navigation_core.dart';
|
||||
import 'package:analysis_server/analysis/navigation_core.dart';
|
||||
import 'package:analysis_server/src/protocol_server.dart' as protocol;
|
||||
import 'package:analyzer/src/generated/ast.dart';
|
||||
import 'package:analyzer/src/generated/element.dart';
|
||||
|
||||
@@ -0,0 +1,45 @@
|
||||
// Copyright (c) 2015, 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 domains.analysis.occurrences;
|
||||
|
||||
import 'package:analysis_server/analysis/occurrences_core.dart';
|
||||
import 'package:analysis_server/src/analysis_server.dart';
|
||||
import 'package:analysis_server/src/protocol_server.dart' as protocol;
|
||||
import 'package:analyzer/src/generated/engine.dart'
|
||||
show AnalysisContext, AnalysisEngine;
|
||||
import 'package:analyzer/src/generated/java_engine.dart' show CaughtException;
|
||||
import 'package:analyzer/src/generated/source.dart' show Source;
|
||||
|
||||
/**
|
||||
* Compute all known occurrences for the given [source].
|
||||
*/
|
||||
OccurrencesCollectorImpl computeOccurrences(
|
||||
AnalysisServer server, AnalysisContext context, Source source) {
|
||||
OccurrencesCollectorImpl collector = new OccurrencesCollectorImpl();
|
||||
List<OccurrencesContributor> contributors =
|
||||
server.serverPlugin.occurrencesContributors;
|
||||
for (OccurrencesContributor contributor in contributors) {
|
||||
try {
|
||||
contributor.computeOccurrences(collector, context, source);
|
||||
} catch (exception, stackTrace) {
|
||||
AnalysisEngine.instance.logger.logError(
|
||||
'Exception from occurrences contributor: ${contributor.runtimeType}',
|
||||
new CaughtException(exception, stackTrace));
|
||||
}
|
||||
}
|
||||
return collector;
|
||||
}
|
||||
|
||||
/**
|
||||
* A concrete implementation of [OccurrencesCollector].
|
||||
*/
|
||||
class OccurrencesCollectorImpl implements OccurrencesCollector {
|
||||
final List<protocol.Occurrences> allOccurrences = <protocol.Occurrences>[];
|
||||
|
||||
@override
|
||||
void addOccurrences(protocol.Occurrences occurrences) {
|
||||
allOccurrences.add(occurrences);
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,79 @@
|
||||
// Copyright (c) 2015, 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 domains.analysis.occurrences_dart;
|
||||
|
||||
import 'package:analysis_server/analysis/occurrences_core.dart';
|
||||
import 'package:analysis_server/src/protocol_server.dart' as protocol;
|
||||
import 'package:analyzer/src/generated/ast.dart';
|
||||
import 'package:analyzer/src/generated/element.dart';
|
||||
import 'package:analyzer/src/generated/engine.dart';
|
||||
import 'package:analyzer/src/generated/source.dart';
|
||||
|
||||
/**
|
||||
* A computer for occurrences in a Dart [CompilationUnit].
|
||||
*/
|
||||
class DartOccurrencesComputer implements OccurrencesContributor {
|
||||
@override
|
||||
void computeOccurrences(
|
||||
OccurrencesCollector collector, AnalysisContext context, Source source) {
|
||||
List<Source> libraries = context.getLibrariesContaining(source);
|
||||
if (libraries.isNotEmpty) {
|
||||
CompilationUnit unit =
|
||||
context.getResolvedCompilationUnit2(source, libraries.first);
|
||||
if (unit != null) {
|
||||
_DartUnitOccurrencesComputerVisitor visitor =
|
||||
new _DartUnitOccurrencesComputerVisitor();
|
||||
unit.accept(visitor);
|
||||
visitor.elementsOffsets.forEach((engineElement, offsets) {
|
||||
int length = engineElement.displayName.length;
|
||||
protocol.Element serverElement =
|
||||
protocol.newElement_fromEngine(engineElement);
|
||||
protocol.Occurrences occurrences =
|
||||
new protocol.Occurrences(serverElement, offsets, length);
|
||||
collector.addOccurrences(occurrences);
|
||||
});
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
class _DartUnitOccurrencesComputerVisitor extends RecursiveAstVisitor {
|
||||
final Map<Element, List<int>> elementsOffsets = <Element, List<int>>{};
|
||||
|
||||
@override
|
||||
visitSimpleIdentifier(SimpleIdentifier node) {
|
||||
Element element = node.bestElement;
|
||||
if (element != null) {
|
||||
_addOccurrence(element, node.offset);
|
||||
}
|
||||
return super.visitSimpleIdentifier(node);
|
||||
}
|
||||
|
||||
void _addOccurrence(Element element, int offset) {
|
||||
element = _canonicalizeElement(element);
|
||||
if (element == null || element == DynamicElementImpl.instance) {
|
||||
return;
|
||||
}
|
||||
List<int> offsets = elementsOffsets[element];
|
||||
if (offsets == null) {
|
||||
offsets = <int>[];
|
||||
elementsOffsets[element] = offsets;
|
||||
}
|
||||
offsets.add(offset);
|
||||
}
|
||||
|
||||
Element _canonicalizeElement(Element element) {
|
||||
if (element is FieldFormalParameterElement) {
|
||||
element = (element as FieldFormalParameterElement).field;
|
||||
}
|
||||
if (element is PropertyAccessorElement) {
|
||||
element = (element as PropertyAccessorElement).variable;
|
||||
}
|
||||
if (element is Member) {
|
||||
element = (element as Member).baseElement;
|
||||
}
|
||||
return element;
|
||||
}
|
||||
}
|
||||
@@ -7,10 +7,10 @@ library operation.analysis;
|
||||
import 'package:analysis_server/src/analysis_server.dart';
|
||||
import 'package:analysis_server/src/computer/computer_highlights.dart';
|
||||
import 'package:analysis_server/src/computer/computer_highlights2.dart';
|
||||
import 'package:analysis_server/src/computer/computer_occurrences.dart';
|
||||
import 'package:analysis_server/src/computer/computer_outline.dart';
|
||||
import 'package:analysis_server/src/computer/computer_overrides.dart';
|
||||
import 'package:analysis_server/src/domains/analysis/navigation.dart';
|
||||
import 'package:analysis_server/src/domains/analysis/occurrences.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';
|
||||
@@ -82,8 +82,8 @@ void scheduleNotificationOperations(
|
||||
}
|
||||
if (server.hasAnalysisSubscription(
|
||||
protocol.AnalysisService.OCCURRENCES, file)) {
|
||||
server.scheduleOperation(
|
||||
new _DartOccurrencesOperation(context, file, resolvedDartUnit));
|
||||
Source source = resolvedDartUnit.element.source;
|
||||
server.scheduleOperation(new OccurrencesOperation(context, source));
|
||||
}
|
||||
if (server.hasAnalysisSubscription(
|
||||
protocol.AnalysisService.OVERRIDES, file)) {
|
||||
@@ -179,10 +179,13 @@ void sendAnalysisNotificationNavigation(
|
||||
}
|
||||
|
||||
void sendAnalysisNotificationOccurrences(
|
||||
AnalysisServer server, String file, CompilationUnit dartUnit) {
|
||||
AnalysisServer server, AnalysisContext context, Source source) {
|
||||
_sendNotification(server, () {
|
||||
var occurrences = new DartUnitOccurrencesComputer(dartUnit).compute();
|
||||
var params = new protocol.AnalysisOccurrencesParams(file, occurrences);
|
||||
OccurrencesCollectorImpl collector =
|
||||
computeOccurrences(server, context, source);
|
||||
String file = source.fullName;
|
||||
var params =
|
||||
new protocol.AnalysisOccurrencesParams(file, collector.allOccurrences);
|
||||
server.sendNotification(params.toNotification());
|
||||
});
|
||||
}
|
||||
@@ -234,17 +237,35 @@ class NavigationOperation extends _NotificationOperation
|
||||
NavigationOperation(AnalysisContext context, Source source)
|
||||
: super(context, source);
|
||||
|
||||
@override
|
||||
void perform(AnalysisServer server) {
|
||||
sendAnalysisNotificationNavigation(server, context, source);
|
||||
}
|
||||
|
||||
@override
|
||||
bool merge(ServerOperation other) {
|
||||
return other is NavigationOperation &&
|
||||
other.context == context &&
|
||||
other.source == source;
|
||||
}
|
||||
|
||||
@override
|
||||
void perform(AnalysisServer server) {
|
||||
sendAnalysisNotificationNavigation(server, context, source);
|
||||
}
|
||||
}
|
||||
|
||||
class OccurrencesOperation extends _NotificationOperation
|
||||
implements MergeableOperation {
|
||||
OccurrencesOperation(AnalysisContext context, Source source)
|
||||
: super(context, source);
|
||||
|
||||
@override
|
||||
bool merge(ServerOperation other) {
|
||||
return other is OccurrencesOperation &&
|
||||
other.context == context &&
|
||||
other.source == source;
|
||||
}
|
||||
|
||||
@override
|
||||
void perform(AnalysisServer server) {
|
||||
sendAnalysisNotificationOccurrences(server, context, source);
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
@@ -410,17 +431,6 @@ abstract class _DartNotificationOperation extends _SingleFileOperation {
|
||||
}
|
||||
}
|
||||
|
||||
class _DartOccurrencesOperation extends _DartNotificationOperation {
|
||||
_DartOccurrencesOperation(
|
||||
AnalysisContext context, String file, CompilationUnit unit)
|
||||
: super(context, file, unit);
|
||||
|
||||
@override
|
||||
void perform(AnalysisServer server) {
|
||||
sendAnalysisNotificationOccurrences(server, file, unit);
|
||||
}
|
||||
}
|
||||
|
||||
class _DartOutlineOperation extends _DartNotificationOperation {
|
||||
final LineInfo lineInfo;
|
||||
|
||||
|
||||
@@ -6,7 +6,8 @@ library analysis_server.src.plugin.server_plugin;
|
||||
|
||||
import 'package:analysis_server/analysis/analysis_domain.dart';
|
||||
import 'package:analysis_server/analysis/index/index_core.dart';
|
||||
import 'package:analysis_server/analysis/navigation/navigation_core.dart';
|
||||
import 'package:analysis_server/analysis/navigation_core.dart';
|
||||
import 'package:analysis_server/analysis/occurrences_core.dart';
|
||||
import 'package:analysis_server/completion/completion_core.dart';
|
||||
import 'package:analysis_server/edit/assist/assist_core.dart';
|
||||
import 'package:analysis_server/edit/fix/fix_core.dart';
|
||||
@@ -14,12 +15,14 @@ import 'package:analysis_server/plugin/analyzed_files.dart';
|
||||
import 'package:analysis_server/plugin/assist.dart';
|
||||
import 'package:analysis_server/plugin/fix.dart';
|
||||
import 'package:analysis_server/plugin/navigation.dart';
|
||||
import 'package:analysis_server/plugin/occurrences.dart';
|
||||
import 'package:analysis_server/src/analysis_server.dart';
|
||||
import 'package:analysis_server/src/domain_analysis.dart';
|
||||
import 'package:analysis_server/src/domain_completion.dart';
|
||||
import 'package:analysis_server/src/domain_execution.dart';
|
||||
import 'package:analysis_server/src/domain_server.dart';
|
||||
import 'package:analysis_server/src/domains/analysis/navigation_dart.dart';
|
||||
import 'package:analysis_server/src/domains/analysis/occurrences_dart.dart';
|
||||
import 'package:analysis_server/src/edit/edit_domain.dart';
|
||||
import 'package:analysis_server/src/protocol.dart';
|
||||
import 'package:analysis_server/src/search/search_domain.dart';
|
||||
@@ -84,6 +87,13 @@ class ServerPlugin implements Plugin {
|
||||
static const String NAVIGATION_CONTRIBUTOR_EXTENSION_POINT =
|
||||
'navigationContributor';
|
||||
|
||||
/**
|
||||
* The simple identifier of the extension point that allows plugins to
|
||||
* register element occurrences.
|
||||
*/
|
||||
static const String OCCURRENCES_CONTRIBUTOR_EXTENSION_POINT =
|
||||
'occurrencesContributor';
|
||||
|
||||
/**
|
||||
* The simple identifier of the extension point that allows plugins to
|
||||
* register analysis result listeners.
|
||||
@@ -130,10 +140,17 @@ class ServerPlugin implements Plugin {
|
||||
ExtensionPoint indexContributorExtensionPoint;
|
||||
|
||||
/**
|
||||
* The extension point that allows plugins to register navigation contributors.
|
||||
* The extension point that allows plugins to register navigation
|
||||
* contributors.
|
||||
*/
|
||||
ExtensionPoint navigationContributorExtensionPoint;
|
||||
|
||||
/**
|
||||
* The extension point that allows plugins to register occurrences
|
||||
* contributors.
|
||||
*/
|
||||
ExtensionPoint occurrencesContributorExtensionPoint;
|
||||
|
||||
/**
|
||||
* The extension point that allows plugins to get access to the `analysis`
|
||||
* domain.
|
||||
@@ -186,6 +203,13 @@ class ServerPlugin implements Plugin {
|
||||
List<NavigationContributor> get navigationContributors =>
|
||||
navigationContributorExtensionPoint.extensions;
|
||||
|
||||
/**
|
||||
* Return a list containing all of the occurrences contributors that were
|
||||
* contributed.
|
||||
*/
|
||||
List<OccurrencesContributor> get occurrencesContributors =>
|
||||
occurrencesContributorExtensionPoint.extensions;
|
||||
|
||||
/**
|
||||
* Return a list containing all of the receivers of the `analysis` domain
|
||||
* instance.
|
||||
@@ -231,6 +255,9 @@ class ServerPlugin implements Plugin {
|
||||
navigationContributorExtensionPoint = registerExtensionPoint(
|
||||
NAVIGATION_CONTRIBUTOR_EXTENSION_POINT,
|
||||
_validateNavigationContributorExtension);
|
||||
occurrencesContributorExtensionPoint = registerExtensionPoint(
|
||||
OCCURRENCES_CONTRIBUTOR_EXTENSION_POINT,
|
||||
_validateOccurrencesContributorExtension);
|
||||
}
|
||||
|
||||
@override
|
||||
@@ -253,10 +280,12 @@ class ServerPlugin implements Plugin {
|
||||
// TODO(brianwilkerson) Register the completion contributors.
|
||||
// registerExtension(COMPLETION_CONTRIBUTOR_EXTENSION_POINT_ID, ???);
|
||||
//
|
||||
// Register navigation contributors.
|
||||
// Register analysis contributors.
|
||||
//
|
||||
registerExtension(NAVIGATION_CONTRIBUTOR_EXTENSION_POINT_ID,
|
||||
new DartNavigationComputer());
|
||||
registerExtension(OCCURRENCES_CONTRIBUTOR_EXTENSION_POINT_ID,
|
||||
new DartOccurrencesComputer());
|
||||
//
|
||||
// Register domains.
|
||||
//
|
||||
@@ -367,6 +396,18 @@ class ServerPlugin implements Plugin {
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Validate the given extension by throwing an [ExtensionError] if it is not a
|
||||
* valid occurrences contributor.
|
||||
*/
|
||||
void _validateOccurrencesContributorExtension(Object extension) {
|
||||
if (extension is! OccurrencesContributor) {
|
||||
String id = occurrencesContributorExtensionPoint.uniqueIdentifier;
|
||||
throw new ExtensionError(
|
||||
'Extensions to $id must be an OccurrencesContributor');
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Validate the given extension by throwing an [ExtensionError] if it is not a
|
||||
* valid analysis domain receiver.
|
||||
|
||||
@@ -7,8 +7,10 @@ library test.plugin.analysis_contributor;
|
||||
import 'dart:async';
|
||||
|
||||
import 'package:analysis_server/analysis/analysis_domain.dart';
|
||||
import 'package:analysis_server/analysis/navigation/navigation_core.dart';
|
||||
import 'package:analysis_server/analysis/navigation_core.dart';
|
||||
import 'package:analysis_server/analysis/occurrences_core.dart';
|
||||
import 'package:analysis_server/plugin/navigation.dart';
|
||||
import 'package:analysis_server/plugin/occurrences.dart';
|
||||
import 'package:analysis_server/src/constants.dart';
|
||||
import 'package:analysis_server/src/protocol.dart';
|
||||
import 'package:analyzer/src/generated/engine.dart';
|
||||
@@ -38,9 +40,8 @@ main() {
|
||||
class SetAnalysisDomainTest extends AbstractAnalysisTest {
|
||||
final Set<String> parsedUnitFiles = new Set<String>();
|
||||
|
||||
List<NavigationRegion> regions;
|
||||
List<NavigationTarget> targets;
|
||||
List<String> targetFiles;
|
||||
AnalysisNavigationParams navigationParams;
|
||||
AnalysisOccurrencesParams occurrencesParams;
|
||||
|
||||
@override
|
||||
void addServerPlugins(List<Plugin> plugins) {
|
||||
@@ -53,9 +54,13 @@ class SetAnalysisDomainTest extends AbstractAnalysisTest {
|
||||
if (notification.event == ANALYSIS_NAVIGATION) {
|
||||
var params = new AnalysisNavigationParams.fromNotification(notification);
|
||||
if (params.file == testFile) {
|
||||
regions = params.regions;
|
||||
targets = params.targets;
|
||||
targetFiles = params.files;
|
||||
navigationParams = params;
|
||||
}
|
||||
}
|
||||
if (notification.event == ANALYSIS_OCCURRENCES) {
|
||||
var params = new AnalysisOccurrencesParams.fromNotification(notification);
|
||||
if (params.file == testFile) {
|
||||
occurrencesParams = params;
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -63,27 +68,38 @@ class SetAnalysisDomainTest extends AbstractAnalysisTest {
|
||||
Future test_contributorIsInvoked() async {
|
||||
createProject();
|
||||
addAnalysisSubscription(AnalysisService.NAVIGATION, testFile);
|
||||
addAnalysisSubscription(AnalysisService.OCCURRENCES, testFile);
|
||||
addTestFile('// usually no navigation');
|
||||
await server.onAnalysisComplete;
|
||||
// we have PARSED_UNIT
|
||||
expect(parsedUnitFiles, contains(testFile));
|
||||
// we have an additional navigation region/target
|
||||
expect(regions, hasLength(1));
|
||||
{
|
||||
NavigationRegion region = regions.single;
|
||||
expect(region.offset, 1);
|
||||
expect(region.length, 5);
|
||||
expect(region.targets.single, 0);
|
||||
expect(navigationParams.regions, hasLength(1));
|
||||
{
|
||||
NavigationRegion region = navigationParams.regions.single;
|
||||
expect(region.offset, 1);
|
||||
expect(region.length, 5);
|
||||
expect(region.targets.single, 0);
|
||||
}
|
||||
{
|
||||
NavigationTarget target = navigationParams.targets.single;
|
||||
expect(target.fileIndex, 0);
|
||||
expect(target.offset, 1);
|
||||
expect(target.length, 2);
|
||||
expect(target.startLine, 3);
|
||||
expect(target.startColumn, 4);
|
||||
}
|
||||
expect(navigationParams.files.single, '/testLocation.dart');
|
||||
}
|
||||
// we have additional occurrences
|
||||
{
|
||||
NavigationTarget target = targets.single;
|
||||
expect(target.fileIndex, 0);
|
||||
expect(target.offset, 1);
|
||||
expect(target.length, 2);
|
||||
expect(target.startLine, 3);
|
||||
expect(target.startColumn, 4);
|
||||
expect(occurrencesParams.occurrences, hasLength(1));
|
||||
Occurrences occurrences = occurrencesParams.occurrences.single;
|
||||
expect(occurrences.element.name, 'TestElement');
|
||||
expect(occurrences.length, 5);
|
||||
expect(occurrences.offsets, unorderedEquals([1, 2, 3]));
|
||||
}
|
||||
expect(targetFiles.single, '/testLocation.dart');
|
||||
}
|
||||
}
|
||||
|
||||
@@ -100,6 +116,19 @@ class TestNavigationContributor implements NavigationContributor {
|
||||
}
|
||||
}
|
||||
|
||||
class TestOccurrencesContributor implements OccurrencesContributor {
|
||||
final SetAnalysisDomainTest test;
|
||||
|
||||
TestOccurrencesContributor(this.test);
|
||||
|
||||
@override
|
||||
void computeOccurrences(
|
||||
OccurrencesCollector collector, AnalysisContext context, Source source) {
|
||||
collector.addOccurrences(new Occurrences(
|
||||
new Element(ElementKind.UNKNOWN, 'TestElement', 0), <int>[1, 2, 3], 5));
|
||||
}
|
||||
}
|
||||
|
||||
class TestSetAnalysisDomainPlugin implements Plugin {
|
||||
final SetAnalysisDomainTest test;
|
||||
|
||||
@@ -116,6 +145,8 @@ class TestSetAnalysisDomainPlugin implements Plugin {
|
||||
register(SET_ANALYSIS_DOMAIN_EXTENSION_POINT_ID, _setAnalysisDomain);
|
||||
register(NAVIGATION_CONTRIBUTOR_EXTENSION_POINT_ID,
|
||||
new TestNavigationContributor(test));
|
||||
register(OCCURRENCES_CONTRIBUTOR_EXTENSION_POINT_ID,
|
||||
new TestOccurrencesContributor(test));
|
||||
}
|
||||
|
||||
void _setAnalysisDomain(AnalysisDomain domain) {
|
||||
@@ -127,6 +158,8 @@ class TestSetAnalysisDomainPlugin implements Plugin {
|
||||
test.parsedUnitFiles.add(source.fullName);
|
||||
domain.scheduleNotification(
|
||||
result.context, source, AnalysisService.NAVIGATION);
|
||||
domain.scheduleNotification(
|
||||
result.context, source, AnalysisService.OCCURRENCES);
|
||||
});
|
||||
}
|
||||
}
|
||||
|
||||
Reference in New Issue
Block a user