Chromium Code Reviews
chromiumcodereview-hr@appspot.gserviceaccount.com (chromiumcodereview-hr) | Please choose your nickname with Settings | Help | Chromium Project | Gerrit Changes | Sign out
(157)

Side by Side Diff: pkg/analysis_server/lib/src/computer/computer_overrides.dart

Issue 1632033002: Issue 25542. If an element does not have its own documentation, use the documentation from the over… (Closed) Base URL: git@github.com:dart-lang/sdk.git@master
Patch Set: New test cases and tweaks. Created 4 years, 11 months ago
Use n/p to move between diff chunks; N/P to move between comments. Draft comments are only viewable by you.
Jump to:
View unified diff | Download patch
OLDNEW
1 // Copyright (c) 2014, the Dart project authors. Please see the AUTHORS file 1 // Copyright (c) 2014, the Dart project authors. Please see the AUTHORS file
2 // for details. All rights reserved. Use of this source code is governed by a 2 // for details. All rights reserved. Use of this source code is governed by a
3 // BSD-style license that can be found in the LICENSE file. 3 // BSD-style license that can be found in the LICENSE file.
4 4
5 library computer.overrides; 5 library computer.overrides;
6 6
7 import 'package:analysis_server/src/collections.dart'; 7 import 'package:analysis_server/src/collections.dart';
8 import 'package:analysis_server/src/protocol_server.dart'; 8 import 'package:analysis_server/src/protocol_server.dart' as proto;
9 import 'package:analyzer/dart/element/element.dart' as engine; 9 import 'package:analyzer/dart/element/element.dart';
10 import 'package:analyzer/dart/element/type.dart' as engine; 10 import 'package:analyzer/dart/element/type.dart';
11 import 'package:analyzer/src/generated/ast.dart'; 11 import 'package:analyzer/src/generated/ast.dart';
12 12
13 /** 13 /**
14 * Return the elements that the given [element] overrides.
15 */
16 OverriddenElements findOverriddenElements(Element element) {
17 if (element?.enclosingElement is ClassElement) {
18 return new _OverriddenElementsFinder(element).find();
19 }
20 return new OverriddenElements(element, <Element>[], <Element>[]);
21 }
22
23 /**
14 * A computer for class member overrides in a Dart [CompilationUnit]. 24 * A computer for class member overrides in a Dart [CompilationUnit].
15 */ 25 */
16 class DartUnitOverridesComputer { 26 class DartUnitOverridesComputer {
17 static const List<ElementKind> FIELD_KINDS = const <ElementKind>[
18 ElementKind.FIELD,
19 ElementKind.GETTER,
20 ElementKind.SETTER
21 ];
22
23 static const List<ElementKind> GETTER_KINDS = const <ElementKind>[
24 ElementKind.FIELD,
25 ElementKind.GETTER
26 ];
27
28 static const List<ElementKind> METHOD_KINDS = const <ElementKind>[
29 ElementKind.METHOD
30 ];
31
32 static const List<ElementKind> SETTER_KINDS = const <ElementKind>[
33 ElementKind.FIELD,
34 ElementKind.SETTER
35 ];
36
37 final CompilationUnit _unit; 27 final CompilationUnit _unit;
38 28 final List<proto.Override> _overrides = <proto.Override>[];
39 final List<Override> _overrides = <Override>[];
40 engine.ClassElement _currentClass;
41 29
42 DartUnitOverridesComputer(this._unit); 30 DartUnitOverridesComputer(this._unit);
43 31
44 /** 32 /**
45 * Returns the computed occurrences, not `null`. 33 * Returns the computed occurrences, not `null`.
46 */ 34 */
47 List<Override> compute() { 35 List<proto.Override> compute() {
48 for (CompilationUnitMember unitMember in _unit.declarations) { 36 for (CompilationUnitMember unitMember in _unit.declarations) {
49 if (unitMember is ClassDeclaration) { 37 if (unitMember is ClassDeclaration) {
50 _currentClass = unitMember.element;
51 for (ClassMember classMember in unitMember.members) { 38 for (ClassMember classMember in unitMember.members) {
52 if (classMember is MethodDeclaration) { 39 if (classMember is MethodDeclaration) {
53 if (classMember.isStatic) { 40 if (classMember.isStatic) {
54 continue; 41 continue;
55 } 42 }
56 SimpleIdentifier name = classMember.name; 43 _addOverride(classMember.name);
57 List<ElementKind> kinds;
58 if (classMember.isGetter) {
59 kinds = GETTER_KINDS;
60 } else if (classMember.isSetter) {
61 kinds = SETTER_KINDS;
62 } else {
63 kinds = METHOD_KINDS;
64 }
65 new _SingleOverrideComputer(_currentClass, name, kinds)
66 .addOverrideTo(_overrides);
67 } 44 }
68 if (classMember is FieldDeclaration) { 45 if (classMember is FieldDeclaration) {
69 if (classMember.isStatic) { 46 if (classMember.isStatic) {
70 continue; 47 continue;
71 } 48 }
72 List<VariableDeclaration> fields = classMember.fields.variables; 49 List<VariableDeclaration> fields = classMember.fields.variables;
73 for (VariableDeclaration field in fields) { 50 for (VariableDeclaration field in fields) {
74 SimpleIdentifier name = field.name; 51 _addOverride(field.name);
75 new _SingleOverrideComputer(_currentClass, name, FIELD_KINDS)
76 .addOverrideTo(_overrides);
77 } 52 }
78 } 53 }
79 } 54 }
80 } 55 }
81 } 56 }
82 return _overrides; 57 return _overrides;
83 } 58 }
59
60 /**
61 * Add a new [Override] for the declaration with the given name [node].
62 */
63 void _addOverride(SimpleIdentifier node) {
64 Element element = node.staticElement;
65 OverriddenElements overridesResult =
66 new _OverriddenElementsFinder(element).find();
67 List<Element> superElements = overridesResult.superElements;
68 List<Element> interfaceElements = overridesResult.interfaceElements;
69 if (superElements.isNotEmpty || interfaceElements.isNotEmpty) {
70 proto.OverriddenMember superMember = superElements.isNotEmpty
71 ? proto.newOverriddenMember_fromEngine(superElements.first)
72 : null;
73 List<proto.OverriddenMember> interfaceMembers = interfaceElements
74 .map((member) => proto.newOverriddenMember_fromEngine(member))
75 .toList();
76 _overrides.add(new proto.Override(node.offset, node.length,
77 superclassMember: superMember,
78 interfaceMembers: nullIfEmpty(interfaceMembers)));
79 }
80 }
84 } 81 }
85 82
86 /** 83 /**
87 * Computer for [Override] for a single declaration. 84 * The container with elements that a class member overrides.
88 */ 85 */
89 class _SingleOverrideComputer { 86 class OverriddenElements {
90 final engine.LibraryElement currentLibrary; 87 /**
91 final engine.ClassElement currentClass; 88 * The element that overrides other class members.
92 final SimpleIdentifier node; 89 */
93 final String name; 90 final Element element;
94 final List<ElementKind> kinds;
95
96 _SingleOverrideComputer(
97 engine.ClassElement currentClass, SimpleIdentifier node, this.kinds)
98 : currentClass = currentClass,
99 currentLibrary = currentClass.library,
100 node = node,
101 name = node.name;
102 91
103 /** 92 /**
104 * Add a new [Override] for this declaration to the given [overrides]. 93 * The elements that [element] overrides and which is defined in a class that
94 * is a superclass of the class that defines [element].
105 */ 95 */
106 void addOverrideTo(List<Override> overrides) { 96 final List<Element> superElements;
107 // super 97
108 engine.Element superEngineElement; 98 /**
109 { 99 * The elements that [element] overrides and which is defined in a class that
110 engine.InterfaceType superType = currentClass.supertype; 100 * which is implemented by the class that defines [element].
111 if (superType != null) { 101 */
112 superEngineElement = _lookupMember(superType.element); 102 final List<Element> interfaceElements;
103
104 OverriddenElements(this.element, this.superElements, this.interfaceElements);
105 }
106
107 class _OverriddenElementsFinder {
108 static const List<ElementKind> FIELD_KINDS = const <ElementKind>[
109 ElementKind.FIELD,
110 ElementKind.GETTER,
111 ElementKind.SETTER
112 ];
113
114 static const List<ElementKind> GETTER_KINDS = const <ElementKind>[
115 ElementKind.FIELD,
116 ElementKind.GETTER
117 ];
118
119 static const List<ElementKind> METHOD_KINDS = const <ElementKind>[
120 ElementKind.METHOD
121 ];
122
123 static const List<ElementKind> SETTER_KINDS = const <ElementKind>[
124 ElementKind.FIELD,
125 ElementKind.SETTER
126 ];
127
128 Element _seed;
129 LibraryElement _library;
130 ClassElement _class;
131 String _name;
132 List<ElementKind> _kinds;
133
134 List<Element> _superElements = <Element>[];
135 List<Element> _interfaceElements = <Element>[];
136 Set<InterfaceType> _visited = new Set<InterfaceType>();
137
138 _OverriddenElementsFinder(Element seed) {
139 _seed = seed;
140 _class = seed.enclosingElement;
141 _library = _class.library;
142 _name = seed.displayName;
143 if (seed is MethodElement) {
144 _kinds = METHOD_KINDS;
145 } else if (seed is PropertyAccessorElement) {
146 _kinds = seed.isGetter ? GETTER_KINDS : SETTER_KINDS;
147 } else {
148 _kinds = FIELD_KINDS;
149 }
150 }
151
152 /**
153 * Add the [OverriddenElements] for this element.
154 */
155 OverriddenElements find() {
156 _visited.clear();
157 _addSuperOverrides(_class.supertype);
158 _visited.clear();
159 _addInterfaceOverrides(_class.type, false);
160 _superElements.forEach(_interfaceElements.remove);
161 return new OverriddenElements(_seed, _superElements, _interfaceElements);
162 }
163
164 void _addInterfaceOverrides(InterfaceType type, bool checkType) {
165 if (type == null) {
166 return;
167 }
168 if (!_visited.add(type)) {
169 return;
170 }
171 // this type
172 if (checkType) {
173 Element element = _lookupMember(type.element);
174 if (element != null && !_interfaceElements.contains(element)) {
175 _interfaceElements.add(element);
113 } 176 }
114 } 177 }
115 // interfaces 178 // interfaces
116 Set<engine.Element> interfaceEngineElements = new Set<engine.Element>(); 179 for (InterfaceType interfaceType in type.interfaces) {
117 _addInterfaceOverrides(interfaceEngineElements, currentClass.type, false, 180 _addInterfaceOverrides(interfaceType, true);
118 new Set<engine.InterfaceType>());
119 interfaceEngineElements.remove(superEngineElement);
120 // is there any override?
121 if (superEngineElement != null || interfaceEngineElements.isNotEmpty) {
122 OverriddenMember superMember = superEngineElement != null
123 ? newOverriddenMember_fromEngine(superEngineElement)
124 : null;
125 List<OverriddenMember> interfaceMembers = interfaceEngineElements
126 .map((member) => newOverriddenMember_fromEngine(member))
127 .toList();
128 overrides.add(new Override(node.offset, node.length,
129 superclassMember: superMember,
130 interfaceMembers: nullIfEmpty(interfaceMembers)));
131 } 181 }
182 // super
183 _addInterfaceOverrides(type.superclass, checkType);
132 } 184 }
133 185
134 void _addInterfaceOverrides( 186 void _addSuperOverrides(InterfaceType type) {
135 Set<engine.Element> elements,
136 engine.InterfaceType type,
137 bool checkType,
138 Set<engine.InterfaceType> visited) {
139 if (type == null) { 187 if (type == null) {
140 return; 188 return;
141 } 189 }
142 if (!visited.add(type)) { 190 if (!_visited.add(type)) {
143 return; 191 return;
144 } 192 }
145 // check type 193 // this type
146 if (checkType) { 194 Element element = _lookupMember(type.element);
147 engine.Element element = _lookupMember(type.element); 195 if (element != null && !_superElements.contains(element)) {
148 if (element != null) { 196 _superElements.add(element);
149 elements.add(element);
150 return;
151 }
152 } 197 }
153 // check interfaces 198 // super
154 for (engine.InterfaceType interfaceType in type.interfaces) { 199 _addSuperOverrides(type.superclass);
155 _addInterfaceOverrides(elements, interfaceType, true, visited);
156 }
157 // check super
158 _addInterfaceOverrides(elements, type.superclass, checkType, visited);
159 } 200 }
160 201
161 engine.Element _lookupMember(engine.ClassElement classElement) { 202 Element _lookupMember(ClassElement classElement) {
162 if (classElement == null) { 203 if (classElement == null) {
163 return null; 204 return null;
164 } 205 }
165 engine.Element member; 206 Element member;
166 // method 207 // method
167 if (kinds.contains(ElementKind.METHOD)) { 208 if (_kinds.contains(ElementKind.METHOD)) {
168 member = classElement.lookUpMethod(name, currentLibrary); 209 member = classElement.lookUpMethod(_name, _library);
169 if (member != null) { 210 if (member != null) {
170 return member; 211 return member;
171 } 212 }
172 } 213 }
173 // getter 214 // getter
174 if (kinds.contains(ElementKind.GETTER)) { 215 if (_kinds.contains(ElementKind.GETTER)) {
175 member = classElement.lookUpGetter(name, currentLibrary); 216 member = classElement.lookUpGetter(_name, _library);
176 if (member != null) { 217 if (member != null) {
177 return member; 218 return member;
178 } 219 }
179 } 220 }
180 // setter 221 // setter
181 if (kinds.contains(ElementKind.SETTER)) { 222 if (_kinds.contains(ElementKind.SETTER)) {
182 member = classElement.lookUpSetter(name + '=', currentLibrary); 223 member = classElement.lookUpSetter(_name + '=', _library);
183 if (member != null) { 224 if (member != null) {
184 return member; 225 return member;
185 } 226 }
186 } 227 }
187 // not found 228 // not found
188 return null; 229 return null;
189 } 230 }
190 } 231 }
OLDNEW
« no previous file with comments | « pkg/analysis_server/lib/src/computer/computer_hover.dart ('k') | pkg/analysis_server/test/analysis/get_hover_test.dart » ('j') | no next file with comments »

Powered by Google App Engine
This is Rietveld 408576698