mirror of
https://github.com/dart-lang/sdk
synced 2024-10-14 08:31:29 +00:00
Use single unit/node/element.
R=brianwilkerson@google.com BUG= Review URL: https://codereview.chromium.org/2525693002 .
This commit is contained in:
parent
21b6f8904c
commit
ab0a8e775f
|
@ -706,41 +706,36 @@ class AnalysisServer {
|
|||
}
|
||||
|
||||
/**
|
||||
* Returns [Element]s at the given [offset] of the given [file].
|
||||
*
|
||||
* May be empty if cannot be resolved, but not `null`.
|
||||
* Return the [Element] at the given [offset] of the given [file], or `null`
|
||||
* if there is no node at the [offset] or the node does not have an element.
|
||||
*/
|
||||
List<Element> getElementsAtOffset(String file, int offset) {
|
||||
List<AstNode> nodes = getNodesAtOffset(file, offset);
|
||||
return getElementsOfNodes(nodes);
|
||||
Element getElementAtOffset(String file, int offset) {
|
||||
AstNode node = getNodeAtOffset(file, offset);
|
||||
return getElementOfNode(node);
|
||||
}
|
||||
|
||||
/**
|
||||
* Returns [Element]s of the given [nodes].
|
||||
*
|
||||
* May be empty if not resolved, but not `null`.
|
||||
* Return the [Element] of the given [node], or `null` if [node] is `null` or
|
||||
* does not have an element.
|
||||
*/
|
||||
List<Element> getElementsOfNodes(List<AstNode> nodes) {
|
||||
List<Element> elements = <Element>[];
|
||||
for (AstNode node in nodes) {
|
||||
if (node is SimpleIdentifier && node.parent is LibraryIdentifier) {
|
||||
node = node.parent;
|
||||
}
|
||||
if (node is LibraryIdentifier) {
|
||||
node = node.parent;
|
||||
}
|
||||
if (node is StringLiteral && node.parent is UriBasedDirective) {
|
||||
continue;
|
||||
}
|
||||
Element element = ElementLocator.locate(node);
|
||||
if (node is SimpleIdentifier && element is PrefixElement) {
|
||||
element = getImportElement(node);
|
||||
}
|
||||
if (element != null) {
|
||||
elements.add(element);
|
||||
}
|
||||
Element getElementOfNode(AstNode node) {
|
||||
if (node == null) {
|
||||
return null;
|
||||
}
|
||||
return elements;
|
||||
if (node is SimpleIdentifier && node.parent is LibraryIdentifier) {
|
||||
node = node.parent;
|
||||
}
|
||||
if (node is LibraryIdentifier) {
|
||||
node = node.parent;
|
||||
}
|
||||
if (node is StringLiteral && node.parent is UriBasedDirective) {
|
||||
return null;
|
||||
}
|
||||
Element element = ElementLocator.locate(node);
|
||||
if (node is SimpleIdentifier && element is PrefixElement) {
|
||||
element = getImportElement(node);
|
||||
}
|
||||
return element;
|
||||
}
|
||||
|
||||
/**
|
||||
|
@ -770,49 +765,35 @@ class AnalysisServer {
|
|||
}
|
||||
|
||||
/**
|
||||
* Returns resolved [AstNode]s at the given [offset] of the given [file].
|
||||
*
|
||||
* May be empty, but not `null`.
|
||||
* Return the resolved [AstNode]s at the given [offset] of the given [file],
|
||||
* or `null` if there is no node as the [offset].
|
||||
*/
|
||||
List<AstNode> getNodesAtOffset(String file, int offset) {
|
||||
List<CompilationUnit> units = getResolvedCompilationUnits(file);
|
||||
List<AstNode> nodes = <AstNode>[];
|
||||
for (CompilationUnit unit in units) {
|
||||
AstNode node = new NodeLocator(offset).searchWithin(unit);
|
||||
if (node != null) {
|
||||
nodes.add(node);
|
||||
}
|
||||
AstNode getNodeAtOffset(String file, int offset) {
|
||||
CompilationUnit unit = getResolvedCompilationUnit(file);
|
||||
if (unit != null) {
|
||||
return new NodeLocator(offset).searchWithin(unit);
|
||||
}
|
||||
return nodes;
|
||||
return null;
|
||||
}
|
||||
|
||||
/**
|
||||
* Returns resolved [CompilationUnit]s of the Dart file with the given [path].
|
||||
*
|
||||
* May be empty, but not `null`.
|
||||
* Return the resolved [CompilationUnit] for the Dart file with the given
|
||||
* [path], or `null` if the file is not a Dart file or cannot be resolved.
|
||||
*/
|
||||
List<CompilationUnit> getResolvedCompilationUnits(String path) {
|
||||
List<CompilationUnit> units = <CompilationUnit>[];
|
||||
CompilationUnit getResolvedCompilationUnit(String path) {
|
||||
ContextSourcePair contextSource = getContextSourcePair(path);
|
||||
// prepare AnalysisContext
|
||||
AnalysisContext context = contextSource.context;
|
||||
if (context == null) {
|
||||
return units;
|
||||
return null;
|
||||
}
|
||||
// add a unit for each unit/library combination
|
||||
runWithActiveContext(context, () {
|
||||
return runWithActiveContext(context, () {
|
||||
Source unitSource = contextSource.source;
|
||||
List<Source> librarySources = context.getLibrariesContaining(unitSource);
|
||||
for (Source librarySource in librarySources) {
|
||||
CompilationUnit unit =
|
||||
context.resolveCompilationUnit2(unitSource, librarySource);
|
||||
if (unit != null) {
|
||||
units.add(unit);
|
||||
}
|
||||
return context.resolveCompilationUnit2(unitSource, librarySource);
|
||||
}
|
||||
return null;
|
||||
});
|
||||
// done
|
||||
return units;
|
||||
}
|
||||
|
||||
// TODO(brianwilkerson) Add the following method after 'prioritySources' has
|
||||
|
|
|
@ -90,17 +90,17 @@ class AnalysisDomainHandler implements RequestHandler {
|
|||
var params = new AnalysisGetHoverParams.fromRequest(request);
|
||||
|
||||
// Prepare the resolved units.
|
||||
List<CompilationUnit> units;
|
||||
CompilationUnit unit;
|
||||
if (server.options.enableNewAnalysisDriver) {
|
||||
AnalysisResult result = await server.getAnalysisResult(params.file);
|
||||
units = result != null ? [result.unit] : null;
|
||||
unit = result?.unit;
|
||||
} else {
|
||||
units = server.getResolvedCompilationUnits(params.file);
|
||||
unit = server.getResolvedCompilationUnit(params.file);
|
||||
}
|
||||
|
||||
// Prepare the hovers.
|
||||
List<HoverInformation> hovers = <HoverInformation>[];
|
||||
for (CompilationUnit unit in units) {
|
||||
if (unit != null) {
|
||||
HoverInformation hoverInformation =
|
||||
new DartUnitHoverComputer(unit, params.offset).compute();
|
||||
if (hoverInformation != null) {
|
||||
|
@ -147,12 +147,11 @@ class AnalysisDomainHandler implements RequestHandler {
|
|||
analysisFuture.then((AnalysisDoneReason reason) {
|
||||
switch (reason) {
|
||||
case AnalysisDoneReason.COMPLETE:
|
||||
List<CompilationUnit> units =
|
||||
server.getResolvedCompilationUnits(file);
|
||||
if (units.isEmpty) {
|
||||
CompilationUnit unit = server.getResolvedCompilationUnit(file);
|
||||
if (unit == null) {
|
||||
server.sendResponse(new Response.getNavigationInvalidFile(request));
|
||||
} else {
|
||||
CompilationUnitElement unitElement = units.first.element;
|
||||
CompilationUnitElement unitElement = unit.element;
|
||||
NavigationCollectorImpl collector = computeNavigation(
|
||||
server,
|
||||
unitElement.context,
|
||||
|
|
|
@ -201,27 +201,25 @@ class EditDomainHandler implements RequestHandler {
|
|||
}
|
||||
}
|
||||
} else {
|
||||
List<CompilationUnit> units = server.getResolvedCompilationUnits(file);
|
||||
for (CompilationUnit unit in units) {
|
||||
engine.AnalysisErrorInfo errorInfo = server.getErrors(file);
|
||||
if (errorInfo != null) {
|
||||
LineInfo lineInfo = errorInfo.lineInfo;
|
||||
int requestLine = lineInfo.getLocation(offset).lineNumber;
|
||||
for (engine.AnalysisError error in errorInfo.errors) {
|
||||
int errorLine = lineInfo.getLocation(error.offset).lineNumber;
|
||||
if (errorLine == requestLine) {
|
||||
List<Fix> fixes = await computeFixes(server.serverPlugin,
|
||||
server.resourceProvider, unit.element.context, error);
|
||||
if (fixes.isNotEmpty) {
|
||||
AnalysisError serverError =
|
||||
newAnalysisError_fromEngine(lineInfo, error);
|
||||
AnalysisErrorFixes errorFixes =
|
||||
new AnalysisErrorFixes(serverError);
|
||||
errorFixesList.add(errorFixes);
|
||||
fixes.forEach((fix) {
|
||||
errorFixes.fixes.add(fix.change);
|
||||
});
|
||||
}
|
||||
CompilationUnit unit = server.getResolvedCompilationUnit(file);
|
||||
engine.AnalysisErrorInfo errorInfo = server.getErrors(file);
|
||||
if (errorInfo != null) {
|
||||
LineInfo lineInfo = errorInfo.lineInfo;
|
||||
int requestLine = lineInfo.getLocation(offset).lineNumber;
|
||||
for (engine.AnalysisError error in errorInfo.errors) {
|
||||
int errorLine = lineInfo.getLocation(error.offset).lineNumber;
|
||||
if (errorLine == requestLine) {
|
||||
List<Fix> fixes = await computeFixes(server.serverPlugin,
|
||||
server.resourceProvider, unit.element.context, error);
|
||||
if (fixes.isNotEmpty) {
|
||||
AnalysisError serverError =
|
||||
newAnalysisError_fromEngine(lineInfo, error);
|
||||
AnalysisErrorFixes errorFixes =
|
||||
new AnalysisErrorFixes(serverError);
|
||||
errorFixesList.add(errorFixes);
|
||||
fixes.forEach((fix) {
|
||||
errorFixes.fixes.add(fix.change);
|
||||
});
|
||||
}
|
||||
}
|
||||
}
|
||||
|
@ -286,14 +284,13 @@ class EditDomainHandler implements RequestHandler {
|
|||
unit = result.unit;
|
||||
errors = result.errors;
|
||||
} else {
|
||||
// prepare resolved units
|
||||
List<CompilationUnit> units = server.getResolvedCompilationUnits(file);
|
||||
if (units.isEmpty) {
|
||||
// prepare resolved unit
|
||||
unit = server.getResolvedCompilationUnit(file);
|
||||
if (unit == null) {
|
||||
server.sendResponse(new Response.fileNotAnalyzed(request, file));
|
||||
return;
|
||||
}
|
||||
// prepare context
|
||||
unit = units.first;
|
||||
engine.AnalysisContext context = unit.element.context;
|
||||
Source source = unit.element.source;
|
||||
errors = context.computeErrors(source);
|
||||
|
@ -400,9 +397,8 @@ class EditDomainHandler implements RequestHandler {
|
|||
}
|
||||
// check elements
|
||||
{
|
||||
List<Element> elements = server.getElementsAtOffset(file, offset);
|
||||
if (elements.isNotEmpty) {
|
||||
Element element = elements[0];
|
||||
Element element = server.getElementAtOffset(file, offset);
|
||||
if (element != null) {
|
||||
// try CONVERT_METHOD_TO_GETTER
|
||||
if (element is ExecutableElement) {
|
||||
Refactoring refactoring =
|
||||
|
@ -708,9 +704,8 @@ class _RefactoringManager {
|
|||
}
|
||||
// create a new Refactoring instance
|
||||
if (kind == RefactoringKind.CONVERT_GETTER_TO_METHOD) {
|
||||
List<Element> elements = server.getElementsAtOffset(file, offset);
|
||||
if (elements.isNotEmpty) {
|
||||
Element element = elements[0];
|
||||
Element element = server.getElementAtOffset(file, offset);
|
||||
if (element != null) {
|
||||
if (element is ExecutableElement) {
|
||||
_resetOnAnalysisStarted();
|
||||
refactoring =
|
||||
|
@ -719,9 +714,8 @@ class _RefactoringManager {
|
|||
}
|
||||
}
|
||||
if (kind == RefactoringKind.CONVERT_METHOD_TO_GETTER) {
|
||||
List<Element> elements = server.getElementsAtOffset(file, offset);
|
||||
if (elements.isNotEmpty) {
|
||||
Element element = elements[0];
|
||||
Element element = server.getElementAtOffset(file, offset);
|
||||
if (element != null) {
|
||||
if (element is ExecutableElement) {
|
||||
_resetOnAnalysisStarted();
|
||||
refactoring =
|
||||
|
@ -730,10 +724,10 @@ class _RefactoringManager {
|
|||
}
|
||||
}
|
||||
if (kind == RefactoringKind.EXTRACT_LOCAL_VARIABLE) {
|
||||
List<CompilationUnit> units = server.getResolvedCompilationUnits(file);
|
||||
if (units.isNotEmpty) {
|
||||
CompilationUnit unit = server.getResolvedCompilationUnit(file);
|
||||
if (unit != null) {
|
||||
_resetOnFileResolutionChanged(file);
|
||||
refactoring = new ExtractLocalRefactoring(units[0], offset, length);
|
||||
refactoring = new ExtractLocalRefactoring(unit, offset, length);
|
||||
feedback = new ExtractLocalVariableFeedback(
|
||||
<String>[], <int>[], <int>[],
|
||||
coveringExpressionOffsets: <int>[],
|
||||
|
@ -741,29 +735,27 @@ class _RefactoringManager {
|
|||
}
|
||||
}
|
||||
if (kind == RefactoringKind.EXTRACT_METHOD) {
|
||||
List<CompilationUnit> units = server.getResolvedCompilationUnits(file);
|
||||
if (units.isNotEmpty) {
|
||||
CompilationUnit unit = server.getResolvedCompilationUnit(file);
|
||||
if (unit != null) {
|
||||
_resetOnAnalysisStarted();
|
||||
refactoring = new ExtractMethodRefactoring(
|
||||
searchEngine, units[0], offset, length);
|
||||
refactoring =
|
||||
new ExtractMethodRefactoring(searchEngine, unit, offset, length);
|
||||
feedback = new ExtractMethodFeedback(offset, length, '', <String>[],
|
||||
false, <RefactoringMethodParameter>[], <int>[], <int>[]);
|
||||
}
|
||||
}
|
||||
if (kind == RefactoringKind.INLINE_LOCAL_VARIABLE) {
|
||||
List<CompilationUnit> units = server.getResolvedCompilationUnits(file);
|
||||
if (units.isNotEmpty) {
|
||||
CompilationUnit unit = server.getResolvedCompilationUnit(file);
|
||||
if (unit != null) {
|
||||
_resetOnFileResolutionChanged(file);
|
||||
refactoring =
|
||||
new InlineLocalRefactoring(searchEngine, units[0], offset);
|
||||
refactoring = new InlineLocalRefactoring(searchEngine, unit, offset);
|
||||
}
|
||||
}
|
||||
if (kind == RefactoringKind.INLINE_METHOD) {
|
||||
List<CompilationUnit> units = server.getResolvedCompilationUnits(file);
|
||||
if (units.isNotEmpty) {
|
||||
CompilationUnit unit = server.getResolvedCompilationUnit(file);
|
||||
if (unit != null) {
|
||||
_resetOnAnalysisStarted();
|
||||
refactoring =
|
||||
new InlineMethodRefactoring(searchEngine, units[0], offset);
|
||||
refactoring = new InlineMethodRefactoring(searchEngine, unit, offset);
|
||||
}
|
||||
}
|
||||
if (kind == RefactoringKind.MOVE_FILE) {
|
||||
|
@ -775,11 +767,9 @@ class _RefactoringManager {
|
|||
server.resourceProvider, searchEngine, context, source, file);
|
||||
}
|
||||
if (kind == RefactoringKind.RENAME) {
|
||||
List<AstNode> nodes = server.getNodesAtOffset(file, offset);
|
||||
List<Element> elements = server.getElementsOfNodes(nodes);
|
||||
if (nodes.isNotEmpty && elements.isNotEmpty) {
|
||||
AstNode node = nodes[0];
|
||||
Element element = elements[0];
|
||||
AstNode node = server.getNodeAtOffset(file, offset);
|
||||
Element element = server.getElementOfNode(node);
|
||||
if (node != null && element != null) {
|
||||
if (element is FieldFormalParameterElement) {
|
||||
element = (element as FieldFormalParameterElement).field;
|
||||
}
|
||||
|
|
|
@ -35,7 +35,7 @@ runWithActiveContext(AnalysisContext context, f()) {
|
|||
context.isActive = false;
|
||||
}
|
||||
} else {
|
||||
f();
|
||||
return f();
|
||||
}
|
||||
}
|
||||
|
||||
|
|
|
@ -61,39 +61,30 @@ class SearchDomainHandler implements protocol.RequestHandler {
|
|||
var params =
|
||||
new protocol.SearchFindElementReferencesParams.fromRequest(request);
|
||||
await server.onAnalysisComplete;
|
||||
// prepare elements
|
||||
List<Element> elements =
|
||||
server.getElementsAtOffset(params.file, params.offset);
|
||||
elements = elements.map((Element element) {
|
||||
if (element is ImportElement) {
|
||||
return element.prefix;
|
||||
}
|
||||
if (element is FieldFormalParameterElement) {
|
||||
return element.field;
|
||||
}
|
||||
if (element is PropertyAccessorElement) {
|
||||
return element.variable;
|
||||
}
|
||||
return element;
|
||||
}).where((Element element) {
|
||||
return element != null;
|
||||
}).toList();
|
||||
// prepare element
|
||||
Element element = server.getElementAtOffset(params.file, params.offset);
|
||||
if (element is ImportElement) {
|
||||
element = (element as ImportElement).prefix;
|
||||
}
|
||||
if (element is FieldFormalParameterElement) {
|
||||
element = (element as FieldFormalParameterElement).field;
|
||||
}
|
||||
if (element is PropertyAccessorElement) {
|
||||
element = (element as PropertyAccessorElement).variable;
|
||||
}
|
||||
// respond
|
||||
String searchId = (_nextSearchId++).toString();
|
||||
var result = new protocol.SearchFindElementReferencesResult();
|
||||
if (elements.isNotEmpty) {
|
||||
if (element != null) {
|
||||
result.id = searchId;
|
||||
result.element = protocol.convertElement(elements.first);
|
||||
result.element = protocol.convertElement(element);
|
||||
}
|
||||
_sendSearchResult(request, result);
|
||||
// search elements
|
||||
elements.forEach((Element element) async {
|
||||
var computer = new ElementReferencesComputer(searchEngine);
|
||||
List<protocol.SearchResult> results =
|
||||
await computer.compute(element, params.includePotential);
|
||||
bool isLast = identical(element, elements.last);
|
||||
_sendSearchNotification(searchId, isLast, results);
|
||||
});
|
||||
var computer = new ElementReferencesComputer(searchEngine);
|
||||
List<protocol.SearchResult> results =
|
||||
await computer.compute(element, params.includePotential);
|
||||
_sendSearchNotification(searchId, true, results);
|
||||
}
|
||||
|
||||
Future findMemberDeclarations(protocol.Request request) async {
|
||||
|
@ -171,12 +162,11 @@ class SearchDomainHandler implements protocol.RequestHandler {
|
|||
await server.onAnalysisComplete;
|
||||
}
|
||||
// prepare element
|
||||
List<Element> elements = server.getElementsAtOffset(file, params.offset);
|
||||
if (elements.isEmpty) {
|
||||
Element element = server.getElementAtOffset(file, params.offset);
|
||||
if (element == null) {
|
||||
_sendTypeHierarchyNull(request);
|
||||
return;
|
||||
}
|
||||
Element element = elements.first;
|
||||
// maybe supertype hierarchy only
|
||||
if (params.superOnly == true) {
|
||||
TypeHierarchyComputer computer =
|
||||
|
|
|
@ -116,8 +116,8 @@ main() {
|
|||
// unit "a" is resolved eventually
|
||||
// unit "b" is not resolved
|
||||
return server.onAnalysisComplete.then((_) {
|
||||
expect(serverRef.getResolvedCompilationUnits(fileA), hasLength(1));
|
||||
expect(serverRef.getResolvedCompilationUnits(fileB), isEmpty);
|
||||
expect(serverRef.getResolvedCompilationUnit(fileA), isNotNull);
|
||||
expect(serverRef.getResolvedCompilationUnit(fileB), isNull);
|
||||
});
|
||||
});
|
||||
|
||||
|
@ -148,8 +148,8 @@ main() {
|
|||
expect(response, isResponseSuccess('0'));
|
||||
// verify that unit is resolved eventually
|
||||
return server.onAnalysisComplete.then((_) {
|
||||
var units = serverRef.getResolvedCompilationUnits(file);
|
||||
expect(units, hasLength(1));
|
||||
var unit = serverRef.getResolvedCompilationUnit(file);
|
||||
expect(unit, isNotNull);
|
||||
});
|
||||
});
|
||||
|
||||
|
@ -162,7 +162,7 @@ main() {
|
|||
// Non-existence of /project_a should not prevent files in /project_b
|
||||
// from being analyzed.
|
||||
await server.onAnalysisComplete;
|
||||
expect(serverRef.getResolvedCompilationUnits(fileB), hasLength(1));
|
||||
expect(serverRef.getResolvedCompilationUnit(fileB), isNotNull);
|
||||
});
|
||||
|
||||
test('not absolute', () async {
|
||||
|
|
|
@ -403,38 +403,6 @@ main() {
|
|||
expect(searchId, isNull);
|
||||
}
|
||||
|
||||
test_oneUnit_twoLibraries() async {
|
||||
var pathA = '/project/bin/libA.dart';
|
||||
var pathB = '/project/bin/libB.dart';
|
||||
var codeA = '''
|
||||
library lib;
|
||||
part 'test.dart';
|
||||
main() {
|
||||
fff(1);
|
||||
}
|
||||
''';
|
||||
var codeB = '''
|
||||
library lib;
|
||||
part 'test.dart';
|
||||
main() {
|
||||
fff(2);
|
||||
}
|
||||
''';
|
||||
addFile(pathA, codeA);
|
||||
addFile(pathB, codeB);
|
||||
addTestFile('''
|
||||
part of lib;
|
||||
fff(p) {}
|
||||
''');
|
||||
await findElementReferences('fff(p) {}', false);
|
||||
expect(searchElement.kind, ElementKind.FUNCTION);
|
||||
expect(results, hasLength(2));
|
||||
findResult(
|
||||
SearchResultKind.INVOCATION, pathA, codeA.indexOf('fff(1)'), 3, true);
|
||||
findResult(
|
||||
SearchResultKind.INVOCATION, pathB, codeB.indexOf('fff(2)'), 3, true);
|
||||
}
|
||||
|
||||
test_oneUnit_zeroLibraries() async {
|
||||
addTestFile('''
|
||||
part of lib;
|
||||
|
|
Loading…
Reference in a new issue