mirror of
https://github.com/github/codeql.git
synced 2026-02-20 17:03:41 +01:00
Remove VariableScope IPA type
This commit is contained in:
@@ -5,20 +5,7 @@ private import codeql.Locations
|
||||
private import internal.Variable
|
||||
|
||||
/** A scope in which variables can be declared. */
|
||||
class VariableScope extends TScope {
|
||||
VariableScope::Range range;
|
||||
|
||||
VariableScope() { range = this }
|
||||
|
||||
/** Gets a textual representation of this element. */
|
||||
final string toString() { result = range.toString() }
|
||||
|
||||
/** Gets the program element this scope is associated with, if any. */
|
||||
final AstNode getScopeElement() { result = range.getScopeElement() }
|
||||
|
||||
/** Gets the location of the program element this scope is associated with. */
|
||||
final Location getLocation() { result = getScopeElement().getLocation() }
|
||||
|
||||
class VariableScope extends Scope {
|
||||
/** Gets a variable that is declared in this scope. */
|
||||
final Variable getAVariable() { result.getDeclaringScope() = this }
|
||||
|
||||
@@ -27,9 +14,6 @@ class VariableScope extends TScope {
|
||||
result = this.getAVariable() and
|
||||
result.getName() = name
|
||||
}
|
||||
|
||||
/** Gets the scope in which this scope is nested, if any. */
|
||||
VariableScope getOuterScope() { result = enclosingScope(this.getScopeElement()) }
|
||||
}
|
||||
|
||||
/** A variable declared in a scope. */
|
||||
|
||||
@@ -7,78 +7,37 @@ private import codeql_ruby.ast.internal.Method
|
||||
private import codeql_ruby.ast.internal.Module
|
||||
private import codeql_ruby.ast.internal.Pattern
|
||||
private import codeql_ruby.ast.internal.Parameter
|
||||
|
||||
Generated::AstNode parentOf(Generated::AstNode n) {
|
||||
exists(Generated::AstNode parent | parent = n.getParent() |
|
||||
if
|
||||
n =
|
||||
[
|
||||
parent.(Generated::Module).getName(), parent.(Generated::Class).getName(),
|
||||
parent.(Generated::Class).getSuperclass(), parent.(Generated::SingletonClass).getValue(),
|
||||
parent.(Generated::Method).getName(), parent.(Generated::SingletonMethod).getName(),
|
||||
parent.(Generated::SingletonMethod).getObject()
|
||||
]
|
||||
then result = parent.getParent()
|
||||
else result = parent
|
||||
)
|
||||
}
|
||||
|
||||
private Generated::AstNode parentOfNoScope(Generated::AstNode n) {
|
||||
result = parentOf(n) and
|
||||
not n = any(VariableScope::Range s).getScopeElement()
|
||||
}
|
||||
private import codeql_ruby.ast.internal.Scope
|
||||
|
||||
private predicate instanceVariableAccess(
|
||||
Generated::InstanceVariable var, string name, VariableScope scope, boolean instance
|
||||
Generated::InstanceVariable var, string name, Scope::Range scope, boolean instance
|
||||
) {
|
||||
name = var.getValue() and
|
||||
scope = enclosingModuleOrClass(var) and
|
||||
if hasEnclosingMethod(var) then instance = true else instance = false
|
||||
}
|
||||
|
||||
private predicate classVariableAccess(Generated::ClassVariable var, string name, VariableScope scope) {
|
||||
private predicate classVariableAccess(Generated::ClassVariable var, string name, Scope::Range scope) {
|
||||
name = var.getValue() and
|
||||
scope = enclosingModuleOrClass(var)
|
||||
}
|
||||
|
||||
predicate hasEnclosingMethod(Generated::AstNode node) {
|
||||
exists(Callable::Range method |
|
||||
parentCallableScope*(enclosingScope(node)) = TCallableScope(method)
|
||||
|
|
||||
method instanceof Method::Range or
|
||||
method instanceof SingletonMethod::Range
|
||||
)
|
||||
private predicate hasEnclosingMethod(Generated::AstNode node) {
|
||||
exists(Scope::Range s | node = s.getADescendant() and exists(s.getEnclosingMethod()))
|
||||
}
|
||||
|
||||
private TCallableScope parentCallableScope(TCallableScope scope) {
|
||||
exists(Callable::Range c |
|
||||
scope = TCallableScope(c) and
|
||||
not c instanceof Method::Range and
|
||||
not c instanceof SingletonMethod::Range
|
||||
|
|
||||
result = scope.(VariableScope::Range).getOuterScope()
|
||||
)
|
||||
private ModuleBase::Range enclosingModuleOrClass(Generated::AstNode node) {
|
||||
exists(Scope::Range s | node = s.getADescendant() and result = s.getEnclosingModule())
|
||||
}
|
||||
|
||||
private VariableScope::Range parentScope(VariableScope::Range scope) {
|
||||
not scope instanceof ModuleOrClassScope and
|
||||
result = scope.getOuterScope()
|
||||
}
|
||||
|
||||
private ModuleOrClassScope enclosingModuleOrClass(Generated::AstNode node) {
|
||||
result = parentScope*(enclosingScope(node))
|
||||
}
|
||||
|
||||
private predicate parameterAssignment(
|
||||
CallableScope::Range scope, string name, Generated::Identifier i
|
||||
) {
|
||||
implicitParameterAssignmentNode(i, scope.getScopeElement()) and
|
||||
private predicate parameterAssignment(Callable::Range scope, string name, Generated::Identifier i) {
|
||||
implicitParameterAssignmentNode(i, scope) and
|
||||
name = i.getValue()
|
||||
}
|
||||
|
||||
/** Holds if `scope` defines `name` in its parameter declaration at `i`. */
|
||||
private predicate scopeDefinesParameterVariable(
|
||||
CallableScope::Range scope, string name, Generated::Identifier i
|
||||
Callable::Range scope, string name, Generated::Identifier i
|
||||
) {
|
||||
// In case of overlapping parameter names (e.g. `_`), only the first
|
||||
// parameter will give rise to a variable
|
||||
@@ -90,7 +49,7 @@ private predicate scopeDefinesParameterVariable(
|
||||
)
|
||||
or
|
||||
exists(Parameter::Range p |
|
||||
p = scope.getScopeElement().(Callable::Range).getParameter(_) and
|
||||
p = scope.(Callable::Range).getParameter(_) and
|
||||
name = p.(NamedParameter::Range).getName()
|
||||
|
|
||||
i = p.(Generated::BlockParameter).getName() or
|
||||
@@ -102,7 +61,7 @@ private predicate scopeDefinesParameterVariable(
|
||||
}
|
||||
|
||||
/** Holds if `name` is assigned in `scope` at `i`. */
|
||||
private predicate scopeAssigns(VariableScope scope, string name, Generated::Identifier i) {
|
||||
private predicate scopeAssigns(Scope::Range scope, string name, Generated::Identifier i) {
|
||||
(explicitAssignmentNode(i, _) or implicitAssignmentNode(i)) and
|
||||
name = i.getValue() and
|
||||
scope = enclosingScope(i)
|
||||
@@ -137,9 +96,7 @@ cached
|
||||
private module Cached {
|
||||
/** Gets the enclosing scope for `node`. */
|
||||
cached
|
||||
VariableScope::Range enclosingScope(Generated::AstNode node) {
|
||||
result.getScopeElement() = parentOfNoScope*(parentOf(node))
|
||||
}
|
||||
Scope::Range enclosingScope(Generated::AstNode node) { result.getADescendant() = node }
|
||||
|
||||
cached
|
||||
newtype TScope =
|
||||
@@ -154,7 +111,7 @@ private module Cached {
|
||||
cached
|
||||
newtype TVariable =
|
||||
TGlobalVariable(string name) { name = any(Generated::GlobalVariable var).getValue() } or
|
||||
TClassVariable(VariableScope scope, string name, Generated::AstNode decl) {
|
||||
TClassVariable(Scope::Range scope, string name, Generated::AstNode decl) {
|
||||
decl =
|
||||
min(Generated::ClassVariable other |
|
||||
classVariableAccess(other, name, scope)
|
||||
@@ -162,7 +119,7 @@ private module Cached {
|
||||
other order by other.getLocation().getStartLine(), other.getLocation().getStartColumn()
|
||||
)
|
||||
} or
|
||||
TInstanceVariable(VariableScope scope, string name, boolean instance, Generated::AstNode decl) {
|
||||
TInstanceVariable(Scope::Range scope, string name, boolean instance, Generated::AstNode decl) {
|
||||
decl =
|
||||
min(Generated::InstanceVariable other |
|
||||
instanceVariableAccess(other, name, scope, instance)
|
||||
@@ -170,7 +127,7 @@ private module Cached {
|
||||
other order by other.getLocation().getStartLine(), other.getLocation().getStartColumn()
|
||||
)
|
||||
} or
|
||||
TLocalVariable(VariableScope::Range scope, string name, Generated::Identifier i) {
|
||||
TLocalVariable(Scope::Range scope, string name, Generated::Identifier i) {
|
||||
scopeDefinesParameterVariable(scope, name, i)
|
||||
or
|
||||
i =
|
||||
@@ -180,7 +137,7 @@ private module Cached {
|
||||
other order by other.getLocation().getStartLine(), other.getLocation().getStartColumn()
|
||||
) and
|
||||
not scopeDefinesParameterVariable(scope, name, _) and
|
||||
not scope.inherits(name, _)
|
||||
not inherits(scope, name, _)
|
||||
}
|
||||
|
||||
// Db types that can be vcalls
|
||||
@@ -330,10 +287,12 @@ private module Cached {
|
||||
}
|
||||
|
||||
cached
|
||||
predicate access(Generated::Identifier access, Variable variable) {
|
||||
exists(string name | name = access.getValue() |
|
||||
variable.getDeclaringScope() = enclosingScope(access) and
|
||||
predicate access(Generated::Identifier access, Variable::Range variable) {
|
||||
exists(string name |
|
||||
variable.getName() = name and
|
||||
name = access.getValue()
|
||||
|
|
||||
variable.getDeclaringScope() = enclosingScope(access) and
|
||||
not strictlyBefore(access.getLocation(), variable.getLocation()) and
|
||||
// In case of overlapping parameter names, later parameters should not
|
||||
// be considered accesses to the first parameter
|
||||
@@ -341,9 +300,9 @@ private module Cached {
|
||||
then scopeDefinesParameterVariable(_, _, access)
|
||||
else any()
|
||||
or
|
||||
exists(VariableScope declScope |
|
||||
variable = declScope.getVariable(name) and
|
||||
enclosingScope(access).inherits(name, declScope)
|
||||
exists(Scope::Range declScope |
|
||||
variable.getDeclaringScope() = declScope and
|
||||
inherits(enclosingScope(access), name, declScope)
|
||||
)
|
||||
)
|
||||
}
|
||||
@@ -371,7 +330,7 @@ private module Cached {
|
||||
|
||||
cached
|
||||
predicate instanceVariableAccess(Generated::InstanceVariable var, InstanceVariable v) {
|
||||
exists(string name, VariableScope scope, boolean instance |
|
||||
exists(string name, Scope::Range scope, boolean instance |
|
||||
v = TInstanceVariable(scope, name, instance, _) and
|
||||
instanceVariableAccess(var, name, scope, instance)
|
||||
)
|
||||
@@ -379,7 +338,7 @@ private module Cached {
|
||||
|
||||
cached
|
||||
predicate classVariableAccess(Generated::ClassVariable var, ClassVariable variable) {
|
||||
exists(VariableScope scope, string name |
|
||||
exists(Scope::Range scope, string name |
|
||||
variable = TClassVariable(scope, name, _) and
|
||||
classVariableAccess(var, name, scope)
|
||||
)
|
||||
@@ -388,125 +347,22 @@ private module Cached {
|
||||
|
||||
import Cached
|
||||
|
||||
module VariableScope {
|
||||
abstract class Range extends TScope {
|
||||
abstract string toString();
|
||||
|
||||
abstract Generated::AstNode getScopeElement();
|
||||
|
||||
abstract predicate isCapturing();
|
||||
|
||||
VariableScope::Range getOuterScope() { result = enclosingScope(this.getScopeElement()) }
|
||||
|
||||
/** Holds if this scope inherits `name` from an outer scope `outer`. */
|
||||
predicate inherits(string name, VariableScope::Range outer) {
|
||||
this.isCapturing() and
|
||||
not scopeDefinesParameterVariable(this, name, _) and
|
||||
(
|
||||
outer = this.getOuterScope() and
|
||||
(
|
||||
scopeDefinesParameterVariable(outer, name, _)
|
||||
or
|
||||
exists(Generated::Identifier i |
|
||||
scopeAssigns(outer, name, i) and
|
||||
strictlyBefore(i.getLocation(), this.getLocation())
|
||||
)
|
||||
)
|
||||
or
|
||||
this.getOuterScope().inherits(name, outer)
|
||||
/** Holds if this scope inherits `name` from an outer scope `outer`. */
|
||||
private predicate inherits(Block::Range scope, string name, Scope::Range outer) {
|
||||
not scopeDefinesParameterVariable(scope, name, _) and
|
||||
(
|
||||
outer = scope.getOuterScope() and
|
||||
(
|
||||
scopeDefinesParameterVariable(outer, name, _)
|
||||
or
|
||||
exists(Generated::Identifier i |
|
||||
scopeAssigns(outer, name, i) and
|
||||
strictlyBefore(i.getLocation(), scope.(Generated::AstNode).getLocation())
|
||||
)
|
||||
}
|
||||
|
||||
final Location getLocation() { result = getScopeElement().getLocation() }
|
||||
}
|
||||
}
|
||||
|
||||
module GlobalScope {
|
||||
class Range extends VariableScope::Range, TGlobalScope {
|
||||
override string toString() { result = "global scope" }
|
||||
|
||||
override Generated::AstNode getScopeElement() { none() }
|
||||
|
||||
override predicate isCapturing() { none() }
|
||||
}
|
||||
}
|
||||
|
||||
module TopLevelScope {
|
||||
class Range extends VariableScope::Range, TTopLevelScope {
|
||||
Generated::Program program;
|
||||
|
||||
Range() { TTopLevelScope(program) = this }
|
||||
|
||||
override string toString() {
|
||||
result = "top-level scope for " + program.getLocation().getFile().getBaseName()
|
||||
}
|
||||
|
||||
override Generated::AstNode getScopeElement() { result = program }
|
||||
|
||||
override predicate isCapturing() { none() }
|
||||
}
|
||||
}
|
||||
|
||||
module ModuleScope {
|
||||
class Range extends VariableScope::Range, TModuleScope {
|
||||
Generated::Module mdl;
|
||||
|
||||
Range() { TModuleScope(mdl) = this }
|
||||
|
||||
override string toString() { result = "module scope for " + mdl.(Module::Range).getName() }
|
||||
|
||||
override Generated::AstNode getScopeElement() { result = mdl }
|
||||
|
||||
override predicate isCapturing() { none() }
|
||||
}
|
||||
}
|
||||
|
||||
module ClassScope {
|
||||
class Range extends VariableScope::Range, TClassScope {
|
||||
Generated::AstNode cls;
|
||||
|
||||
Range() { TClassScope(cls) = this }
|
||||
|
||||
override string toString() {
|
||||
result = "class scope for " + cls.(Class::Range).getName()
|
||||
or
|
||||
cls instanceof Generated::SingletonClass and result = "class scope"
|
||||
}
|
||||
|
||||
override Generated::AstNode getScopeElement() { result = cls }
|
||||
|
||||
override predicate isCapturing() { none() }
|
||||
}
|
||||
}
|
||||
|
||||
module CallableScope {
|
||||
class Range extends VariableScope::Range, TCallableScope {
|
||||
private Generated::AstNode c;
|
||||
|
||||
Range() { this = TCallableScope(c) }
|
||||
|
||||
override string toString() {
|
||||
result = "method scope for " + c.(SingletonMethod).getName()
|
||||
or
|
||||
result = "method scope for " + c.(Method).getName()
|
||||
or
|
||||
c instanceof Lambda and
|
||||
result = "lambda scope"
|
||||
or
|
||||
c instanceof Block and
|
||||
result = "block scope"
|
||||
}
|
||||
|
||||
override Generated::AstNode getScopeElement() { TCallableScope(result) = this }
|
||||
|
||||
override predicate isCapturing() {
|
||||
c instanceof Generated::Lambda
|
||||
or
|
||||
c instanceof Generated::Block
|
||||
or
|
||||
c instanceof Generated::DoBlock
|
||||
}
|
||||
}
|
||||
)
|
||||
or
|
||||
inherits(scope.getOuterScope(), name, outer)
|
||||
)
|
||||
}
|
||||
|
||||
module Variable {
|
||||
@@ -517,13 +373,13 @@ module Variable {
|
||||
|
||||
abstract Location getLocation();
|
||||
|
||||
abstract VariableScope getDeclaringScope();
|
||||
abstract Scope::Range getDeclaringScope();
|
||||
}
|
||||
}
|
||||
|
||||
module LocalVariable {
|
||||
class Range extends Variable::Range, TLocalVariable {
|
||||
private VariableScope scope;
|
||||
private Scope::Range scope;
|
||||
private string name;
|
||||
private Generated::Identifier i;
|
||||
|
||||
@@ -533,7 +389,7 @@ module LocalVariable {
|
||||
|
||||
final override Location getLocation() { result = i.getLocation() }
|
||||
|
||||
final override VariableScope getDeclaringScope() { result = scope }
|
||||
final override Scope::Range getDeclaringScope() { result = scope }
|
||||
|
||||
final VariableAccess getDefiningAccess() { result = getNodeForIdentifier(i) }
|
||||
}
|
||||
@@ -549,7 +405,7 @@ module GlobalVariable {
|
||||
|
||||
final override Location getLocation() { none() }
|
||||
|
||||
final override VariableScope getDeclaringScope() { result = TGlobalScope() }
|
||||
final override Scope::Range getDeclaringScope() { none() }
|
||||
}
|
||||
}
|
||||
|
||||
@@ -557,7 +413,7 @@ private class ModuleOrClassScope = TClassScope or TModuleScope or TTopLevelScope
|
||||
|
||||
module InstanceVariable {
|
||||
class Range extends Variable::Range, TInstanceVariable {
|
||||
private ModuleOrClassScope scope;
|
||||
private ModuleBase::Range scope;
|
||||
private boolean instance;
|
||||
private string name;
|
||||
private Generated::AstNode decl;
|
||||
@@ -570,13 +426,13 @@ module InstanceVariable {
|
||||
|
||||
final override Location getLocation() { result = decl.getLocation() }
|
||||
|
||||
final override VariableScope getDeclaringScope() { result = scope }
|
||||
final override Scope::Range getDeclaringScope() { result = scope }
|
||||
}
|
||||
}
|
||||
|
||||
module ClassVariable {
|
||||
class Range extends Variable::Range, TClassVariable {
|
||||
private ModuleOrClassScope scope;
|
||||
private ModuleBase::Range scope;
|
||||
private string name;
|
||||
private Generated::AstNode decl;
|
||||
|
||||
@@ -586,7 +442,7 @@ module ClassVariable {
|
||||
|
||||
final override Location getLocation() { result = decl.getLocation() }
|
||||
|
||||
final override VariableScope getDeclaringScope() { result = scope }
|
||||
final override Scope::Range getDeclaringScope() { result = scope }
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
Reference in New Issue
Block a user