@@ -19,8 +19,6 @@ private class TModuleLike = TToplevel or TModuleDeclaration or TClassDeclaration
1919
2020private class TScopeReal = TMethodBase or TModuleLike or TDoBlock or TLambda or TBraceBlock ;
2121
22- private class TScopeSynth = TBlockSynth ;
23-
2422module Scope {
2523 class TypeRange = Callable:: TypeRange or ModuleBase:: TypeRange or @ruby_end_block;
2624
@@ -108,35 +106,74 @@ Ruby::HeredocBody getHereDocBody(Ruby::HeredocBeginning g) {
108106 )
109107}
110108
109+ private Ruby:: AstNode specialParentOf ( Ruby:: AstNode n ) {
110+ n =
111+ [
112+ result .( Ruby:: Module ) .getName ( ) , result .( Ruby:: Class ) .getName ( ) ,
113+ result .( Ruby:: Class ) .getSuperclass ( ) , result .( Ruby:: SingletonClass ) .getValue ( ) ,
114+ result .( Ruby:: Method ) .getName ( ) , result .( Ruby:: SingletonMethod ) .getName ( ) ,
115+ result .( Ruby:: SingletonMethod ) .getObject ( )
116+ ]
117+ }
118+
111119private Ruby:: AstNode parentOf ( Ruby:: AstNode n ) {
112120 n = getHereDocBody ( result )
113121 or
114- exists ( Ruby:: AstNode parent | parent = n .getParent ( ) |
115- if
116- n =
117- [
118- parent .( Ruby:: Module ) .getName ( ) , parent .( Ruby:: Class ) .getName ( ) ,
119- parent .( Ruby:: Class ) .getSuperclass ( ) , parent .( Ruby:: SingletonClass ) .getValue ( ) ,
120- parent .( Ruby:: Method ) .getName ( ) , parent .( Ruby:: SingletonMethod ) .getName ( ) ,
121- parent .( Ruby:: SingletonMethod ) .getObject ( )
122- ]
123- then result = parent .getParent ( )
124- else result = parent
125- )
122+ result = specialParentOf ( n ) .getParent ( )
123+ or
124+ not exists ( specialParentOf ( n ) ) and
125+ result = n .getParent ( )
126126}
127127
128- /** Gets the enclosing scope of a node */
129- cached
130- Scope:: Range scopeOf ( Ruby:: AstNode n ) {
131- exists ( Ruby:: AstNode p | p = parentOf ( n ) |
132- p = result
128+ private AstNode specialParentOfInclSynth ( AstNode n ) {
129+ n =
130+ [
131+ result .( Namespace ) .getScopeExpr ( ) , result .( ClassDeclaration ) .getSuperclassExpr ( ) ,
132+ result .( SingletonMethod ) .getObject ( )
133+ ]
134+ }
135+
136+ private AstNode parentOfInclSynth ( AstNode n ) {
137+ (
138+ result = specialParentOfInclSynth ( n ) .getParent ( )
133139 or
134- not p instanceof Scope:: Range and result = scopeOf ( p )
135- )
140+ not exists ( specialParentOfInclSynth ( n ) ) and
141+ result = n .getParent ( )
142+ ) and
143+ ( synthChild ( _, _, n ) implies synthChild ( result , _, n ) )
144+ }
145+
146+ cached
147+ private module Cached {
148+ /** Gets the enclosing scope of a node */
149+ cached
150+ Scope:: Range scopeOf ( Ruby:: AstNode n ) {
151+ exists ( Ruby:: AstNode p | p = parentOf ( n ) |
152+ p = result
153+ or
154+ not p instanceof Scope:: Range and result = scopeOf ( p )
155+ )
156+ }
157+
158+ /**
159+ * Gets the enclosing scope of a node. Unlike `scopeOf`, this predicate
160+ * operates on the external AST API, and therefore takes synthesized nodes
161+ * and synthesized scopes into account.
162+ */
163+ cached
164+ Scope scopeOfInclSynth ( AstNode n ) {
165+ exists ( AstNode p | p = parentOfInclSynth ( n ) |
166+ p = result
167+ or
168+ not p instanceof Scope and result = scopeOfInclSynth ( p )
169+ )
170+ }
136171}
137172
173+ import Cached
174+
138175abstract class ScopeImpl extends AstNode , TScopeType {
139- abstract Scope getOuterScopeImpl ( ) ;
176+ final Scope getOuterScopeImpl ( ) { result = scopeOfInclSynth ( this ) }
140177
141178 abstract Variable getAVariableImpl ( ) ;
142179
@@ -151,8 +188,6 @@ private class ScopeRealImpl extends ScopeImpl, TScopeReal {
151188
152189 ScopeRealImpl ( ) { range = toGenerated ( this ) }
153190
154- override Scope getOuterScopeImpl ( ) { toGenerated ( result ) = range .getOuterScope ( ) }
155-
156191 override Variable getAVariableImpl ( ) { result .getDeclaringScope ( ) = this }
157192}
158193
@@ -161,17 +196,15 @@ private class ScopeRealImpl extends ScopeImpl, TScopeReal {
161196// in practice there is not a real nested scope created, so variables that
162197// may appear to be local to the loop body (e.g. the iteration variable) are
163198// scoped to the outer scope rather than the loop body.
164- private class ScopeSynthImpl extends ScopeImpl , TScopeSynth {
165- ScopeSynthImpl ( ) { this = TBlockSynth ( _, _) }
166-
167- override Scope getOuterScopeImpl ( ) { scopeOf ( toGeneratedInclSynth ( this ) ) = toGenerated ( result ) }
199+ private class ScopeSynthImpl extends ScopeImpl , TBraceBlockSynth {
200+ ScopeSynthImpl ( ) { this = TBraceBlockSynth ( _, _) }
168201
169202 override Variable getAVariableImpl ( ) {
170203 // Synthesized variables introduced as parameters to this scope
171204 // As this variable is also synthetic, it is genuinely local to this scope.
172- exists ( SimpleParameter p | p = TSimpleParameterSynth ( this , _ ) |
173- p . getVariable ( ) = result and
174- exists ( TLocalVariableAccessSynth ( p , _ , result ) )
205+ exists ( SimpleParameterSynthImpl p |
206+ p = TSimpleParameterSynth ( this , _ ) and
207+ p . getVariableImpl ( ) = result
175208 )
176209 }
177210}
0 commit comments