| OLD | NEW |
| 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 analyzer.src.generated.resolver; | 5 library analyzer.src.generated.resolver; |
| 6 | 6 |
| 7 import 'dart:collection'; | 7 import 'dart:collection'; |
| 8 | 8 |
| 9 import 'package:analyzer/dart/ast/ast.dart'; | 9 import 'package:analyzer/dart/ast/ast.dart'; |
| 10 import 'package:analyzer/dart/ast/visitor.dart'; | 10 import 'package:analyzer/dart/ast/visitor.dart'; |
| (...skipping 2012 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 2023 * @param node the node to be visited | 2023 * @param node the node to be visited |
| 2024 */ | 2024 */ |
| 2025 void _safelyVisit(AstNode node) { | 2025 void _safelyVisit(AstNode node) { |
| 2026 if (node != null) { | 2026 if (node != null) { |
| 2027 node.accept(this); | 2027 node.accept(this); |
| 2028 } | 2028 } |
| 2029 } | 2029 } |
| 2030 } | 2030 } |
| 2031 | 2031 |
| 2032 /** | 2032 /** |
| 2033 * Instances of the class `DeclarationResolver` are used to resolve declarations
in an AST | 2033 * A visitor that resolves declarations in an AST structure to already built |
| 2034 * structure to already built elements. | 2034 * elements. |
| 2035 */ | 2035 */ |
| 2036 class DeclarationResolver extends RecursiveAstVisitor<Object> { | 2036 class DeclarationResolver extends RecursiveAstVisitor<Object> { |
| 2037 /** | 2037 /** |
| 2038 * The compilation unit containing the AST nodes being visited. | 2038 * The compilation unit containing the AST nodes being visited. |
| 2039 */ | 2039 */ |
| 2040 CompilationUnitElement _enclosingUnit; | 2040 CompilationUnitElement _enclosingUnit; |
| 2041 | 2041 |
| 2042 /** | 2042 /** |
| 2043 * The function type alias containing the AST nodes being visited, or `null` i
f we are not | 2043 * The function type alias containing the AST nodes being visited, or `null` |
| 2044 * in the scope of a function type alias. | 2044 * if we are not in the scope of a function type alias. |
| 2045 */ | 2045 */ |
| 2046 FunctionTypeAliasElement _enclosingAlias; | 2046 FunctionTypeAliasElement _enclosingAlias; |
| 2047 | 2047 |
| 2048 /** | 2048 /** |
| 2049 * The class containing the AST nodes being visited, or `null` if we are not i
n the scope of | 2049 * The class containing the AST nodes being visited, or `null` if we are not |
| 2050 * a class. | 2050 * in the scope of a class. |
| 2051 */ | 2051 */ |
| 2052 ClassElement _enclosingClass; | 2052 ClassElement _enclosingClass; |
| 2053 | 2053 |
| 2054 /** | 2054 /** |
| 2055 * The method or function containing the AST nodes being visited, or `null` if
we are not in | 2055 * The method or function containing the AST nodes being visited, or `null` if |
| 2056 * the scope of a method or function. | 2056 * we are not in the scope of a method or function. |
| 2057 */ | 2057 */ |
| 2058 ExecutableElement _enclosingExecutable; | 2058 ExecutableElement _enclosingExecutable; |
| 2059 | 2059 |
| 2060 /** | 2060 /** |
| 2061 * The parameter containing the AST nodes being visited, or `null` if we are n
ot in the | 2061 * The parameter containing the AST nodes being visited, or `null` if we are |
| 2062 * scope of a parameter. | 2062 * not in the scope of a parameter. |
| 2063 */ | 2063 */ |
| 2064 ParameterElement _enclosingParameter; | 2064 ParameterElement _enclosingParameter; |
| 2065 | 2065 |
| 2066 /** | 2066 /** |
| 2067 * Resolve the declarations within the given compilation unit to the elements
rooted at the given | 2067 * Resolve the declarations within the given compilation [unit] to the |
| 2068 * element. | 2068 * elements rooted at the given [element]. Throw an [ElementMismatchException] |
| 2069 * | 2069 * if the element model and compilation unit do not match each other. |
| 2070 * @param unit the compilation unit to be resolved | |
| 2071 * @param element the root of the element model used to resolve the AST nodes | |
| 2072 */ | 2070 */ |
| 2073 void resolve(CompilationUnit unit, CompilationUnitElement element) { | 2071 void resolve(CompilationUnit unit, CompilationUnitElement element) { |
| 2074 _enclosingUnit = element; | 2072 _enclosingUnit = element; |
| 2075 unit.element = element; | 2073 unit.element = element; |
| 2076 unit.accept(this); | 2074 unit.accept(this); |
| 2077 } | 2075 } |
| 2078 | 2076 |
| 2079 @override | 2077 @override |
| 2080 Object visitCatchClause(CatchClause node) { | 2078 Object visitCatchClause(CatchClause node) { |
| 2081 SimpleIdentifier exceptionParameter = node.exceptionParameter; | 2079 SimpleIdentifier exceptionParameter = node.exceptionParameter; |
| (...skipping 33 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 2115 } | 2113 } |
| 2116 } | 2114 } |
| 2117 | 2115 |
| 2118 @override | 2116 @override |
| 2119 Object visitConstructorDeclaration(ConstructorDeclaration node) { | 2117 Object visitConstructorDeclaration(ConstructorDeclaration node) { |
| 2120 ExecutableElement outerExecutable = _enclosingExecutable; | 2118 ExecutableElement outerExecutable = _enclosingExecutable; |
| 2121 try { | 2119 try { |
| 2122 SimpleIdentifier constructorName = node.name; | 2120 SimpleIdentifier constructorName = node.name; |
| 2123 if (constructorName == null) { | 2121 if (constructorName == null) { |
| 2124 _enclosingExecutable = _enclosingClass.unnamedConstructor; | 2122 _enclosingExecutable = _enclosingClass.unnamedConstructor; |
| 2123 if (_enclosingExecutable == null) { |
| 2124 _mismatch('Could not find default constructor', node); |
| 2125 } |
| 2125 } else { | 2126 } else { |
| 2126 _enclosingExecutable = | 2127 _enclosingExecutable = |
| 2127 _enclosingClass.getNamedConstructor(constructorName.name); | 2128 _enclosingClass.getNamedConstructor(constructorName.name); |
| 2129 if (_enclosingExecutable == null) { |
| 2130 _mismatch( |
| 2131 'Could not find constructor element with name "${constructorName.n
ame}', |
| 2132 node); |
| 2133 } |
| 2128 constructorName.staticElement = _enclosingExecutable; | 2134 constructorName.staticElement = _enclosingExecutable; |
| 2129 } | 2135 } |
| 2130 node.element = _enclosingExecutable as ConstructorElement; | 2136 node.element = _enclosingExecutable as ConstructorElement; |
| 2131 return super.visitConstructorDeclaration(node); | 2137 return super.visitConstructorDeclaration(node); |
| 2132 } finally { | 2138 } finally { |
| 2133 _enclosingExecutable = outerExecutable; | 2139 _enclosingExecutable = outerExecutable; |
| 2134 } | 2140 } |
| 2135 } | 2141 } |
| 2136 | 2142 |
| 2137 @override | 2143 @override |
| 2138 Object visitDeclaredIdentifier(DeclaredIdentifier node) { | 2144 Object visitDeclaredIdentifier(DeclaredIdentifier node) { |
| 2139 SimpleIdentifier variableName = node.identifier; | 2145 SimpleIdentifier variableName = node.identifier; |
| 2140 _findIdentifier(_enclosingExecutable.localVariables, variableName); | 2146 _findIdentifier(_enclosingExecutable.localVariables, variableName); |
| 2141 return super.visitDeclaredIdentifier(node); | 2147 return super.visitDeclaredIdentifier(node); |
| 2142 } | 2148 } |
| 2143 | 2149 |
| 2144 @override | 2150 @override |
| 2145 Object visitDefaultFormalParameter(DefaultFormalParameter node) { | 2151 Object visitDefaultFormalParameter(DefaultFormalParameter node) { |
| 2146 SimpleIdentifier parameterName = node.parameter.identifier; | 2152 SimpleIdentifier parameterName = node.parameter.identifier; |
| 2147 ParameterElement element = _getElementForParameter(node, parameterName); | 2153 ParameterElement element = _getElementForParameter(node, parameterName); |
| 2148 Expression defaultValue = node.defaultValue; | 2154 Expression defaultValue = node.defaultValue; |
| 2149 if (defaultValue != null) { | 2155 if (defaultValue != null) { |
| 2150 ExecutableElement outerExecutable = _enclosingExecutable; | 2156 ExecutableElement outerExecutable = _enclosingExecutable; |
| 2151 try { | 2157 try { |
| 2152 if (element == null) { | 2158 _enclosingExecutable = element.initializer; |
| 2153 // TODO(brianwilkerson) Report this internal error. | |
| 2154 } else { | |
| 2155 _enclosingExecutable = element.initializer; | |
| 2156 } | |
| 2157 defaultValue.accept(this); | 2159 defaultValue.accept(this); |
| 2158 } finally { | 2160 } finally { |
| 2159 _enclosingExecutable = outerExecutable; | 2161 _enclosingExecutable = outerExecutable; |
| 2160 } | 2162 } |
| 2161 } | 2163 } |
| 2162 ParameterElement outerParameter = _enclosingParameter; | 2164 ParameterElement outerParameter = _enclosingParameter; |
| 2163 try { | 2165 try { |
| 2164 _enclosingParameter = element; | 2166 _enclosingParameter = element; |
| 2165 return super.visitDefaultFormalParameter(node); | 2167 return super.visitDefaultFormalParameter(node); |
| 2166 } finally { | 2168 } finally { |
| (...skipping 11 matching lines...) Expand all Loading... |
| 2178 } | 2180 } |
| 2179 return super.visitEnumDeclaration(node); | 2181 return super.visitEnumDeclaration(node); |
| 2180 } | 2182 } |
| 2181 | 2183 |
| 2182 @override | 2184 @override |
| 2183 Object visitExportDirective(ExportDirective node) { | 2185 Object visitExportDirective(ExportDirective node) { |
| 2184 String uri = _getStringValue(node.uri); | 2186 String uri = _getStringValue(node.uri); |
| 2185 if (uri != null) { | 2187 if (uri != null) { |
| 2186 LibraryElement library = _enclosingUnit.library; | 2188 LibraryElement library = _enclosingUnit.library; |
| 2187 ExportElement exportElement = _findExport( | 2189 ExportElement exportElement = _findExport( |
| 2190 node, |
| 2188 library.exports, | 2191 library.exports, |
| 2189 _enclosingUnit.context.sourceFactory | 2192 _enclosingUnit.context.sourceFactory |
| 2190 .resolveUri(_enclosingUnit.source, uri)); | 2193 .resolveUri(_enclosingUnit.source, uri)); |
| 2191 node.element = exportElement; | 2194 node.element = exportElement; |
| 2192 } | 2195 } |
| 2193 return super.visitExportDirective(node); | 2196 return super.visitExportDirective(node); |
| 2194 } | 2197 } |
| 2195 | 2198 |
| 2196 @override | 2199 @override |
| 2197 Object visitFieldFormalParameter(FieldFormalParameter node) { | 2200 Object visitFieldFormalParameter(FieldFormalParameter node) { |
| (...skipping 24 matching lines...) Expand all Loading... |
| 2222 _findIdentifier(_enclosingExecutable.functions, functionName); | 2225 _findIdentifier(_enclosingExecutable.functions, functionName); |
| 2223 } else { | 2226 } else { |
| 2224 _enclosingExecutable = | 2227 _enclosingExecutable = |
| 2225 _findIdentifier(_enclosingUnit.functions, functionName); | 2228 _findIdentifier(_enclosingUnit.functions, functionName); |
| 2226 } | 2229 } |
| 2227 } else { | 2230 } else { |
| 2228 if (_enclosingExecutable != null) { | 2231 if (_enclosingExecutable != null) { |
| 2229 _enclosingExecutable = | 2232 _enclosingExecutable = |
| 2230 _findIdentifier(_enclosingExecutable.functions, functionName); | 2233 _findIdentifier(_enclosingExecutable.functions, functionName); |
| 2231 } else { | 2234 } else { |
| 2232 PropertyAccessorElement accessor = | 2235 List<PropertyAccessorElement> accessors; |
| 2233 _findIdentifier(_enclosingUnit.accessors, functionName); | 2236 if (_enclosingClass != null) { |
| 2234 if ((property as KeywordToken).keyword == Keyword.SET) { | 2237 accessors = _enclosingClass.accessors; |
| 2235 accessor = accessor.variable.setter; | 2238 } else { |
| 2239 accessors = _enclosingUnit.accessors; |
| 2240 } |
| 2241 PropertyAccessorElement accessor; |
| 2242 if ((property as KeywordToken).keyword == Keyword.GET) { |
| 2243 accessor = _findIdentifier(accessors, functionName); |
| 2244 } else if ((property as KeywordToken).keyword == Keyword.SET) { |
| 2245 accessor = _findWithNameAndOffset(accessors, functionName, |
| 2246 functionName.name + '=', functionName.offset); |
| 2236 functionName.staticElement = accessor; | 2247 functionName.staticElement = accessor; |
| 2237 } | 2248 } |
| 2238 _enclosingExecutable = accessor; | 2249 _enclosingExecutable = accessor; |
| 2239 } | 2250 } |
| 2240 } | 2251 } |
| 2241 node.functionExpression.element = _enclosingExecutable; | 2252 node.functionExpression.element = _enclosingExecutable; |
| 2242 return super.visitFunctionDeclaration(node); | 2253 return super.visitFunctionDeclaration(node); |
| 2243 } finally { | 2254 } finally { |
| 2244 _enclosingExecutable = outerExecutable; | 2255 _enclosingExecutable = outerExecutable; |
| 2245 } | 2256 } |
| 2246 } | 2257 } |
| 2247 | 2258 |
| 2248 @override | 2259 @override |
| 2249 Object visitFunctionExpression(FunctionExpression node) { | 2260 Object visitFunctionExpression(FunctionExpression node) { |
| 2250 if (node.parent is! FunctionDeclaration) { | 2261 if (node.parent is! FunctionDeclaration) { |
| 2251 FunctionElement element = | 2262 FunctionElement element = _findAtOffset( |
| 2252 _findAtOffset(_enclosingExecutable.functions, node.beginToken.offset); | 2263 _enclosingExecutable.functions, node, node.beginToken.offset); |
| 2253 node.element = element; | 2264 node.element = element; |
| 2254 } | 2265 } |
| 2255 ExecutableElement outerExecutable = _enclosingExecutable; | 2266 ExecutableElement outerExecutable = _enclosingExecutable; |
| 2256 try { | 2267 try { |
| 2257 _enclosingExecutable = node.element; | 2268 _enclosingExecutable = node.element; |
| 2258 return super.visitFunctionExpression(node); | 2269 return super.visitFunctionExpression(node); |
| 2259 } finally { | 2270 } finally { |
| 2260 _enclosingExecutable = outerExecutable; | 2271 _enclosingExecutable = outerExecutable; |
| 2261 } | 2272 } |
| 2262 } | 2273 } |
| (...skipping 27 matching lines...) Expand all Loading... |
| 2290 return super.visitFunctionTypedFormalParameter(node); | 2301 return super.visitFunctionTypedFormalParameter(node); |
| 2291 } | 2302 } |
| 2292 } | 2303 } |
| 2293 | 2304 |
| 2294 @override | 2305 @override |
| 2295 Object visitImportDirective(ImportDirective node) { | 2306 Object visitImportDirective(ImportDirective node) { |
| 2296 String uri = _getStringValue(node.uri); | 2307 String uri = _getStringValue(node.uri); |
| 2297 if (uri != null) { | 2308 if (uri != null) { |
| 2298 LibraryElement library = _enclosingUnit.library; | 2309 LibraryElement library = _enclosingUnit.library; |
| 2299 ImportElement importElement = _findImport( | 2310 ImportElement importElement = _findImport( |
| 2311 node, |
| 2300 library.imports, | 2312 library.imports, |
| 2301 _enclosingUnit.context.sourceFactory | 2313 _enclosingUnit.context.sourceFactory |
| 2302 .resolveUri(_enclosingUnit.source, uri), | 2314 .resolveUri(_enclosingUnit.source, uri)); |
| 2303 node.prefix); | |
| 2304 node.element = importElement; | 2315 node.element = importElement; |
| 2305 } | 2316 } |
| 2306 return super.visitImportDirective(node); | 2317 return super.visitImportDirective(node); |
| 2307 } | 2318 } |
| 2308 | 2319 |
| 2309 @override | 2320 @override |
| 2310 Object visitLabeledStatement(LabeledStatement node) { | 2321 Object visitLabeledStatement(LabeledStatement node) { |
| 2311 for (Label label in node.labels) { | 2322 for (Label label in node.labels) { |
| 2312 SimpleIdentifier labelName = label.label; | 2323 SimpleIdentifier labelName = label.label; |
| 2313 _findIdentifier(_enclosingExecutable.labels, labelName); | 2324 _findIdentifier(_enclosingExecutable.labels, labelName); |
| 2314 } | 2325 } |
| 2315 return super.visitLabeledStatement(node); | 2326 return super.visitLabeledStatement(node); |
| 2316 } | 2327 } |
| 2317 | 2328 |
| 2318 @override | 2329 @override |
| 2319 Object visitLibraryDirective(LibraryDirective node) { | 2330 Object visitLibraryDirective(LibraryDirective node) { |
| 2320 node.element = _enclosingUnit.library; | 2331 node.element = _enclosingUnit.library; |
| 2321 return super.visitLibraryDirective(node); | 2332 return super.visitLibraryDirective(node); |
| 2322 } | 2333 } |
| 2323 | 2334 |
| 2324 @override | 2335 @override |
| 2325 Object visitMethodDeclaration(MethodDeclaration node) { | 2336 Object visitMethodDeclaration(MethodDeclaration node) { |
| 2326 ExecutableElement outerExecutable = _enclosingExecutable; | 2337 ExecutableElement outerExecutable = _enclosingExecutable; |
| 2327 try { | 2338 try { |
| 2328 Token property = node.propertyKeyword; | 2339 Token property = node.propertyKeyword; |
| 2329 SimpleIdentifier methodName = node.name; | 2340 SimpleIdentifier methodName = node.name; |
| 2330 String nameOfMethod = methodName.name; | 2341 String nameOfMethod = methodName.name; |
| 2331 if (property == null) { | 2342 if (property == null) { |
| 2332 _enclosingExecutable = _findWithNameAndOffset( | 2343 _enclosingExecutable = _findWithNameAndOffset(_enclosingClass.methods, |
| 2333 _enclosingClass.methods, nameOfMethod, methodName.offset); | 2344 methodName, nameOfMethod, methodName.offset); |
| 2334 methodName.staticElement = _enclosingExecutable; | 2345 methodName.staticElement = _enclosingExecutable; |
| 2335 } else { | 2346 } else { |
| 2336 PropertyAccessorElement accessor = | 2347 PropertyAccessorElement accessor; |
| 2337 _findIdentifier(_enclosingClass.accessors, methodName); | 2348 if ((property as KeywordToken).keyword == Keyword.GET) { |
| 2338 if ((property as KeywordToken).keyword == Keyword.SET) { | 2349 accessor = _findIdentifier(_enclosingClass.accessors, methodName); |
| 2339 accessor = accessor.variable.setter; | 2350 } else if ((property as KeywordToken).keyword == Keyword.SET) { |
| 2351 accessor = _findWithNameAndOffset(_enclosingClass.accessors, |
| 2352 methodName, methodName.name + '=', methodName.offset); |
| 2340 methodName.staticElement = accessor; | 2353 methodName.staticElement = accessor; |
| 2341 } | 2354 } |
| 2342 _enclosingExecutable = accessor; | 2355 _enclosingExecutable = accessor; |
| 2343 } | 2356 } |
| 2344 return super.visitMethodDeclaration(node); | 2357 return super.visitMethodDeclaration(node); |
| 2345 } finally { | 2358 } finally { |
| 2346 _enclosingExecutable = outerExecutable; | 2359 _enclosingExecutable = outerExecutable; |
| 2347 } | 2360 } |
| 2348 } | 2361 } |
| 2349 | 2362 |
| 2350 @override | 2363 @override |
| 2351 Object visitPartDirective(PartDirective node) { | 2364 Object visitPartDirective(PartDirective node) { |
| 2352 String uri = _getStringValue(node.uri); | 2365 String uri = _getStringValue(node.uri); |
| 2353 if (uri != null) { | 2366 if (uri != null) { |
| 2354 Source partSource = _enclosingUnit.context.sourceFactory | 2367 Source partSource = _enclosingUnit.context.sourceFactory |
| 2355 .resolveUri(_enclosingUnit.source, uri); | 2368 .resolveUri(_enclosingUnit.source, uri); |
| 2356 node.element = _findPart(_enclosingUnit.library.parts, partSource); | 2369 node.element = _findPart(_enclosingUnit.library.parts, node, partSource); |
| 2357 } | 2370 } |
| 2358 return super.visitPartDirective(node); | 2371 return super.visitPartDirective(node); |
| 2359 } | 2372 } |
| 2360 | 2373 |
| 2361 @override | 2374 @override |
| 2362 Object visitPartOfDirective(PartOfDirective node) { | 2375 Object visitPartOfDirective(PartOfDirective node) { |
| 2363 node.element = _enclosingUnit.library; | 2376 node.element = _enclosingUnit.library; |
| 2364 return super.visitPartOfDirective(node); | 2377 return super.visitPartOfDirective(node); |
| 2365 } | 2378 } |
| 2366 | 2379 |
| (...skipping 27 matching lines...) Expand all Loading... |
| 2394 for (Label label in node.labels) { | 2407 for (Label label in node.labels) { |
| 2395 SimpleIdentifier labelName = label.label; | 2408 SimpleIdentifier labelName = label.label; |
| 2396 _findIdentifier(_enclosingExecutable.labels, labelName); | 2409 _findIdentifier(_enclosingExecutable.labels, labelName); |
| 2397 } | 2410 } |
| 2398 return super.visitSwitchDefault(node); | 2411 return super.visitSwitchDefault(node); |
| 2399 } | 2412 } |
| 2400 | 2413 |
| 2401 @override | 2414 @override |
| 2402 Object visitTypeParameter(TypeParameter node) { | 2415 Object visitTypeParameter(TypeParameter node) { |
| 2403 SimpleIdentifier parameterName = node.name; | 2416 SimpleIdentifier parameterName = node.name; |
| 2404 | 2417 Element element = null; |
| 2405 Element element; | |
| 2406 if (_enclosingExecutable != null) { | 2418 if (_enclosingExecutable != null) { |
| 2407 element = | 2419 element = _findIdentifier( |
| 2408 _findIdentifier(_enclosingExecutable.typeParameters, parameterName); | 2420 _enclosingExecutable.typeParameters, parameterName, |
| 2421 required: false); |
| 2409 } | 2422 } |
| 2410 if (element == null) { | 2423 if (element == null) { |
| 2411 if (_enclosingClass != null) { | 2424 if (_enclosingClass != null) { |
| 2412 _findIdentifier(_enclosingClass.typeParameters, parameterName); | 2425 _findIdentifier(_enclosingClass.typeParameters, parameterName); |
| 2413 } else if (_enclosingAlias != null) { | 2426 } else if (_enclosingAlias != null) { |
| 2414 _findIdentifier(_enclosingAlias.typeParameters, parameterName); | 2427 _findIdentifier(_enclosingAlias.typeParameters, parameterName); |
| 2415 } | 2428 } |
| 2416 } | 2429 } |
| 2417 return super.visitTypeParameter(node); | 2430 return super.visitTypeParameter(node); |
| 2418 } | 2431 } |
| 2419 | 2432 |
| 2420 @override | 2433 @override |
| 2421 Object visitVariableDeclaration(VariableDeclaration node) { | 2434 Object visitVariableDeclaration(VariableDeclaration node) { |
| 2422 VariableElement element = null; | 2435 VariableElement element = null; |
| 2423 SimpleIdentifier variableName = node.name; | 2436 SimpleIdentifier variableName = node.name; |
| 2424 if (_enclosingExecutable != null) { | 2437 if (_enclosingExecutable != null) { |
| 2425 element = | 2438 element = _findIdentifier( |
| 2426 _findIdentifier(_enclosingExecutable.localVariables, variableName); | 2439 _enclosingExecutable.localVariables, variableName, |
| 2440 required: false); |
| 2427 } | 2441 } |
| 2428 if (element == null && _enclosingClass != null) { | 2442 if (element == null && _enclosingClass != null) { |
| 2429 element = _findIdentifier(_enclosingClass.fields, variableName); | 2443 element = _findIdentifier(_enclosingClass.fields, variableName, |
| 2444 required: false); |
| 2430 } | 2445 } |
| 2431 if (element == null && _enclosingUnit != null) { | 2446 if (element == null && _enclosingUnit != null) { |
| 2432 element = _findIdentifier(_enclosingUnit.topLevelVariables, variableName); | 2447 element = _findIdentifier(_enclosingUnit.topLevelVariables, variableName); |
| 2433 } | 2448 } |
| 2434 Expression initializer = node.initializer; | 2449 Expression initializer = node.initializer; |
| 2435 if (initializer != null) { | 2450 if (initializer != null) { |
| 2436 ExecutableElement outerExecutable = _enclosingExecutable; | 2451 ExecutableElement outerExecutable = _enclosingExecutable; |
| 2437 try { | 2452 try { |
| 2438 if (element == null) { | 2453 _enclosingExecutable = element.initializer; |
| 2439 // TODO(brianwilkerson) Report this internal error. | |
| 2440 } else { | |
| 2441 _enclosingExecutable = element.initializer; | |
| 2442 } | |
| 2443 return super.visitVariableDeclaration(node); | 2454 return super.visitVariableDeclaration(node); |
| 2444 } finally { | 2455 } finally { |
| 2445 _enclosingExecutable = outerExecutable; | 2456 _enclosingExecutable = outerExecutable; |
| 2446 } | 2457 } |
| 2447 } | 2458 } |
| 2448 return super.visitVariableDeclaration(node); | 2459 return super.visitVariableDeclaration(node); |
| 2449 } | 2460 } |
| 2450 | 2461 |
| 2451 /** | 2462 /** |
| 2452 * Return the element in the given array of elements that was created for the
declaration at the | 2463 * Return the element in the given list of [elements] that was created for the |
| 2453 * given offset. This method should only be used when there is no name | 2464 * declaration at the given [offset]. Throw an [ElementMismatchException] if |
| 2465 * an element at that offset cannot be found. |
| 2454 * | 2466 * |
| 2455 * @param elements the elements of the appropriate kind that exist in the curr
ent context | 2467 * This method should only be used when there is no name associated with the |
| 2456 * @param offset the offset of the name of the element to be returned | 2468 * node. |
| 2457 * @return the element at the given offset | |
| 2458 */ | 2469 */ |
| 2459 Element _findAtOffset(List<Element> elements, int offset) => | 2470 Element _findAtOffset(List<Element> elements, AstNode node, int offset) => |
| 2460 _findWithNameAndOffset(elements, "", offset); | 2471 _findWithNameAndOffset(elements, node, '', offset); |
| 2461 | 2472 |
| 2462 /** | 2473 /** |
| 2463 * Return the export element from the given array whose library has the given
source, or | 2474 * Return the export element from the given list of [exports] whose library |
| 2464 * `null` if there is no such export. | 2475 * has the given [source]. Throw an [ElementMismatchException] if an element |
| 2465 * | 2476 * corresponding to the identifier cannot be found. |
| 2466 * @param exports the export elements being searched | |
| 2467 * @param source the source of the library associated with the export element
to being searched | |
| 2468 * for | |
| 2469 * @return the export element whose library has the given source | |
| 2470 */ | 2477 */ |
| 2471 ExportElement _findExport(List<ExportElement> exports, Source source) { | 2478 ExportElement _findExport( |
| 2479 ExportDirective node, List<ExportElement> exports, Source source) { |
| 2472 for (ExportElement export in exports) { | 2480 for (ExportElement export in exports) { |
| 2473 if (export.exportedLibrary.source == source) { | 2481 if (export.exportedLibrary.source == source) { |
| 2474 return export; | 2482 return export; |
| 2475 } | 2483 } |
| 2476 } | 2484 } |
| 2477 return null; | 2485 _mismatch("Could not find export element for '$source'", node); |
| 2486 return null; // Never reached |
| 2478 } | 2487 } |
| 2479 | 2488 |
| 2480 /** | 2489 /** |
| 2481 * Return the element in the given array of elements that was created for the
declaration with the | 2490 * Return the element in the given list of [elements] that was created for the |
| 2482 * given name. | 2491 * declaration with the given [identifier]. As a side-effect, associate the |
| 2483 * | 2492 * returned element with the identifier. Throw an [ElementMismatchException] |
| 2484 * @param elements the elements of the appropriate kind that exist in the curr
ent context | 2493 * if an element corresponding to the identifier cannot be found unless |
| 2485 * @param identifier the name node in the declaration of the element to be ret
urned | 2494 * [required] is `false`, in which case return `null`. |
| 2486 * @return the element created for the declaration with the given name | |
| 2487 */ | 2495 */ |
| 2488 Element _findIdentifier(List<Element> elements, SimpleIdentifier identifier) { | 2496 Element _findIdentifier(List<Element> elements, SimpleIdentifier identifier, |
| 2489 Element element = | 2497 {bool required: true}) { |
| 2490 _findWithNameAndOffset(elements, identifier.name, identifier.offset); | 2498 Element element = _findWithNameAndOffset( |
| 2499 elements, identifier, identifier.name, identifier.offset, |
| 2500 required: required); |
| 2491 identifier.staticElement = element; | 2501 identifier.staticElement = element; |
| 2492 return element; | 2502 return element; |
| 2493 } | 2503 } |
| 2494 | 2504 |
| 2495 /** | 2505 /** |
| 2496 * Return the import element from the given array whose library has the given
source and that has | 2506 * Return the import element from the given list of [imports] whose library |
| 2497 * the given prefix, or `null` if there is no such import. | 2507 * has the given [source] and that has the given [prefix]. Throw an |
| 2498 * | 2508 * [ElementMismatchException] if an element corresponding to the identifier |
| 2499 * @param imports the import elements being searched | 2509 * cannot be found. |
| 2500 * @param source the source of the library associated with the import element
to being searched | |
| 2501 * for | |
| 2502 * @param prefix the prefix with which the library was imported | |
| 2503 * @return the import element whose library has the given source and prefix | |
| 2504 */ | 2510 */ |
| 2505 ImportElement _findImport( | 2511 ImportElement _findImport( |
| 2506 List<ImportElement> imports, Source source, SimpleIdentifier prefix) { | 2512 ImportDirective node, List<ImportElement> imports, Source source) { |
| 2513 SimpleIdentifier prefix = node.prefix; |
| 2514 bool foundSource = false; |
| 2507 for (ImportElement element in imports) { | 2515 for (ImportElement element in imports) { |
| 2508 if (element.importedLibrary.source == source) { | 2516 if (element.importedLibrary.source == source) { |
| 2517 foundSource = true; |
| 2509 PrefixElement prefixElement = element.prefix; | 2518 PrefixElement prefixElement = element.prefix; |
| 2510 if (prefix == null) { | 2519 if (prefix == null) { |
| 2511 if (prefixElement == null) { | 2520 if (prefixElement == null) { |
| 2512 return element; | 2521 return element; |
| 2513 } | 2522 } |
| 2514 } else { | 2523 } else { |
| 2515 if (prefixElement != null && | 2524 if (prefixElement != null && |
| 2516 prefix.name == prefixElement.displayName) { | 2525 prefix.name == prefixElement.displayName) { |
| 2517 return element; | 2526 return element; |
| 2518 } | 2527 } |
| 2519 } | 2528 } |
| 2520 } | 2529 } |
| 2521 } | 2530 } |
| 2522 return null; | 2531 if (foundSource) { |
| 2532 if (prefix == null) { |
| 2533 _mismatch( |
| 2534 "Could not find import element for '$source' with no prefix", node); |
| 2535 } |
| 2536 _mismatch( |
| 2537 "Could not find import element for '$source' with prefix ${prefix.name
}", |
| 2538 node); |
| 2539 } |
| 2540 _mismatch("Could not find import element for '$source'", node); |
| 2541 return null; // Never reached |
| 2523 } | 2542 } |
| 2524 | 2543 |
| 2525 /** | 2544 /** |
| 2526 * Return the element for the part with the given source, or `null` if there i
s no element | 2545 * Return the element in the given list of [parts] that was created for the |
| 2527 * for the given source. | 2546 * part with the given [source]. Throw an [ElementMismatchException] if an |
| 2528 * | 2547 * element corresponding to the source cannot be found. |
| 2529 * @param parts the elements for the parts | |
| 2530 * @param partSource the source for the part whose element is to be returned | |
| 2531 * @return the element for the part with the given source | |
| 2532 */ | 2548 */ |
| 2533 CompilationUnitElement _findPart( | 2549 CompilationUnitElement _findPart(List<CompilationUnitElement> parts, |
| 2534 List<CompilationUnitElement> parts, Source partSource) { | 2550 PartDirective directive, Source source) { |
| 2535 for (CompilationUnitElement part in parts) { | 2551 for (CompilationUnitElement part in parts) { |
| 2536 if (part.source == partSource) { | 2552 if (part.source == source) { |
| 2537 return part; | 2553 return part; |
| 2538 } | 2554 } |
| 2539 } | 2555 } |
| 2540 return null; | 2556 _mismatch( |
| 2557 'Could not find compilation unit element for "$source"', directive); |
| 2558 return null; // Never reached |
| 2541 } | 2559 } |
| 2542 | 2560 |
| 2543 /** | 2561 /** |
| 2544 * Return the element in the given array of elements that was created for the
declaration with the | 2562 * Return the element in the given list of [elements] that was created for the |
| 2545 * given name at the given offset. | 2563 * declaration with the given [name] at the given [offset]. Throw an |
| 2546 * | 2564 * [ElementMismatchException] if an element corresponding to the identifier |
| 2547 * @param elements the elements of the appropriate kind that exist in the curr
ent context | 2565 * cannot be found unless [required] is `false`, in which case return `null`. |
| 2548 * @param name the name of the element to be returned | |
| 2549 * @param offset the offset of the name of the element to be returned | |
| 2550 * @return the element with the given name and offset | |
| 2551 */ | 2566 */ |
| 2552 Element _findWithNameAndOffset( | 2567 Element _findWithNameAndOffset( |
| 2553 List<Element> elements, String name, int offset) { | 2568 List<Element> elements, AstNode node, String name, int offset, |
| 2569 {bool required: true}) { |
| 2554 for (Element element in elements) { | 2570 for (Element element in elements) { |
| 2555 if (element.nameOffset == offset && element.displayName == name) { | 2571 if (element.nameOffset == offset && element.name == name) { |
| 2556 return element; | 2572 return element; |
| 2557 } | 2573 } |
| 2558 } | 2574 } |
| 2559 return null; | 2575 if (!required) { |
| 2576 return null; |
| 2577 } |
| 2578 for (Element element in elements) { |
| 2579 if (element.name == name) { |
| 2580 _mismatch( |
| 2581 'Found element with name "$name" at ${element.nameOffset}, ' |
| 2582 'but expected offset of $offset', |
| 2583 node); |
| 2584 } |
| 2585 if (element.nameOffset == offset) { |
| 2586 _mismatch( |
| 2587 'Found element with name "${element.name}" at $offset, ' |
| 2588 'but expected element with name "$name"', |
| 2589 node); |
| 2590 } |
| 2591 } |
| 2592 _mismatch('Could not find element with name "$name" at $offset', node); |
| 2593 return null; // Never reached |
| 2560 } | 2594 } |
| 2561 | 2595 |
| 2562 /** | 2596 /** |
| 2563 * Search the most closely enclosing list of parameters for a parameter with t
he given name. | 2597 * Search the most closely enclosing list of parameter elements for a |
| 2564 * | 2598 * parameter, defined by the given [node], with the given [parameterName]. |
| 2565 * @param node the node defining the parameter with the given name | 2599 * Return the element that was found, or throw an [ElementMismatchException] |
| 2566 * @param parameterName the name of the parameter being searched for | 2600 * if an element corresponding to the identifier cannot be found. |
| 2567 * @return the element representing the parameter with that name | |
| 2568 */ | 2601 */ |
| 2569 ParameterElement _getElementForParameter( | 2602 ParameterElement _getElementForParameter( |
| 2570 FormalParameter node, SimpleIdentifier parameterName) { | 2603 FormalParameter node, SimpleIdentifier parameterName) { |
| 2571 List<ParameterElement> parameters = null; | 2604 List<ParameterElement> parameters = null; |
| 2572 if (_enclosingParameter != null) { | 2605 if (_enclosingParameter != null) { |
| 2573 parameters = _enclosingParameter.parameters; | 2606 parameters = _enclosingParameter.parameters; |
| 2574 } | 2607 } |
| 2575 if (parameters == null && _enclosingExecutable != null) { | 2608 if (parameters == null && _enclosingExecutable != null) { |
| 2576 parameters = _enclosingExecutable.parameters; | 2609 parameters = _enclosingExecutable.parameters; |
| 2577 } | 2610 } |
| 2578 if (parameters == null && _enclosingAlias != null) { | 2611 if (parameters == null && _enclosingAlias != null) { |
| 2579 parameters = _enclosingAlias.parameters; | 2612 parameters = _enclosingAlias.parameters; |
| 2580 } | 2613 } |
| 2581 ParameterElement element = | 2614 if (parameters == null) { |
| 2582 parameters == null ? null : _findIdentifier(parameters, parameterName); | |
| 2583 if (element == null) { | |
| 2584 StringBuffer buffer = new StringBuffer(); | 2615 StringBuffer buffer = new StringBuffer(); |
| 2585 buffer.writeln("Invalid state found in the Analysis Engine:"); | 2616 buffer.writeln('Could not find parameter in enclosing scope'); |
| 2586 buffer.writeln( | 2617 buffer.writeln( |
| 2587 "DeclarationResolver.getElementForParameter() is visiting a parameter
that does not appear to be in a method or function."); | 2618 '(_enclosingParameter == null) == ${_enclosingParameter == null}'); |
| 2588 buffer.writeln("Ancestors:"); | 2619 buffer.writeln( |
| 2589 AstNode parent = node.parent; | 2620 '(_enclosingExecutable == null) == ${_enclosingExecutable == null}'); |
| 2590 while (parent != null) { | 2621 buffer.writeln('(_enclosingAlias == null) == ${_enclosingAlias == null}'); |
| 2591 buffer.writeln(parent.runtimeType.toString()); | 2622 _mismatch(buffer.toString(), parameterName); |
| 2592 buffer.writeln("---------"); | |
| 2593 parent = parent.parent; | |
| 2594 } | |
| 2595 AnalysisEngine.instance.logger.logError(buffer.toString(), | |
| 2596 new CaughtException(new AnalysisException(), null)); | |
| 2597 } | 2623 } |
| 2598 return element; | 2624 return _findIdentifier(parameters, parameterName); |
| 2599 } | 2625 } |
| 2600 | 2626 |
| 2601 /** | 2627 /** |
| 2602 * Return the value of the given string literal, or `null` if the string is no
t a constant | 2628 * Return the value of the given string [literal], or `null` if the string is |
| 2603 * string without any string interpolation. | 2629 * not a constant string without any string interpolation. |
| 2604 * | |
| 2605 * @param literal the string literal whose value is to be returned | |
| 2606 * @return the value of the given string literal | |
| 2607 */ | 2630 */ |
| 2608 String _getStringValue(StringLiteral literal) { | 2631 String _getStringValue(StringLiteral literal) { |
| 2609 if (literal is StringInterpolation) { | 2632 if (literal is StringInterpolation) { |
| 2610 return null; | 2633 return null; |
| 2611 } | 2634 } |
| 2612 return literal.stringValue; | 2635 return literal.stringValue; |
| 2613 } | 2636 } |
| 2637 |
| 2638 /** |
| 2639 * Throw an [ElementMismatchException] to report that the element model and |
| 2640 * the AST do not match. The [message] will have the path to the given [node] |
| 2641 * appended to it. |
| 2642 */ |
| 2643 void _mismatch(String message, AstNode node) { |
| 2644 StringBuffer buffer = new StringBuffer(); |
| 2645 buffer.writeln(message); |
| 2646 buffer.write('Path to root:'); |
| 2647 String separator = ' '; |
| 2648 AstNode parent = node; |
| 2649 while (parent != null) { |
| 2650 buffer.write(separator); |
| 2651 buffer.write(parent.runtimeType.toString()); |
| 2652 separator = ', '; |
| 2653 parent = parent.parent; |
| 2654 } |
| 2655 throw new ElementMismatchException(buffer.toString()); |
| 2656 } |
| 2614 } | 2657 } |
| 2615 | 2658 |
| 2616 /** | 2659 /** |
| 2617 * Instances of the class `ElementHolder` hold on to elements created while trav
ersing an AST | 2660 * Instances of the class `ElementHolder` hold on to elements created while trav
ersing an AST |
| 2618 * structure so that they can be accessed when creating their enclosing element. | 2661 * structure so that they can be accessed when creating their enclosing element. |
| 2619 */ | 2662 */ |
| 2620 class ElementHolder { | 2663 class ElementHolder { |
| 2621 List<PropertyAccessorElement> _accessors; | 2664 List<PropertyAccessorElement> _accessors; |
| 2622 | 2665 |
| 2623 List<ConstructorElement> _constructors; | 2666 List<ConstructorElement> _constructors; |
| (...skipping 343 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 2967 buffer.write(_typeParameters.length); | 3010 buffer.write(_typeParameters.length); |
| 2968 buffer.write(" type parameters"); | 3011 buffer.write(" type parameters"); |
| 2969 } | 3012 } |
| 2970 if (buffer.length > 0) { | 3013 if (buffer.length > 0) { |
| 2971 AnalysisEngine.instance.logger | 3014 AnalysisEngine.instance.logger |
| 2972 .logError("Failed to capture elements: $buffer"); | 3015 .logError("Failed to capture elements: $buffer"); |
| 2973 } | 3016 } |
| 2974 } | 3017 } |
| 2975 } | 3018 } |
| 2976 | 3019 |
| 3020 class ElementMismatchException extends AnalysisException { |
| 3021 /** |
| 3022 * Initialize a newly created exception to have the given [message] and |
| 3023 * [cause]. |
| 3024 */ |
| 3025 ElementMismatchException(String message, [CaughtException cause = null]) |
| 3026 : super(message, cause); |
| 3027 } |
| 3028 |
| 2977 /** | 3029 /** |
| 2978 * Instances of the class `EnclosedScope` implement a scope that is lexically en
closed in | 3030 * Instances of the class `EnclosedScope` implement a scope that is lexically en
closed in |
| 2979 * another scope. | 3031 * another scope. |
| 2980 */ | 3032 */ |
| 2981 class EnclosedScope extends Scope { | 3033 class EnclosedScope extends Scope { |
| 2982 /** | 3034 /** |
| 2983 * The scope in which this scope is lexically enclosed. | 3035 * The scope in which this scope is lexically enclosed. |
| 2984 */ | 3036 */ |
| 2985 final Scope enclosingScope; | 3037 final Scope enclosingScope; |
| 2986 | 3038 |
| (...skipping 9515 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 12502 nonFields.add(node); | 12554 nonFields.add(node); |
| 12503 return null; | 12555 return null; |
| 12504 } | 12556 } |
| 12505 | 12557 |
| 12506 @override | 12558 @override |
| 12507 Object visitNode(AstNode node) => node.accept(TypeResolverVisitor_this); | 12559 Object visitNode(AstNode node) => node.accept(TypeResolverVisitor_this); |
| 12508 | 12560 |
| 12509 @override | 12561 @override |
| 12510 Object visitWithClause(WithClause node) => null; | 12562 Object visitWithClause(WithClause node) => null; |
| 12511 } | 12563 } |
| OLD | NEW |