blob: dba4f370c58c34beabbfaedbbc5b76c14aea288d [file] [log] [blame]
// 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.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 = new protocol.Element.fromEngine(engineElement);
var length = engineElement.displayName.length;
occurrences.add(new protocol.Occurrences(serverElement, offsets, length));
});
return occurrences;
}
void _addOccurrence(Element element, int offset) {
if (element == null || element == DynamicElementImpl.instance) {
return;
}
element = _canonicalizeElement(element);
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);
}
}