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

Side by Side Diff: pkg/analyzer/lib/src/dart/analysis/referenced_names.dart

Issue 2519443003: Compute names referenced in a unit. (Closed)
Patch Set: Created 4 years, 1 month 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
(Empty)
1 // Copyright (c) 2016, the Dart project authors. Please see the AUTHORS file
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.
4
5 import 'package:analyzer/dart/ast/ast.dart';
6 import 'package:analyzer/dart/ast/visitor.dart';
7
8 /**
9 * Compute the set of external names referenced in the [unit].
10 */
11 Set<String> computeReferencedNames(CompilationUnit unit) {
12 _ReferencedNamesComputer computer = new _ReferencedNamesComputer();
13 unit.accept(computer);
14 return computer.names;
15 }
16
17 class _LocalNameScope {
Brian Wilkerson 2016/11/18 17:55:51 Consider renaming (and documenting) the class. It
scheglov 2016/11/18 18:33:44 I've added a comment.
18 final _LocalNameScope enclosing;
19 Set<String> names;
20
21 _LocalNameScope(this.enclosing);
22
23 factory _LocalNameScope.forBlock(_LocalNameScope enclosing, Block node) {
24 _LocalNameScope scope = new _LocalNameScope(enclosing);
25 for (Statement statement in node.statements) {
26 if (statement is FunctionDeclarationStatement) {
27 scope.add(statement.functionDeclaration.name.name);
28 } else if (statement is VariableDeclarationStatement) {
29 for (VariableDeclaration variable in statement.variables.variables) {
30 scope.add(variable.name.name);
31 }
32 }
33 }
34 return scope;
35 }
36
37 factory _LocalNameScope.forClass(
38 _LocalNameScope enclosing, ClassDeclaration node) {
39 _LocalNameScope scope = new _LocalNameScope(enclosing);
40 scope.addTypeParameters(node.typeParameters);
41 for (ClassMember member in node.members) {
42 if (member is FieldDeclaration) {
43 for (VariableDeclaration variable in member.fields.variables) {
44 scope.add(variable.name.name);
45 }
46 } else if (member is MethodDeclaration) {
47 scope.add(member.name.name);
48 }
49 }
50 return scope;
51 }
52
53 factory _LocalNameScope.forClassTypeAlias(
54 _LocalNameScope enclosing, ClassTypeAlias node) {
55 _LocalNameScope scope = new _LocalNameScope(enclosing);
56 scope.addTypeParameters(node.typeParameters);
57 return scope;
58 }
59
60 factory _LocalNameScope.forFunction(
61 _LocalNameScope enclosing, FunctionDeclaration node) {
62 _LocalNameScope scope = new _LocalNameScope(enclosing);
63 scope.addTypeParameters(node.functionExpression.typeParameters);
64 scope.addFormalParameters(node.functionExpression.parameters);
65 return scope;
66 }
67
68 factory _LocalNameScope.forFunctionTypeAlias(
69 _LocalNameScope enclosing, FunctionTypeAlias node) {
70 _LocalNameScope scope = new _LocalNameScope(enclosing);
71 scope.addTypeParameters(node.typeParameters);
72 return scope;
73 }
74
75 factory _LocalNameScope.forMethod(
76 _LocalNameScope enclosing, MethodDeclaration node) {
77 _LocalNameScope scope = new _LocalNameScope(enclosing);
78 scope.addTypeParameters(node.typeParameters);
79 scope.addFormalParameters(node.parameters);
80 return scope;
81 }
82
83 void add(String name) {
84 names ??= new Set<String>();
85 names.add(name);
86 }
87
88 void addFormalParameters(FormalParameterList parameterList) {
89 if (parameterList != null) {
90 parameterList.parameters
91 .map((p) => p is NormalFormalParameter ? p.identifier.name : '')
92 .forEach(add);
93 }
94 }
95
96 void addTypeParameters(TypeParameterList typeParameterList) {
97 if (typeParameterList != null) {
98 typeParameterList.typeParameters.map((p) => p.name.name).forEach(add);
99 }
100 }
101
102 bool contains(String name) {
103 if (names != null && names.contains(name)) {
104 return true;
105 }
106 if (enclosing != null) {
107 return enclosing.contains(name);
108 }
109 return false;
110 }
111 }
112
113 class _ReferencedNamesComputer extends GeneralizingAstVisitor {
114 final Set<String> names = new Set<String>();
115 final Set<String> importPrefixNames = new Set<String>();
116
117 _LocalNameScope localScope = new _LocalNameScope(null);
118 int localLevel = 0;
119
120 @override
121 visitBlock(Block node) {
122 _LocalNameScope outerScope = localScope;
123 try {
124 localScope = new _LocalNameScope.forBlock(localScope, node);
125 super.visitBlock(node);
126 } finally {
127 localScope = outerScope;
128 }
129 }
130
131 @override
132 visitClassDeclaration(ClassDeclaration node) {
133 _LocalNameScope outerScope = localScope;
134 try {
135 localScope = new _LocalNameScope.forClass(localScope, node);
136 super.visitClassDeclaration(node);
137 } finally {
138 localScope = outerScope;
139 }
140 }
141
142 @override
143 visitClassTypeAlias(ClassTypeAlias node) {
144 _LocalNameScope outerScope = localScope;
145 try {
146 localScope = new _LocalNameScope.forClassTypeAlias(localScope, node);
147 super.visitClassTypeAlias(node);
148 } finally {
149 localScope = outerScope;
150 }
151 }
152
153 @override
154 visitComment(Comment node) {
155 try {
156 localLevel++;
157 super.visitComment(node);
158 } finally {
159 localLevel--;
160 }
161 }
162
163 @override
164 visitConstructorName(ConstructorName node) {
165 if (node.parent is! ConstructorDeclaration) {
166 super.visitConstructorName(node);
167 }
168 }
169
170 @override
171 visitFunctionBody(FunctionBody node) {
172 try {
173 localLevel++;
174 super.visitFunctionBody(node);
175 } finally {
176 localLevel--;
177 }
178 }
179
180 @override
181 visitFunctionDeclaration(FunctionDeclaration node) {
182 if (localLevel == 0) {
Paul Berry 2016/11/18 17:59:59 Why do we skip this logic for local functions? It
scheglov 2016/11/18 18:33:44 Acknowledged. You're right. I've added the corresp
183 _LocalNameScope outerScope = localScope;
184 try {
185 localScope = new _LocalNameScope.forFunction(localScope, node);
186 super.visitFunctionDeclaration(node);
187 } finally {
188 localScope = outerScope;
189 }
190 } else {
191 super.visitFunctionDeclaration(node);
192 }
193 }
194
195 @override
196 visitFunctionTypeAlias(FunctionTypeAlias node) {
197 if (localLevel == 0) {
Paul Berry 2016/11/18 17:59:59 Why is this necessary? I thought function type al
scheglov 2016/11/18 18:33:44 Acknowledged.
198 _LocalNameScope outerScope = localScope;
199 try {
200 localScope = new _LocalNameScope.forFunctionTypeAlias(localScope, node);
201 super.visitFunctionTypeAlias(node);
202 } finally {
203 localScope = outerScope;
204 }
205 } else {
206 super.visitFunctionTypeAlias(node);
207 }
208 }
209
210 @override
211 visitImportDirective(ImportDirective node) {
212 if (node.prefix != null) {
213 importPrefixNames.add(node.prefix.name);
214 }
215 super.visitImportDirective(node);
216 }
217
218 @override
219 visitMethodDeclaration(MethodDeclaration node) {
220 _LocalNameScope outerScope = localScope;
221 try {
222 localScope = new _LocalNameScope.forMethod(localScope, node);
223 super.visitMethodDeclaration(node);
224 } finally {
225 localScope = outerScope;
226 }
227 }
228
229 @override
230 visitSimpleIdentifier(SimpleIdentifier node) {
231 // Ignore all declarations.
232 if (node.inDeclarationContext()) {
233 return;
234 }
235 // Ignore class names references from constructors.
236 AstNode parent = node.parent;
237 if (parent is ConstructorDeclaration && parent.returnType == node) {
238 return;
239 }
240 // Prepare name.
241 String name = node.name;
242 // Ignore unqualified names shadowed by local elements.
243 if (!node.isQualified) {
244 if (localScope.contains(name)) {
245 return;
Paul Berry 2016/11/18 17:59:59 What happens if the code looks like this? void f(
scheglov 2016/11/18 18:33:44 Actually this works. Local declarations hide only
Paul Berry 2016/11/18 19:15:44 Ah, ok. I mistakenly thought that "isQualified" j
246 }
247 if (importPrefixNames.contains(name)) {
248 return;
249 }
250 }
251 // Do add the name.
252 names.add(name);
253 }
254 }
OLDNEW

Powered by Google App Engine
This is Rietveld 408576698