@@ -395,9 +395,26 @@ module Public {
395395 LocalName getLocalName ( ) { result = this .( LocalNameBindingOutput:: LocalAccess ) .getLocal ( ) }
396396 }
397397
398+ final class LocalVariable = LocalVariableImpl ;
399+
398400 /** A representative for a lexically scoped local variable. */
399- class LocalVariable extends LocalName {
400- LocalVariable ( ) {
401+ abstract private class LocalVariableImpl extends LocalName {
402+ /** Gets the callable containing the declaration of this local variable. */
403+ abstract Callable getDeclaringCallable ( ) ;
404+
405+ /** Holds if this local variable is captured, that is, it is accessed from another callable than the one declaring it. */
406+ predicate isCaptured ( ) {
407+ this .getAnAccess ( ) .getEnclosingCallable ( ) != this .getDeclaringCallable ( )
408+ }
409+
410+ /**
411+ * Holds if this local variable represents an implicit receiver parameter of the given callable.
412+ */
413+ abstract predicate isImplicitReceiverParameter ( Callable c ) ;
414+ }
415+
416+ private class ExplicitLocalVariable extends LocalVariableImpl {
417+ ExplicitLocalVariable ( ) {
401418 exists ( AstNode decl |
402419 decl = this .getABinding ( ) .getDeclaration ( ) and
403420 not isInstanceMember ( decl ) and
@@ -411,29 +428,34 @@ module Public {
411428 decl instanceof CatchClause or
412429 decl instanceof SwitchCase
413430 )
414- or
431+ }
432+
433+ override Callable getDeclaringCallable ( ) { result = this .getABinding ( ) .getEnclosingCallable ( ) }
434+
435+ override predicate isImplicitReceiverParameter ( Callable c ) { none ( ) }
436+ }
437+
438+ private class ImplicitLocalVariable extends LocalVariableImpl instanceof LocalNameBindingOutput:: ImplicitLocal
439+ {
440+ AstNode scope ;
441+ string name ;
442+
443+ ImplicitLocalVariable ( ) {
415444 // For implicitly-declared locals we can't expect to find a binding. Check 'implicitDeclInScope' directly.
416- exists ( AstNode scope , string name |
417- this .( LocalNameBindingOutput:: ImplicitLocal ) .hasNameAndScope ( name , scope ) and
418- LocalNameBindingInput:: implicitDeclInScope ( name , scope , true )
419- )
445+ super .hasNameAndScope ( name , scope ) and
446+ LocalNameBindingInput:: implicitDeclInScope ( name , scope , true )
420447 }
421448
422- /** Gets the callable containing the declaration of this local variable. */
423- Callable getDeclaringCallable ( ) {
424- result = this .getABinding ( ) .getEnclosingCallable ( )
449+ override Callable getDeclaringCallable ( ) {
450+ result = scope
425451 or
426- exists ( AstNode scope | scope = this .( LocalNameBindingOutput:: ImplicitLocal ) .getScope ( ) |
427- result = scope
428- or
429- not scope instanceof Callable and
430- result = scope .getEnclosingCallable ( )
431- )
452+ not scope instanceof Callable and
453+ result = scope .getEnclosingCallable ( )
432454 }
433455
434- /** Holds if this local variable is captured, that is, it is accessed from another callable than the one declaring it. */
435- predicate isCaptured ( ) {
436- this . getAnAccess ( ) . getEnclosingCallable ( ) != this . getDeclaringCallable ( )
456+ override predicate isImplicitReceiverParameter ( Callable c ) {
457+ name = any ( NameBindingPlugin p ) . getImplicitReceiverParameterName ( scope ) and
458+ scope = c
437459 }
438460 }
439461
0 commit comments