Index: pkg/analysis_server/lib/src/services/index/indexable_element.dart |
diff --git a/pkg/analysis_server/lib/src/services/index/indexable_element.dart b/pkg/analysis_server/lib/src/services/index/indexable_element.dart |
new file mode 100644 |
index 0000000000000000000000000000000000000000..d3977239294be15f84bc05350a343bd1dd7a0ebb |
--- /dev/null |
+++ b/pkg/analysis_server/lib/src/services/index/indexable_element.dart |
@@ -0,0 +1,159 @@ |
+// 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 src.services.index; |
+ |
+import 'dart:collection'; |
+ |
+import 'package:analysis_server/analysis/index/index_core.dart'; |
+import 'package:analyzer/src/generated/element.dart'; |
+import 'package:analyzer/src/generated/engine.dart'; |
+import 'package:analyzer/src/generated/source.dart'; |
+ |
+/** |
+ * A wrapper around an [Element] that implements the [IndexableObject] interface. |
+ */ |
+class IndexableElement implements IndexableObject { |
+ /** |
+ * The element being wrapped. |
+ */ |
+ final Element element; |
+ |
+ /** |
+ * Initialize a newly created wrapper to wrap the given [element]. |
+ */ |
+ IndexableElement(this.element); |
+ |
+ @override |
+ int get hashCode => element.hashCode; |
+ |
+ @override |
+ IndexableObjectKind get kind => IndexableElementKind.forElement(element); |
+ |
+ @override |
+ int get length => element.displayName.length; |
+ |
+ @override |
+ String get name => element.displayName; |
+ |
+ @override |
+ int get offset { |
+ if (element is ConstructorElement) { |
+ return element.enclosingElement.nameOffset; |
+ } |
+ return element.nameOffset; |
+ } |
+ |
+ @override |
+ Source get source => element.source; |
+ |
+ @override |
+ bool operator ==(Object object) => |
+ object is IndexableElement && element == object.element; |
+ |
+ @override |
+ String toString() => element.toString(); |
+} |
+ |
+/** |
+ * The kind associated with an [IndexableElement]. |
+ */ |
+class IndexableElementKind implements IndexableObjectKind { |
+ /** |
+ * A table mapping element kinds to the corresponding indexable element kind. |
+ */ |
+ static Map<ElementKind, IndexableElementKind> _kindMap = |
+ new HashMap<ElementKind, IndexableElementKind>(); |
+ |
+ /** |
+ * A table mapping the index of a constructor (in the lexically-ordered list |
+ * of constructors associated with a class) to the indexable element kind used |
+ * to represent it. |
+ */ |
+ static Map<int, IndexableElementKind> _constructorKinds = |
+ new HashMap<int, IndexableElementKind>(); |
+ |
+ @override |
+ final int index; |
scheglov
2015/05/25 18:29:33
Will this work?
So, we could avoid passing in thro
Brian Wilkerson
2015/06/01 13:20:08
Done
|
+ |
+ /** |
+ * The element kind represented by this index element kind. |
+ */ |
+ final ElementKind elementKind; |
+ |
+ /** |
+ * Initialize a newly created kind to have the given [index] and be associated |
+ * with the given [elementKind]. |
+ */ |
+ IndexableElementKind._(this.index, this.elementKind) { |
+ IndexableObjectKind.register(this); |
+ } |
+ |
+ /** |
+ * Return the index of the constructor with this indexable element kind. |
+ */ |
+ int get constructorIndex { |
+ for (int index in _constructorKinds.keys) { |
+ if (_constructorKinds[index] == this) { |
+ return index; |
+ } |
+ } |
+ return -1; |
+ } |
+ |
+ @override |
+ IndexableObject decode(AnalysisContext context, String filePath, int offset) { |
+ List<Source> unitSources = context.getSourcesWithFullName(filePath); |
+ for (Source unitSource in unitSources) { |
+ List<Source> libSources = context.getLibrariesContaining(unitSource); |
+ for (Source libSource in libSources) { |
+ CompilationUnitElement unitElement = |
+ context.getCompilationUnitElement(unitSource, libSource); |
+ if (unitElement == null) { |
+ return null; |
+ } |
+ if (elementKind == ElementKind.LIBRARY) { |
+ return new IndexableElement(unitElement.library); |
+ } else if (elementKind == ElementKind.COMPILATION_UNIT) { |
+ return new IndexableElement(unitElement); |
+ } else { |
+ Element element = unitElement.getElementAt(offset); |
+ if (element == null) { |
+ return null; |
+ } |
+ if (element is ClassElement && |
+ elementKind == ElementKind.CONSTRUCTOR) { |
+ return new IndexableElement(element.constructors[constructorIndex]); |
+ } |
+ if (element is PropertyInducingElement) { |
+ if (elementKind == ElementKind.GETTER) { |
+ return new IndexableElement(element.getter); |
+ } |
+ if (elementKind == ElementKind.SETTER) { |
+ return new IndexableElement(element.setter); |
+ } |
+ } |
+ return new IndexableElement(element); |
+ } |
+ } |
+ } |
+ return null; |
+ } |
+ |
+ /** |
+ * Return the indexable element kind representing the given [element]. |
+ */ |
+ static IndexableElementKind forElement(Element element) { |
+ if (element is ConstructorElement) { |
+ ClassElement classElement = element.enclosingElement; |
+ int constructorIndex = classElement.constructors.indexOf(element); |
+ return _constructorKinds.putIfAbsent(constructorIndex, |
+ () => new IndexableElementKind._( |
+ IndexableObjectKind.nextIndex, ElementKind.CONSTRUCTOR)); |
+ } |
+ ElementKind elementKind = element.kind; |
+ return _kindMap.putIfAbsent(elementKind, () => |
+ new IndexableElementKind._(IndexableObjectKind.nextIndex, elementKind)); |
+ } |
+} |