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

Side by Side Diff: pkg/analyzer2dart/lib/src/identifier_semantics.dart

Issue 652403005: Support assignment of locals in analyzer2dart. (Closed) Base URL: https://dart.googlecode.com/svn/branches/bleeding_edge/dart
Patch Set: Created 6 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 | Annotate | Revision Log
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 /** 5 /**
6 * Code for classifying the semantics of identifiers appearing in a Dart file. 6 * Code for classifying the semantics of identifiers appearing in a Dart file.
7 */ 7 */
8 library analyzer2dart.identifierSemantics; 8 library analyzer2dart.identifierSemantics;
9 9
10 import 'package:analyzer/analyzer.dart'; 10 import 'package:analyzer/analyzer.dart';
(...skipping 181 matching lines...) Expand 10 before | Expand all | Expand 10 after
192 sb.write('target=this.$identifier'); 192 sb.write('target=this.$identifier');
193 } else { 193 } else {
194 sb.write('target=$target.$identifier'); 194 sb.write('target=$target.$identifier');
195 } 195 }
196 } 196 }
197 sb.write(']'); 197 sb.write(']');
198 return sb.toString(); 198 return sb.toString();
199 } 199 }
200 } 200 }
201 201
202 /** 202 // TODO(johnniwinther,paulberry): This should be a constant.
203 * Return the semantics for [node]. 203 final AccessSemanticsVisitor ACCESS_SEMANTICS_VISITOR =
204 */ 204 new AccessSemanticsVisitor();
205 AccessSemantics classifyMethodInvocation(MethodInvocation node) { 205
206 Expression target = node.realTarget; 206 // TODO(johnniwinther,paulberry): This should extend a non-recursive visitor.
207 Element staticElement = node.methodName.staticElement; 207 class AccessSemanticsVisitor extends RecursiveAstVisitor<AccessSemantics> {
208 if (target == null) { 208 /**
209 if (staticElement is FunctionElement) { 209 * Return the semantics for [node].
210 if (staticElement.enclosingElement is CompilationUnitElement) { 210 */
211 @override
212 AccessSemantics visitMethodInvocation(MethodInvocation node) {
213 Expression target = node.realTarget;
214 Element staticElement = node.methodName.staticElement;
215 if (target == null) {
216 if (staticElement is FunctionElement) {
217 if (staticElement.enclosingElement is CompilationUnitElement) {
218 return new AccessSemantics.staticMethod(
219 node.methodName,
220 staticElement,
221 null,
222 isInvoke: true);
223 } else {
224 return new AccessSemantics.localFunction(
225 node.methodName,
226 staticElement,
227 isInvoke: true);
228 }
229 } else if (staticElement is MethodElement && staticElement.isStatic) {
211 return new AccessSemantics.staticMethod( 230 return new AccessSemantics.staticMethod(
212 node.methodName, 231 node.methodName,
213 staticElement, 232 staticElement,
214 null, 233 staticElement.enclosingElement,
215 isInvoke: true); 234 isInvoke: true);
216 } else { 235 } else if (staticElement is PropertyAccessorElement) {
217 return new AccessSemantics.localFunction( 236 if (staticElement.isSynthetic) {
237 if (staticElement.enclosingElement is CompilationUnitElement) {
238 return new AccessSemantics.staticField(
239 node.methodName,
240 staticElement.variable,
241 null,
242 isInvoke: true);
243 } else if (staticElement.isStatic) {
244 return new AccessSemantics.staticField(
245 node.methodName,
246 staticElement.variable,
247 staticElement.enclosingElement,
248 isInvoke: true);
249 }
250 } else {
251 if (staticElement.enclosingElement is CompilationUnitElement) {
252 return new AccessSemantics.staticProperty(
253 node.methodName,
254 staticElement,
255 null,
256 isInvoke: true);
257 } else if (staticElement.isStatic) {
258 return new AccessSemantics.staticProperty(
259 node.methodName,
260 staticElement,
261 staticElement.enclosingElement,
262 isInvoke: true);
263 }
264 }
265 } else if (staticElement is LocalVariableElement) {
266 return new AccessSemantics.localVariable(
218 node.methodName, 267 node.methodName,
219 staticElement, 268 staticElement,
220 isInvoke: true); 269 isInvoke: true);
221 } 270 } else if (staticElement is ParameterElement) {
222 } else if (staticElement is MethodElement && staticElement.isStatic) { 271 return new AccessSemantics.parameter(
223 return new AccessSemantics.staticMethod( 272 node.methodName,
224 node.methodName, 273 staticElement,
225 staticElement, 274 isInvoke: true);
226 staticElement.enclosingElement, 275 }
227 isInvoke: true); 276 } else if (target is Identifier) {
228 } else if (staticElement is PropertyAccessorElement) { 277 Element targetStaticElement = target.staticElement;
278 if (targetStaticElement is PrefixElement) {
279 if (staticElement == null) {
280 return new AccessSemantics.dynamic(
281 node.methodName,
282 null,
283 isInvoke: true);
284 } else if (staticElement is PropertyAccessorElement) {
285 if (staticElement.isSynthetic) {
286 return new AccessSemantics.staticField(
287 node.methodName,
288 staticElement.variable,
289 null,
290 isInvoke: true);
291 } else {
292 return new AccessSemantics.staticProperty(
293 node.methodName,
294 staticElement,
295 null,
296 isInvoke: true);
297 }
298 } else {
299 return new AccessSemantics.staticMethod(
300 node.methodName,
301 staticElement,
302 null,
303 isInvoke: true);
304 }
305 } else if (targetStaticElement is ClassElement) {
306 if (staticElement is PropertyAccessorElement) {
307 if (staticElement.isSynthetic) {
308 return new AccessSemantics.staticField(
309 node.methodName,
310 staticElement.variable,
311 targetStaticElement,
312 isInvoke: true);
313 } else {
314 return new AccessSemantics.staticProperty(
315 node.methodName,
316 staticElement,
317 targetStaticElement,
318 isInvoke: true);
319 }
320 } else {
321 return new AccessSemantics.staticMethod(
322 node.methodName,
323 staticElement,
324 targetStaticElement,
325 isInvoke: true);
326 }
327 }
328 }
329 return new AccessSemantics.dynamic(node.methodName, target, isInvoke: true);
330 }
331
332 /**
333 * Return the access semantics for [node].
334 */
335 @override
336 AccessSemantics visitPrefixedIdentifier(PrefixedIdentifier node) {
337 return _classifyPrefixed(node.prefix, node.identifier);
338 }
339
340 /**
341 * Helper function for classifying an expression of type
342 * Identifier.SimpleIdentifier.
343 */
344 AccessSemantics _classifyPrefixed(Identifier lhs, SimpleIdentifier rhs) {
345 Element lhsElement = lhs.staticElement;
346 Element rhsElement = rhs.staticElement;
347 if (lhsElement is PrefixElement) {
348 if (rhsElement is PropertyAccessorElement) {
349 if (rhsElement.isSynthetic) {
350 return new AccessSemantics.staticField(rhs, rhsElement.variable, null) ;
351 } else {
352 return new AccessSemantics.staticProperty(rhs, rhsElement, null);
353 }
354 } else if (rhsElement is FunctionElement) {
355 return new AccessSemantics.staticMethod(rhs, rhsElement, null);
356 } else {
357 return new AccessSemantics.dynamic(rhs, null);
358 }
359 } else if (lhsElement is ClassElement) {
360 if (rhsElement is PropertyAccessorElement && rhsElement.isSynthetic) {
361 return new AccessSemantics.staticField(
362 rhs,
363 rhsElement.variable,
364 lhsElement);
365 } else if (rhsElement is MethodElement) {
366 return new AccessSemantics.staticMethod(rhs, rhsElement, lhsElement);
367 } else {
368 return new AccessSemantics.staticProperty(rhs, rhsElement, lhsElement);
369 }
370 } else {
371 return new AccessSemantics.dynamic(rhs, lhs);
372 }
373 }
374
375 /**
376 * Return the access semantics for [node].
377 */
378 @override
379 AccessSemantics visitPropertyAccess(PropertyAccess node) {
380 if (node.target is Identifier) {
381 return _classifyPrefixed(node.target, node.propertyName);
382 } else {
383 return new AccessSemantics.dynamic(node.propertyName, node.realTarget);
384 }
385 }
386
387 /**
388 * Return the access semantics for [node].
389 *
390 * Note: if [node] is the right hand side of a [PropertyAccess] or
391 * [PrefixedIdentifier], or the method name of a [MethodInvocation], the retur n
392 * value is null, since the semantics are determined by the parent. In
393 * practice these cases should never arise because the parent will visit the
394 * parent node before visiting this one.
395 */
396 @override
397 AccessSemantics visitSimpleIdentifier(SimpleIdentifier node) {
398 AstNode parent = node.parent;
399 if (node.inDeclarationContext()) {
400 // This identifier is a declaration, not a use.
401 return null;
402 }
403 if (parent is TypeName) {
404 // TODO(paulberry): handle this case. Or, perhaps it would be better to
405 // require clients not to visit the children of a TypeName when visiting
406 // the AST structure.
407 //
408 // TODO(paulberry): be sure to consider type literals, e.g.:
409 // class A {}
410 // var a = A;
411 return null;
412 }
413 if ((parent is PropertyAccess && parent.propertyName == node) ||
414 (parent is PrefixedIdentifier && parent.identifier == node) ||
415 (parent is MethodInvocation && parent.methodName == node)) {
416 // The access semantics are determined by the parent.
417 return null;
418 }
419 // TODO(paulberry): handle PrefixElement.
420 Element staticElement = node.staticElement;
421 if (staticElement is PropertyAccessorElement) {
229 if (staticElement.isSynthetic) { 422 if (staticElement.isSynthetic) {
230 if (staticElement.enclosingElement is CompilationUnitElement) { 423 if (staticElement.enclosingElement is CompilationUnitElement) {
231 return new AccessSemantics.staticField( 424 return new AccessSemantics.staticField(
232 node.methodName, 425 node,
233 staticElement.variable, 426 staticElement.variable,
234 null, 427 null);
235 isInvoke: true);
236 } else if (staticElement.isStatic) { 428 } else if (staticElement.isStatic) {
237 return new AccessSemantics.staticField( 429 return new AccessSemantics.staticField(
238 node.methodName, 430 node,
239 staticElement.variable, 431 staticElement.variable,
240 staticElement.enclosingElement, 432 staticElement.enclosingElement);
241 isInvoke: true);
242 } 433 }
243 } else { 434 } else {
244 if (staticElement.enclosingElement is CompilationUnitElement) { 435 if (staticElement.enclosingElement is CompilationUnitElement) {
245 return new AccessSemantics.staticProperty( 436 return new AccessSemantics.staticProperty(node, staticElement, null);
246 node.methodName,
247 staticElement,
248 null,
249 isInvoke: true);
250 } else if (staticElement.isStatic) { 437 } else if (staticElement.isStatic) {
251 return new AccessSemantics.staticProperty( 438 return new AccessSemantics.staticProperty(
252 node.methodName, 439 node,
253 staticElement, 440 staticElement,
254 staticElement.enclosingElement, 441 staticElement.enclosingElement);
255 isInvoke: true);
256 } 442 }
257 } 443 }
258 } else if (staticElement is LocalVariableElement) { 444 } else if (staticElement is LocalVariableElement) {
259 return new AccessSemantics.localVariable( 445 return new AccessSemantics.localVariable(node, staticElement);
260 node.methodName, 446 } else if (staticElement is ParameterElement) {
447 return new AccessSemantics.parameter(node, staticElement);
448 } else if (staticElement is FunctionElement) {
449 if (staticElement.enclosingElement is CompilationUnitElement) {
450 return new AccessSemantics.staticMethod(node, staticElement, null);
451 } else {
452 return new AccessSemantics.localFunction(node, staticElement);
453 }
454 } else if (staticElement is MethodElement && staticElement.isStatic) {
455 return new AccessSemantics.staticMethod(
456 node,
261 staticElement, 457 staticElement,
262 isInvoke: true); 458 staticElement.enclosingElement);
263 } else if (staticElement is ParameterElement) { 459 }
264 return new AccessSemantics.parameter( 460 return new AccessSemantics.dynamic(node, null);
265 node.methodName, 461 }
266 staticElement, 462 }
267 isInvoke: true);
268 }
269 } else if (target is Identifier) {
270 Element targetStaticElement = target.staticElement;
271 if (targetStaticElement is PrefixElement) {
272 if (staticElement == null) {
273 return new AccessSemantics.dynamic(
274 node.methodName,
275 null,
276 isInvoke: true);
277 } else if (staticElement is PropertyAccessorElement) {
278 if (staticElement.isSynthetic) {
279 return new AccessSemantics.staticField(
280 node.methodName,
281 staticElement.variable,
282 null,
283 isInvoke: true);
284 } else {
285 return new AccessSemantics.staticProperty(
286 node.methodName,
287 staticElement,
288 null,
289 isInvoke: true);
290 }
291 } else {
292 return new AccessSemantics.staticMethod(
293 node.methodName,
294 staticElement,
295 null,
296 isInvoke: true);
297 }
298 } else if (targetStaticElement is ClassElement) {
299 if (staticElement is PropertyAccessorElement) {
300 if (staticElement.isSynthetic) {
301 return new AccessSemantics.staticField(
302 node.methodName,
303 staticElement.variable,
304 targetStaticElement,
305 isInvoke: true);
306 } else {
307 return new AccessSemantics.staticProperty(
308 node.methodName,
309 staticElement,
310 targetStaticElement,
311 isInvoke: true);
312 }
313 } else {
314 return new AccessSemantics.staticMethod(
315 node.methodName,
316 staticElement,
317 targetStaticElement,
318 isInvoke: true);
319 }
320 }
321 }
322 return new AccessSemantics.dynamic(node.methodName, target, isInvoke: true);
323 }
324
325 /**
326 * Return the access semantics for [node].
327 */
328 AccessSemantics classifyPrefixedIdentifier(PrefixedIdentifier node) {
329 return _classifyPrefixed(node.prefix, node.identifier);
330 }
331
332 /**
333 * Helper function for classifying an expression of type
334 * Identifier.SimpleIdentifier.
335 */
336 AccessSemantics _classifyPrefixed(Identifier lhs, SimpleIdentifier rhs) {
337 Element lhsElement = lhs.staticElement;
338 Element rhsElement = rhs.staticElement;
339 if (lhsElement is PrefixElement) {
340 if (rhsElement is PropertyAccessorElement) {
341 if (rhsElement.isSynthetic) {
342 return new AccessSemantics.staticField(rhs, rhsElement.variable, null);
343 } else {
344 return new AccessSemantics.staticProperty(rhs, rhsElement, null);
345 }
346 } else if (rhsElement is FunctionElement) {
347 return new AccessSemantics.staticMethod(rhs, rhsElement, null);
348 } else {
349 return new AccessSemantics.dynamic(rhs, null);
350 }
351 } else if (lhsElement is ClassElement) {
352 if (rhsElement is PropertyAccessorElement && rhsElement.isSynthetic) {
353 return new AccessSemantics.staticField(
354 rhs,
355 rhsElement.variable,
356 lhsElement);
357 } else if (rhsElement is MethodElement) {
358 return new AccessSemantics.staticMethod(rhs, rhsElement, lhsElement);
359 } else {
360 return new AccessSemantics.staticProperty(rhs, rhsElement, lhsElement);
361 }
362 } else {
363 return new AccessSemantics.dynamic(rhs, lhs);
364 }
365 }
366
367 /**
368 * Return the access semantics for [node].
369 */
370 AccessSemantics classifyPropertyAccess(PropertyAccess node) {
371 if (node.target is Identifier) {
372 return _classifyPrefixed(node.target, node.propertyName);
373 } else {
374 return new AccessSemantics.dynamic(node.propertyName, node.realTarget);
375 }
376 }
377
378 /**
379 * Return the access semantics for [node].
380 *
381 * Note: if [node] is the right hand side of a [PropertyAccess] or
382 * [PrefixedIdentifier], or the method name of a [MethodInvocation], the return
383 * value is null, since the semantics are determined by the parent. In
384 * practice these cases should never arise because the parent will visit the
385 * parent node before visiting this one.
386 */
387 AccessSemantics classifySimpleIdentifier(SimpleIdentifier node) {
388 AstNode parent = node.parent;
389 if (node.inDeclarationContext()) {
390 // This identifier is a declaration, not a use.
391 return null;
392 }
393 if (parent is TypeName) {
394 // TODO(paulberry): handle this case. Or, perhaps it would be better to
395 // require clients not to visit the children of a TypeName when visiting
396 // the AST structure.
397 //
398 // TODO(paulberry): be sure to consider type literals, e.g.:
399 // class A {}
400 // var a = A;
401 return null;
402 }
403 if ((parent is PropertyAccess && parent.propertyName == node) ||
404 (parent is PrefixedIdentifier && parent.identifier == node) ||
405 (parent is MethodInvocation && parent.methodName == node)) {
406 // The access semantics are determined by the parent.
407 return null;
408 }
409 // TODO(paulberry): handle PrefixElement.
410 Element staticElement = node.staticElement;
411 if (staticElement is PropertyAccessorElement) {
412 if (staticElement.isSynthetic) {
413 if (staticElement.enclosingElement is CompilationUnitElement) {
414 return new AccessSemantics.staticField(
415 node,
416 staticElement.variable,
417 null);
418 } else if (staticElement.isStatic) {
419 return new AccessSemantics.staticField(
420 node,
421 staticElement.variable,
422 staticElement.enclosingElement);
423 }
424 } else {
425 if (staticElement.enclosingElement is CompilationUnitElement) {
426 return new AccessSemantics.staticProperty(node, staticElement, null);
427 } else if (staticElement.isStatic) {
428 return new AccessSemantics.staticProperty(
429 node,
430 staticElement,
431 staticElement.enclosingElement);
432 }
433 }
434 } else if (staticElement is LocalVariableElement) {
435 return new AccessSemantics.localVariable(node, staticElement);
436 } else if (staticElement is ParameterElement) {
437 return new AccessSemantics.parameter(node, staticElement);
438 } else if (staticElement is FunctionElement) {
439 if (staticElement.enclosingElement is CompilationUnitElement) {
440 return new AccessSemantics.staticMethod(node, staticElement, null);
441 } else {
442 return new AccessSemantics.localFunction(node, staticElement);
443 }
444 } else if (staticElement is MethodElement && staticElement.isStatic) {
445 return new AccessSemantics.staticMethod(
446 node,
447 staticElement,
448 staticElement.enclosingElement);
449 }
450 return new AccessSemantics.dynamic(node, null);
451 }
OLDNEW

Powered by Google App Engine
This is Rietveld 408576698