From b2483069e041cc52a382b2037faa13f084be12e8 Mon Sep 17 00:00:00 2001 From: Tom Hvitved Date: Wed, 2 Dec 2020 09:11:43 +0100 Subject: [PATCH] Add `Pattern::getAVariable()` and use `self` range field througout --- ql/src/codeql_ruby/ast/Method.qll | 33 ++++++++------------- ql/src/codeql_ruby/ast/Parameter.qll | 15 +++++----- ql/src/codeql_ruby/ast/Pattern.qll | 17 ++++++----- ql/src/codeql_ruby/ast/Variable.qll | 24 ++++++++------- ql/src/codeql_ruby/ast/internal/Method.qll | 24 +++++++++++---- ql/src/codeql_ruby/ast/internal/Pattern.qll | 19 ++++++++---- 6 files changed, 78 insertions(+), 54 deletions(-) diff --git a/ql/src/codeql_ruby/ast/Method.qll b/ql/src/codeql_ruby/ast/Method.qll index 47cf9d36f09..f674c6540ec 100644 --- a/ql/src/codeql_ruby/ast/Method.qll +++ b/ql/src/codeql_ruby/ast/Method.qll @@ -4,7 +4,9 @@ private import internal.Method /** A callable. */ class Callable extends AstNode { - Callable() { this instanceof CallableRange } + CallableRange self; + + Callable() { self = this } /** Gets the number of parameters of this callable. */ final int getNumberOfParameters() { result = count(this.getAParameter()) } @@ -12,12 +14,13 @@ class Callable extends AstNode { /** Gets a parameter of this callable. */ final Parameter getAParameter() { result = this.getParameter(_) } - /** Gets the nth parameter of this callable. */ - final Parameter getParameter(int n) { result = this.(CallableRange).getParameter(n) } + /** Gets the `n`th parameter of this callable. */ + final Parameter getParameter(int n) { result = self.getParameter(n) } } /** A method. */ class Method extends Callable, @method { + final override MethodRange self; final override Generated::Method generated; final override string describeQlClass() { result = "Method" } @@ -25,12 +28,7 @@ class Method extends Callable, @method { final override string toString() { result = this.getName() } /** Gets the name of this method. */ - final string getName() { - result = generated.getName().(Generated::Token).getValue() or - // TODO: use hand-written Symbol class - result = generated.getName().(Generated::Symbol).toString() or - result = generated.getName().(Generated::Setter).getName().getValue() + "=" - } + final string getName() { result = self.getName() } /** * Holds if this is a setter method, as in the following example: @@ -47,19 +45,14 @@ class Method extends Callable, @method { /** A singleton method. */ class SingletonMethod extends Callable, @singleton_method { - final override Generated::SingletonMethod generated; + final override SingletonMethodRange self; final override string describeQlClass() { result = "SingletonMethod" } final override string toString() { result = this.getName() } /** Gets the name of this method. */ - final string getName() { - result = generated.getName().(Generated::Token).getValue() or - // TODO: use hand-written Symbol class - result = generated.getName().(Generated::Symbol).toString() or - result = generated.getName().(Generated::Setter).getName().getValue() + "=" - } + final string getName() { result = self.getName() } } /** @@ -69,7 +62,7 @@ class SingletonMethod extends Callable, @singleton_method { * ``` */ class Lambda extends Callable, @lambda { - final override Generated::Lambda generated; + final override LambdaRange self; final override string describeQlClass() { result = "Lambda" } @@ -78,12 +71,12 @@ class Lambda extends Callable, @lambda { /** A block. */ class Block extends AstNode, Callable { - Block() { this instanceof BlockRange } + override BlockRange self; } /** A block enclosed within `do` and `end`. */ class DoBlock extends Block, @do_block { - final override Generated::DoBlock generated; + final override DoBlockRange self; final override string describeQlClass() { result = "DoBlock" } @@ -97,7 +90,7 @@ class DoBlock extends Block, @do_block { * ``` */ class BraceBlock extends Block, @block { - final override Generated::Block generated; + final override BraceBlockRange self; final override string describeQlClass() { result = "BraceBlock" } diff --git a/ql/src/codeql_ruby/ast/Parameter.qll b/ql/src/codeql_ruby/ast/Parameter.qll index 87be195530b..4435858b7bd 100644 --- a/ql/src/codeql_ruby/ast/Parameter.qll +++ b/ql/src/codeql_ruby/ast/Parameter.qll @@ -1,6 +1,7 @@ import codeql_ruby.AST private import Variable private import Pattern +private import internal.Pattern private import internal.TreeSitter private import internal.Variable @@ -37,15 +38,13 @@ class Parameter extends AstNode { * * This includes both simple parameters and tuple parameters. */ -class PatternParameter extends Parameter, Pattern { } +class PatternParameter extends Parameter, Pattern { + override Variable getAVariable() { result = Pattern.super.getAVariable() } +} /** A parameter defined using a tuple pattern. */ class TuplePatternParameter extends PatternParameter, TuplePattern { final override string describeQlClass() { result = "TuplePatternParameter" } - - final override Variable getAVariable() { - result = this.getAnElement+().(VariablePattern).getVariable() - } } /** A named parameter. */ @@ -58,7 +57,7 @@ class NamedParameter extends Parameter { /** Gets the variable introduced by this parameter. */ Variable getVariable() { none() } - final override Variable getAVariable() { result = this.getVariable() } + override Variable getAVariable() { result = this.getVariable() } /** Gets an access to this parameter. */ final VariableAccess getAnAccess() { result = this.getVariable().getAnAccess() } @@ -66,10 +65,12 @@ class NamedParameter extends Parameter { /** A simple (normal) parameter. */ class SimpleParameter extends NamedParameter, PatternParameter, VariablePattern { - final override string getName() { result = this.getVariableName() } + final override string getName() { result = this.(VariablePatternRange).getVariableName() } final override Variable getVariable() { result = TLocalVariable(_, _, this) } + final override Variable getAVariable() { result = this.getVariable() } + final override string describeQlClass() { result = "SimpleParameter" } final override string toString() { result = this.getName() } diff --git a/ql/src/codeql_ruby/ast/Pattern.qll b/ql/src/codeql_ruby/ast/Pattern.qll index 530a11ea2c7..962e5ccb02b 100644 --- a/ql/src/codeql_ruby/ast/Pattern.qll +++ b/ql/src/codeql_ruby/ast/Pattern.qll @@ -7,20 +7,23 @@ private import Variable /** A pattern. */ class Pattern extends AstNode { - Pattern() { this instanceof PatternRange } + PatternRange self; + + Pattern() { self = this } + + /** Gets a variable used in (or introduced by) this pattern. */ + Variable getAVariable() { result = self.getAVariable() } } /** A simple variable pattern. */ class VariablePattern extends Pattern { + final override VariablePatternRange self; final override Generated::Identifier generated; - /** Gets the name of the variable used in this pattern. */ - final string getVariableName() { result = generated.getValue() } - /** Gets the variable used in (or introduced by) this pattern. */ Variable getVariable() { access(this, result) } - override string toString() { result = this.getVariableName() } + override string toString() { result = self.getVariableName() } } /** @@ -29,10 +32,10 @@ class VariablePattern extends Pattern { * This includes both tuple patterns in parameters and assignments. */ class TuplePattern extends Pattern { - TuplePattern() { this instanceof TuplePatternRange } + final override TuplePatternRange self; /** Gets the `i`th pattern in this tuple pattern. */ - final Pattern getElement(int i) { result = this.(TuplePatternRange).getElement(i) } + final Pattern getElement(int i) { result = self.getElement(i) } /** Gets a sub pattern in this tuple pattern. */ final Pattern getAnElement() { result = this.getElement(_) } diff --git a/ql/src/codeql_ruby/ast/Variable.qll b/ql/src/codeql_ruby/ast/Variable.qll index dbc36512d49..22fb6ac0358 100644 --- a/ql/src/codeql_ruby/ast/Variable.qll +++ b/ql/src/codeql_ruby/ast/Variable.qll @@ -7,11 +7,15 @@ private import internal.Variable /** A scope in which variables can be declared. */ class VariableScope extends TScope { + VariableScopeRange self; + + VariableScope() { self = this } + /** Gets a textual representation of this element. */ - final string toString() { result = this.(VariableScopeRange).toString() } + final string toString() { result = self.toString() } /** Gets the program element this scope is associated with, if any. */ - final AstNode getScopeElement() { result = this.(VariableScopeRange).getScopeElement() } + final AstNode getScopeElement() { result = self.getScopeElement() } /** Gets the location of the program element this scope is associated with. */ final Location getLocation() { result = getScopeElement().getLocation() } @@ -28,17 +32,21 @@ class VariableScope extends TScope { /** A variable declared in a scope. */ class Variable extends TVariable { + VariableRange self; + + Variable() { self = this } + /** Gets the name of this variable. */ - final string getName() { result = this.(VariableRange).getName() } + final string getName() { result = self.getName() } /** Gets a textual representation of this variable. */ final string toString() { result = this.getName() } /** Gets the location of this variable. */ - final Location getLocation() { result = this.(VariableRange).getLocation() } + final Location getLocation() { result = self.getLocation() } /** Gets the scope this variable is declared in. */ - final VariableScope getDeclaringScope() { result = this.(VariableRange).getDeclaringScope() } + final VariableScope getDeclaringScope() { result = self.getDeclaringScope() } /** Gets an access to this variable. */ VariableAccess getAnAccess() { result.getVariable() = this } @@ -46,11 +54,7 @@ class Variable extends TVariable { /** A local variable. */ class LocalVariable extends Variable { - private VariableScope scope; - private string name; - private Generated::Identifier i; - - LocalVariable() { this = TLocalVariable(scope, name, i) } + override LocalVariableRange self; final override LocalVariableAccess getAnAccess() { result.getVariable() = this } } diff --git a/ql/src/codeql_ruby/ast/internal/Method.qll b/ql/src/codeql_ruby/ast/internal/Method.qll index 43602e66dd4..dc75ac4ced1 100644 --- a/ql/src/codeql_ruby/ast/internal/Method.qll +++ b/ql/src/codeql_ruby/ast/internal/Method.qll @@ -5,19 +5,33 @@ abstract class CallableRange extends AstNode { abstract Parameter getParameter(int n); } -private class MethodRange extends CallableRange, @method { +class MethodRange extends CallableRange, @method { final override Generated::Method generated; override Parameter getParameter(int n) { result = generated.getParameters().getChild(n) } + + string getName() { + result = generated.getName().(Generated::Token).getValue() or + // TODO: use hand-written Symbol class + result = generated.getName().(Generated::Symbol).toString() or + result = generated.getName().(Generated::Setter).getName().getValue() + "=" + } } -private class SingletonMethodRange extends CallableRange, @singleton_method { +class SingletonMethodRange extends CallableRange, @singleton_method { final override Generated::SingletonMethod generated; override Parameter getParameter(int n) { result = generated.getParameters().getChild(n) } + + string getName() { + result = generated.getName().(Generated::Token).getValue() or + // TODO: use hand-written Symbol class + result = generated.getName().(Generated::Symbol).toString() or + result = generated.getName().(Generated::Setter).getName().getValue() + "=" + } } -private class LambdaRange extends CallableRange, @lambda { +class LambdaRange extends CallableRange, @lambda { final override Generated::Lambda generated; final override Parameter getParameter(int n) { result = generated.getParameters().getChild(n) } @@ -29,13 +43,13 @@ abstract class BlockRange extends CallableRange { final override Parameter getParameter(int n) { result = params.getChild(n) } } -private class DoBlockRange extends BlockRange, @do_block { +class DoBlockRange extends BlockRange, @do_block { final override Generated::DoBlock generated; DoBlockRange() { params = generated.getParameters() } } -private class BraceBlockRange extends BlockRange, @block { +class BraceBlockRange extends BlockRange, @block { final override Generated::Block generated; BraceBlockRange() { params = generated.getParameters() } diff --git a/ql/src/codeql_ruby/ast/internal/Pattern.qll b/ql/src/codeql_ruby/ast/internal/Pattern.qll index eb34db359a5..6210ea6bb10 100644 --- a/ql/src/codeql_ruby/ast/internal/Pattern.qll +++ b/ql/src/codeql_ruby/ast/internal/Pattern.qll @@ -1,5 +1,6 @@ import codeql_ruby.AST private import TreeSitter +private import Variable private import codeql.Locations private predicate tuplePatternNode(Generated::AstNode n, boolean parameter) { @@ -36,30 +37,38 @@ predicate assignment(Generated::Identifier i, boolean parameter) { patternNode(i abstract class PatternRange extends AstNode { PatternRange() { patternNode(this, _) } + + abstract Variable getAVariable(); } -private class VariablePatternRange extends PatternRange { +class VariablePatternRange extends PatternRange { override Generated::Identifier generated; + + string getVariableName() { result = generated.getValue() } + + override Variable getAVariable() { access(this, result) } } abstract class TuplePatternRange extends PatternRange { - abstract Pattern getElement(int i); + abstract PatternRange getElement(int i); + + override Variable getAVariable() { result = this.getElement(_).getAVariable() } } private class ParameterTuplePatternRange extends TuplePatternRange { override Generated::DestructuredParameter generated; - override Pattern getElement(int i) { result = generated.getChild(i) } + override PatternRange getElement(int i) { result = generated.getChild(i) } } private class AssignmentTuplePatternRange extends TuplePatternRange { override Generated::DestructuredLeftAssignment generated; - override Pattern getElement(int i) { result = generated.getChild(i) } + override PatternRange getElement(int i) { result = generated.getChild(i) } } private class AssignmentListPatternRange extends TuplePatternRange { override Generated::LeftAssignmentList generated; - override Pattern getElement(int i) { result = generated.getChild(i) } + override PatternRange getElement(int i) { result = generated.getChild(i) } }