OLD | NEW |
1 // Copyright (c) 2015, the Dart project authors. Please see the AUTHORS file | 1 // Copyright (c) 2015, 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 /// Common AST helpers. | 5 /// Common AST helpers. |
6 library linter.src.ast; | 6 library linter.src.ast; |
7 | 7 |
8 import 'package:analyzer/src/generated/ast.dart' | 8 import 'package:analyzer/src/generated/ast.dart' |
9 show | 9 show |
10 AssignmentExpression, | 10 AssignmentExpression, |
(...skipping 13 matching lines...) Expand all Loading... |
24 FieldDeclaration, | 24 FieldDeclaration, |
25 FunctionDeclaration, | 25 FunctionDeclaration, |
26 FunctionTypeAlias, | 26 FunctionTypeAlias, |
27 MethodDeclaration, | 27 MethodDeclaration, |
28 ReturnStatement, | 28 ReturnStatement, |
29 SimpleIdentifier, | 29 SimpleIdentifier, |
30 TopLevelVariableDeclaration, | 30 TopLevelVariableDeclaration, |
31 TypeParameter, | 31 TypeParameter, |
32 VariableDeclaration; | 32 VariableDeclaration; |
33 import 'package:analyzer/src/generated/element.dart' | 33 import 'package:analyzer/src/generated/element.dart' |
34 show Element, ParameterElement, PropertyAccessorElement; | 34 show |
| 35 Element, |
| 36 GeneralizingElementVisitor, |
| 37 ParameterElement, |
| 38 PropertyAccessorElement; |
35 import 'package:analyzer/src/generated/scanner.dart' | 39 import 'package:analyzer/src/generated/scanner.dart' |
36 show Keyword, KeywordToken, KeywordTokenWithComment, Token; | 40 show Keyword, KeywordToken, KeywordTokenWithComment, Token; |
37 import 'package:linter/src/util.dart'; | 41 import 'package:linter/src/util.dart'; |
38 | 42 |
| 43 /// Returns direct children of [parent]. |
| 44 List<Element> getChildren(Element parent, [String name]) { |
| 45 List<Element> children = <Element>[]; |
| 46 visitChildren(parent, (Element element) { |
| 47 if (name == null || element.displayName == name) { |
| 48 children.add(element); |
| 49 } |
| 50 }); |
| 51 return children; |
| 52 } |
| 53 |
39 /// Returns the most specific AST node appropriate for associating errors. | 54 /// Returns the most specific AST node appropriate for associating errors. |
40 AstNode getNodeToAnnotate(Declaration node) { | 55 AstNode getNodeToAnnotate(Declaration node) { |
41 AstNode mostSpecific = _getNodeToAnnotate(node); | 56 AstNode mostSpecific = _getNodeToAnnotate(node); |
42 if (mostSpecific != null) { | 57 return mostSpecific ?? node; |
43 return mostSpecific; | |
44 } | |
45 return node; | |
46 } | 58 } |
47 | 59 |
48 /// Returns `true` if the keyword associated with this token is `final` or | 60 /// Returns `true` if the keyword associated with this token is `final` or |
49 /// `const`. | 61 /// `const`. |
50 bool isFinalOrConst(Token token) => | 62 bool isFinalOrConst(Token token) => |
51 isKeyword(token, Keyword.FINAL) || isKeyword(token, Keyword.CONST); | 63 isKeyword(token, Keyword.FINAL) || isKeyword(token, Keyword.CONST); |
52 | 64 |
53 /// Returns `true` if the keyword associated with the given [token] matches | 65 /// Returns `true` if the keyword associated with the given [token] matches |
54 /// [keyword]. | 66 /// [keyword]. |
55 bool isKeyword(Token token, Keyword keyword) => | 67 bool isKeyword(Token token, Keyword keyword) => |
(...skipping 68 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
124 | 136 |
125 return false; | 137 return false; |
126 } | 138 } |
127 | 139 |
128 /// Returns `true` if the given [id] is a valid Dart identifier. | 140 /// Returns `true` if the given [id] is a valid Dart identifier. |
129 bool isValidDartIdentifier(String id) => !isKeyWord(id) && isIdentifier(id); | 141 bool isValidDartIdentifier(String id) => !isKeyWord(id) && isIdentifier(id); |
130 | 142 |
131 /// Returns `true` if the keyword associated with this token is `var`. | 143 /// Returns `true` if the keyword associated with this token is `var`. |
132 bool isVar(Token token) => isKeyword(token, Keyword.VAR); | 144 bool isVar(Token token) => isKeyword(token, Keyword.VAR); |
133 | 145 |
| 146 /// Uses [processor] to visit all of the children of [element]. |
| 147 /// If [processor] returns `true`, then children of a child are visited too. |
| 148 void visitChildren(Element element, ElementProcessor processor) { |
| 149 element.visitChildren(new _ElementVisitorAdapter(processor)); |
| 150 } |
| 151 |
134 bool _checkForSimpleGetter(MethodDeclaration getter, Expression expression) { | 152 bool _checkForSimpleGetter(MethodDeclaration getter, Expression expression) { |
135 if (expression is SimpleIdentifier) { | 153 if (expression is SimpleIdentifier) { |
136 var staticElement = expression.staticElement; | 154 var staticElement = expression.staticElement; |
137 if (staticElement is PropertyAccessorElement) { | 155 if (staticElement is PropertyAccessorElement) { |
138 Element getterElement = getter.element; | 156 Element getterElement = getter.element; |
139 // Skipping library level getters, test that the enclosing element is | 157 // Skipping library level getters, test that the enclosing element is |
140 // the same | 158 // the same |
141 if (staticElement.enclosingElement != null && | 159 if (staticElement.enclosingElement != null && |
142 (staticElement.enclosingElement == getterElement.enclosingElement)) { | 160 (staticElement.enclosingElement == getterElement.enclosingElement)) { |
143 return staticElement.isSynthetic && staticElement.variable.isPrivate; | 161 return staticElement.isSynthetic && staticElement.variable.isPrivate; |
(...skipping 73 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
217 return node.name; | 235 return node.name; |
218 } | 236 } |
219 if (node is TypeParameter) { | 237 if (node is TypeParameter) { |
220 return node.name; | 238 return node.name; |
221 } | 239 } |
222 if (node is VariableDeclaration) { | 240 if (node is VariableDeclaration) { |
223 return node.name; | 241 return node.name; |
224 } | 242 } |
225 return null; | 243 return null; |
226 } | 244 } |
| 245 |
| 246 /// An [Element] processor function type. |
| 247 /// If `true` is returned, children of [element] will be visited. |
| 248 typedef bool ElementProcessor(Element element); |
| 249 |
| 250 /// A [GeneralizingElementVisitor] adapter for [ElementProcessor]. |
| 251 class _ElementVisitorAdapter extends GeneralizingElementVisitor { |
| 252 final ElementProcessor processor; |
| 253 _ElementVisitorAdapter(this.processor); |
| 254 |
| 255 @override |
| 256 void visitElement(Element element) { |
| 257 bool visitChildren = processor(element); |
| 258 if (visitChildren == true) { |
| 259 element.visitChildren(this); |
| 260 } |
| 261 } |
| 262 } |
OLD | NEW |