OLD | NEW |
(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 /** |
| 18 * Chained set of local names, that hide corresponding external names. |
| 19 */ |
| 20 class _LocalNameScope { |
| 21 final _LocalNameScope enclosing; |
| 22 Set<String> names; |
| 23 |
| 24 _LocalNameScope(this.enclosing); |
| 25 |
| 26 factory _LocalNameScope.forBlock(_LocalNameScope enclosing, Block node) { |
| 27 _LocalNameScope scope = new _LocalNameScope(enclosing); |
| 28 for (Statement statement in node.statements) { |
| 29 if (statement is FunctionDeclarationStatement) { |
| 30 scope.add(statement.functionDeclaration.name); |
| 31 } else if (statement is VariableDeclarationStatement) { |
| 32 scope.addVariableNames(statement.variables); |
| 33 } |
| 34 } |
| 35 return scope; |
| 36 } |
| 37 |
| 38 factory _LocalNameScope.forClass( |
| 39 _LocalNameScope enclosing, ClassDeclaration node) { |
| 40 _LocalNameScope scope = new _LocalNameScope(enclosing); |
| 41 scope.addTypeParameters(node.typeParameters); |
| 42 for (ClassMember member in node.members) { |
| 43 if (member is FieldDeclaration) { |
| 44 scope.addVariableNames(member.fields); |
| 45 } else if (member is MethodDeclaration) { |
| 46 scope.add(member.name); |
| 47 } |
| 48 } |
| 49 return scope; |
| 50 } |
| 51 |
| 52 factory _LocalNameScope.forClassTypeAlias( |
| 53 _LocalNameScope enclosing, ClassTypeAlias node) { |
| 54 _LocalNameScope scope = new _LocalNameScope(enclosing); |
| 55 scope.addTypeParameters(node.typeParameters); |
| 56 return scope; |
| 57 } |
| 58 |
| 59 factory _LocalNameScope.forFunction( |
| 60 _LocalNameScope enclosing, FunctionDeclaration node) { |
| 61 _LocalNameScope scope = new _LocalNameScope(enclosing); |
| 62 scope.addTypeParameters(node.functionExpression.typeParameters); |
| 63 scope.addFormalParameters(node.functionExpression.parameters); |
| 64 return scope; |
| 65 } |
| 66 |
| 67 factory _LocalNameScope.forFunctionTypeAlias( |
| 68 _LocalNameScope enclosing, FunctionTypeAlias node) { |
| 69 _LocalNameScope scope = new _LocalNameScope(enclosing); |
| 70 scope.addTypeParameters(node.typeParameters); |
| 71 return scope; |
| 72 } |
| 73 |
| 74 factory _LocalNameScope.forMethod( |
| 75 _LocalNameScope enclosing, MethodDeclaration node) { |
| 76 _LocalNameScope scope = new _LocalNameScope(enclosing); |
| 77 scope.addTypeParameters(node.typeParameters); |
| 78 scope.addFormalParameters(node.parameters); |
| 79 return scope; |
| 80 } |
| 81 |
| 82 factory _LocalNameScope.forUnit(CompilationUnit node) { |
| 83 _LocalNameScope scope = new _LocalNameScope(null); |
| 84 for (CompilationUnitMember declaration in node.declarations) { |
| 85 if (declaration is NamedCompilationUnitMember) { |
| 86 scope.add(declaration.name); |
| 87 } else if (declaration is TopLevelVariableDeclaration) { |
| 88 scope.addVariableNames(declaration.variables); |
| 89 } |
| 90 } |
| 91 return scope; |
| 92 } |
| 93 |
| 94 void add(SimpleIdentifier identifier) { |
| 95 if (identifier != null) { |
| 96 names ??= new Set<String>(); |
| 97 names.add(identifier.name); |
| 98 } |
| 99 } |
| 100 |
| 101 void addFormalParameters(FormalParameterList parameterList) { |
| 102 if (parameterList != null) { |
| 103 parameterList.parameters |
| 104 .map((p) => p is NormalFormalParameter ? p.identifier : null) |
| 105 .forEach(add); |
| 106 } |
| 107 } |
| 108 |
| 109 void addTypeParameters(TypeParameterList typeParameterList) { |
| 110 if (typeParameterList != null) { |
| 111 typeParameterList.typeParameters.map((p) => p.name).forEach(add); |
| 112 } |
| 113 } |
| 114 |
| 115 void addVariableNames(VariableDeclarationList variableList) { |
| 116 for (VariableDeclaration variable in variableList.variables) { |
| 117 add(variable.name); |
| 118 } |
| 119 } |
| 120 |
| 121 bool contains(String name) { |
| 122 if (names != null && names.contains(name)) { |
| 123 return true; |
| 124 } |
| 125 if (enclosing != null) { |
| 126 return enclosing.contains(name); |
| 127 } |
| 128 return false; |
| 129 } |
| 130 } |
| 131 |
| 132 class _ReferencedNamesComputer extends GeneralizingAstVisitor { |
| 133 final Set<String> names = new Set<String>(); |
| 134 final Set<String> importPrefixNames = new Set<String>(); |
| 135 |
| 136 _LocalNameScope localScope = new _LocalNameScope(null); |
| 137 |
| 138 @override |
| 139 visitBlock(Block node) { |
| 140 _LocalNameScope outerScope = localScope; |
| 141 try { |
| 142 localScope = new _LocalNameScope.forBlock(localScope, node); |
| 143 super.visitBlock(node); |
| 144 } finally { |
| 145 localScope = outerScope; |
| 146 } |
| 147 } |
| 148 |
| 149 @override |
| 150 visitClassDeclaration(ClassDeclaration node) { |
| 151 _LocalNameScope outerScope = localScope; |
| 152 try { |
| 153 localScope = new _LocalNameScope.forClass(localScope, node); |
| 154 super.visitClassDeclaration(node); |
| 155 } finally { |
| 156 localScope = outerScope; |
| 157 } |
| 158 } |
| 159 |
| 160 @override |
| 161 visitClassTypeAlias(ClassTypeAlias node) { |
| 162 _LocalNameScope outerScope = localScope; |
| 163 try { |
| 164 localScope = new _LocalNameScope.forClassTypeAlias(localScope, node); |
| 165 super.visitClassTypeAlias(node); |
| 166 } finally { |
| 167 localScope = outerScope; |
| 168 } |
| 169 } |
| 170 |
| 171 @override |
| 172 visitCompilationUnit(CompilationUnit node) { |
| 173 localScope = new _LocalNameScope.forUnit(node); |
| 174 super.visitCompilationUnit(node); |
| 175 } |
| 176 |
| 177 @override |
| 178 visitConstructorName(ConstructorName node) { |
| 179 if (node.parent is! ConstructorDeclaration) { |
| 180 super.visitConstructorName(node); |
| 181 } |
| 182 } |
| 183 |
| 184 @override |
| 185 visitFunctionDeclaration(FunctionDeclaration node) { |
| 186 _LocalNameScope outerScope = localScope; |
| 187 try { |
| 188 localScope = new _LocalNameScope.forFunction(localScope, node); |
| 189 super.visitFunctionDeclaration(node); |
| 190 } finally { |
| 191 localScope = outerScope; |
| 192 } |
| 193 } |
| 194 |
| 195 @override |
| 196 visitFunctionTypeAlias(FunctionTypeAlias node) { |
| 197 _LocalNameScope outerScope = localScope; |
| 198 try { |
| 199 localScope = new _LocalNameScope.forFunctionTypeAlias(localScope, node); |
| 200 super.visitFunctionTypeAlias(node); |
| 201 } finally { |
| 202 localScope = outerScope; |
| 203 } |
| 204 } |
| 205 |
| 206 @override |
| 207 visitImportDirective(ImportDirective node) { |
| 208 if (node.prefix != null) { |
| 209 importPrefixNames.add(node.prefix.name); |
| 210 } |
| 211 super.visitImportDirective(node); |
| 212 } |
| 213 |
| 214 @override |
| 215 visitMethodDeclaration(MethodDeclaration node) { |
| 216 _LocalNameScope outerScope = localScope; |
| 217 try { |
| 218 localScope = new _LocalNameScope.forMethod(localScope, node); |
| 219 super.visitMethodDeclaration(node); |
| 220 } finally { |
| 221 localScope = outerScope; |
| 222 } |
| 223 } |
| 224 |
| 225 @override |
| 226 visitSimpleIdentifier(SimpleIdentifier node) { |
| 227 // Ignore all declarations. |
| 228 if (node.inDeclarationContext()) { |
| 229 return; |
| 230 } |
| 231 // Ignore class names references from constructors. |
| 232 AstNode parent = node.parent; |
| 233 if (parent is ConstructorDeclaration && parent.returnType == node) { |
| 234 return; |
| 235 } |
| 236 // Prepare name. |
| 237 String name = node.name; |
| 238 // Ignore unqualified names shadowed by local elements. |
| 239 if (!node.isQualified) { |
| 240 if (localScope.contains(name)) { |
| 241 return; |
| 242 } |
| 243 if (importPrefixNames.contains(name)) { |
| 244 return; |
| 245 } |
| 246 } |
| 247 // Do add the name. |
| 248 names.add(name); |
| 249 } |
| 250 } |
OLD | NEW |