Index: pkg/analysis_server/lib/src/computer/computer_overrides.dart |
diff --git a/pkg/analysis_server/lib/src/computer/computer_overrides.dart b/pkg/analysis_server/lib/src/computer/computer_overrides.dart |
new file mode 100644 |
index 0000000000000000000000000000000000000000..832fa7ec8833dd4bb47695f0e69ee22c58643b8e |
--- /dev/null |
+++ b/pkg/analysis_server/lib/src/computer/computer_overrides.dart |
@@ -0,0 +1,159 @@ |
+// 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.overrides; |
+ |
+import 'package:analysis_server/src/computer/element.dart'; |
+import 'package:analysis_server/src/constants.dart'; |
+import 'package:analyzer/src/generated/ast.dart'; |
+import 'package:analyzer/src/generated/element.dart' as engine; |
+ |
+ |
+/** |
+ * A computer for class member overrides in a Dart [CompilationUnit]. |
+ */ |
+class DartUnitOverridesComputer { |
+ final CompilationUnit _unit; |
+ |
+ final List<Override> _overrides = <Override>[]; |
+ engine.ClassElement _currentClass; |
+ |
+ DartUnitOverridesComputer(this._unit); |
+ |
+ /** |
+ * Returns the computed occurrences, not `null`. |
+ */ |
+ List<Map<String, Object>> compute() { |
+ for (CompilationUnitMember unitMember in _unit.declarations) { |
+ if (unitMember is ClassDeclaration) { |
+ _currentClass = unitMember.element; |
+ for (ClassMember classMember in unitMember.members) { |
+ if (classMember is MethodDeclaration) { |
+ SimpleIdentifier nameNode = classMember.name; |
+ _addOverride(nameNode.offset, nameNode.length, nameNode.name); |
+ } |
+ if (classMember is FieldDeclaration) { |
+ List<VariableDeclaration> fields = classMember.fields.variables; |
+ for (VariableDeclaration field in fields) { |
+ SimpleIdentifier nameNode = field.name; |
+ _addOverride(nameNode.offset, nameNode.length, nameNode.name); |
+ } |
+ } |
+ } |
+ } |
+ } |
+ return _overrides.map((override) => override.toJson()).toList(); |
+ } |
+ |
+ void _addOverride(int offset, int length, String name) { |
+ // super |
+ engine.Element superEngineElement; |
+ { |
+ engine.InterfaceType superType = _currentClass.supertype; |
+ if (superType != null) { |
+ superEngineElement = _lookupMember(superType.element, name); |
+ } |
+ } |
+ // interfaces |
+ List<engine.Element> interfaceEngineElements = <engine.Element>[]; |
+ for (engine.InterfaceType interfaceType in _currentClass.interfaces) { |
+ engine.ClassElement interfaceElement = interfaceType.element; |
+ engine.Element interfaceMember = _lookupMember(interfaceElement, name); |
+ if (interfaceMember != null) { |
+ interfaceEngineElements.add(interfaceMember); |
+ } |
+ } |
+ // is there any override? |
+ if (superEngineElement != null || interfaceEngineElements.isNotEmpty) { |
+ Element superElement = superEngineElement != null ? |
+ new Element.fromEngine(superEngineElement) : null; |
+ List<Element> interfaceElements = interfaceEngineElements.map( |
+ (engineElement) { |
+ return new Element.fromEngine(engineElement); |
+ }).toList(); |
+ _overrides.add(new Override(offset, length, superElement, |
+ interfaceElements)); |
+ } |
+ } |
+ |
+ static engine.Element _lookupMember(engine.ClassElement classElement, |
+ String name) { |
+ if (classElement == null) { |
+ return null; |
+ } |
+ engine.LibraryElement library = classElement.library; |
+ // method |
+ engine.Element member = classElement.lookUpMethod(name, library); |
+ if (member != null) { |
+ return member; |
+ } |
+ // getter |
+ member = classElement.lookUpGetter(name, library); |
+ if (member != null) { |
+ return member; |
+ } |
+ // setter |
+ member = classElement.lookUpSetter(name + '=', library); |
+ if (member != null) { |
+ return member; |
+ } |
+ // not found |
+ return null; |
+ } |
+} |
+ |
+ |
+class Override { |
+ final int offset; |
+ final int length; |
+ final Element superclassElement; |
+ final List<Element> interfaceElements; |
+ |
+ Override(this.offset, this.length, this.superclassElement, |
+ this.interfaceElements); |
+ |
+ factory Override.fromJson(Map<String, Object> map) { |
+ int offset = map[OFFSET]; |
+ int length = map[LENGTH]; |
+ // super |
+ Element superclassElement = null; |
+ { |
+ Map<String, Object> superJson = map[SUPER_CLASS_ELEMENT]; |
+ if (superJson != null) { |
+ superclassElement = new Element.fromJson(superJson); |
+ } |
+ } |
+ // interfaces |
+ List<Element> interfaceElements = null; |
+ { |
+ List<Map<String, Object>> jsonList = map[INTERFACE_ELEMENTS]; |
+ if (jsonList != null) { |
+ interfaceElements = <Element>[]; |
+ for (Map<String, Object> json in jsonList) { |
+ interfaceElements.add(new Element.fromJson(json)); |
+ } |
+ } |
+ } |
+ // done |
+ return new Override(offset, length, superclassElement, interfaceElements); |
+ } |
+ |
+ Map<String, Object> toJson() { |
+ Map<String, Object> json = <String, Object>{}; |
+ json[OFFSET] = offset; |
+ json[LENGTH] = length; |
+ if (superclassElement != null) { |
+ json[SUPER_CLASS_ELEMENT] = superclassElement.toJson(); |
+ } |
+ if (interfaceElements != null && interfaceElements.isNotEmpty) { |
+ json[INTERFACE_ELEMENTS] = interfaceElements.map((element) { |
+ return element.toJson(); |
+ }).toList(); |
+ } |
+ return json; |
+ } |
+ |
+ @override |
+ String toString() => toJson().toString(); |
+} |