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

Side by Side Diff: pkg/analyzer/lib/src/generated/resolver.dart

Issue 1669383002: More aggressively fail when associating an existing element model with an AST (issue 25678) (Closed) Base URL: https://github.com/dart-lang/sdk.git@master
Patch Set: Created 4 years, 10 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
« no previous file with comments | « no previous file | pkg/analyzer/test/generated/declaration_resolver_test.dart » ('j') | no next file with comments »
Toggle Intra-line Diffs ('i') | Expand Comments ('e') | Collapse Comments ('c') | Show Comments Hide Comments ('s')
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 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
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
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
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
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
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
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
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
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 }
OLDNEW
« no previous file with comments | « no previous file | pkg/analyzer/test/generated/declaration_resolver_test.dart » ('j') | no next file with comments »

Powered by Google App Engine
This is Rietveld 408576698