diff --git a/ql/src/codeql_ruby/AST.qll b/ql/src/codeql_ruby/AST.qll index 1ae49cabb0d..a6445d133b9 100644 --- a/ql/src/codeql_ruby/AST.qll +++ b/ql/src/codeql_ruby/AST.qll @@ -1,6 +1,8 @@ import codeql.Locations +import ast.Expr import ast.Method import ast.Parameter +import ast.Operation import ast.Pattern import ast.Variable private import ast.internal.TreeSitter diff --git a/ql/src/codeql_ruby/ast/Expr.qll b/ql/src/codeql_ruby/ast/Expr.qll new file mode 100644 index 00000000000..8102412638a --- /dev/null +++ b/ql/src/codeql_ruby/ast/Expr.qll @@ -0,0 +1,75 @@ +import codeql_ruby.AST +private import codeql_ruby.ast.internal.TreeSitter +private import internal.Expr + +/** + * An expression. + * + * This is the root QL class for all expressions. + */ +class Expr extends AstNode { + Expr::Range range; + + Expr() { this = range } +} + +/** + * A literal. + * + * This is the QL root class for all literals. + */ +class Literal extends Expr { + override Literal::Range range; + + override string toString() { result = this.getValueText() } + + string getValueText() { result = range.getValueText() } +} + +/** + * An integer literal. + * ```rb + * x = 123 + * y = 0xff + * ``` + */ +class IntegerLiteral extends Literal, @token_integer { + final override IntegerLiteral::Range range; + + final override string getAPrimaryQlClass() { result = "IntegerLiteral" } +} + +/** A `nil` literal. */ +class NilLiteral extends Literal, @token_nil { + final override NilLiteral::Range range; + + final override string getAPrimaryQlClass() { result = "NilLiteral" } +} + +/** + * A Boolean literal. + * ```rb + * true + * false + * TRUE + * FALSE + * ``` + */ +class BooleanLiteral extends Literal, BooleanLiteral::DbUnion { + final override BooleanLiteral::Range range; + + final override string getAPrimaryQlClass() { result = "BooleanLiteral" } + + /** Holds if the Boolean literal is `true` or `TRUE`. */ + predicate isTrue() { range.isTrue() } + + /** Holds if the Boolean literal is `false` or `FALSE`. */ + predicate isFalse() { range.isFalse() } +} + +// TODO: expand this. It's a minimal placeholder so we can test `=~` and `!~`. +class RegexLiteral extends Literal, @regex { + final override RegexLiteral::Range range; + + final override string getAPrimaryQlClass() { result = "RegexLiteral" } +} diff --git a/ql/src/codeql_ruby/ast/Operation.qll b/ql/src/codeql_ruby/ast/Operation.qll new file mode 100644 index 00000000000..a853009d1c8 --- /dev/null +++ b/ql/src/codeql_ruby/ast/Operation.qll @@ -0,0 +1,655 @@ +import codeql_ruby.AST +private import internal.Operation + +/** + * An operation. + * + * This is the QL root class for all operations. + */ +class Operation extends Expr { + override Operation::Range range; + + /** Gets the operator of this operation. */ + string getOperator() { result = range.getOperator() } + + /** Gets an operand of this operation. */ + Expr getAnOperand() { result = range.getAnOperand() } +} + +/** A unary operation. */ +class UnaryOperation extends Operation, @unary { + override UnaryOperation::Range range; + + /** Gets the operand of this unary operation. */ + Expr getOperand() { result = range.getOperand() } + + override string toString() { result = this.getOperator() + " ..." } +} + +/** A unary logical operation. */ +class UnaryLogicalOperation extends UnaryOperation { + override UnaryLogicalOperation::Range range; +} + +/** + * A logical NOT operation, using either `!` or `not`. + * ```rb + * !x.nil? + * not params.empty? + * ``` + */ +class NotExpr extends UnaryLogicalOperation, NotExpr::DbUnion { + final override NotExpr::Range range; + + final override string getAPrimaryQlClass() { result = "NotExpr" } +} + +/** A unary arithmetic operation. */ +class UnaryArithmeticOperation extends UnaryOperation { + override UnaryArithmeticOperation::Range range; +} + +/** + * A unary plus expression. + * ```rb + * b = + a; + * ``` + */ +class UnaryPlusExpr extends UnaryArithmeticOperation, @unary_plus { + final override UnaryPlusExpr::Range range; + + final override string getAPrimaryQlClass() { result = "UnaryPlusExpr" } +} + +/** + * A unary minus expression. + * ```rb + * b = - a; + * ``` + */ +class UnaryMinusExpr extends UnaryArithmeticOperation, @unary_minus { + final override UnaryMinusExpr::Range range; + + final override string getAPrimaryQlClass() { result = "UnaryMinusExpr" } +} + +/** A unary bitwise operation. */ +class UnaryBitwiseOperation extends UnaryOperation { + override UnaryBitwiseOperation::Range range; +} + +/** + * A complement (bitwise NOT) expression. + * ```rb + * ~x + * ``` + */ +class ComplementExpr extends UnaryBitwiseOperation, @unary_tilde { + final override ComplementExpr::Range range; + + final override string getAPrimaryQlClass() { result = "ComplementExpr" } +} + +/** + * A call to the special `defined?` operator. + * ```rb + * defined? some_method + * ``` + */ +class DefinedExpr extends UnaryOperation, @unary_definedquestion { + final override DefinedExpr::Range range; + + final override string getAPrimaryQlClass() { result = "DefinedExpr" } +} + +/** A binary operation. */ +class BinaryOperation extends Operation, @binary { + override BinaryOperation::Range range; + + override string toString() { result = "... " + this.getOperator() + " ..." } + + /** Gets the left operand of this binary operation. */ + Expr getLeftOperand() { result = range.getLeftOperand() } + + /** Gets the right operand of this binary operation. */ + Expr getRightOperand() { result = range.getRightOperand() } +} + +/** + * A binary arithmetic operation. + */ +class BinaryArithmeticOperation extends BinaryOperation { + override BinaryArithmeticOperation::Range range; +} + +/** + * An add expression. + * ```rb + * x + 1 + * ``` + */ +class AddExpr extends BinaryArithmeticOperation, @binary_plus { + final override AddExpr::Range range; + + final override string getAPrimaryQlClass() { result = "AddExpr" } +} + +/** + * A subtract expression. + * ```rb + * x - 3 + * ``` + */ +class SubExpr extends BinaryArithmeticOperation, @binary_minus { + final override SubExpr::Range range; + + final override string getAPrimaryQlClass() { result = "SubExpr" } +} + +/** + * A multiply expression. + * ```rb + * x * 10 + * ``` + */ +class MulExpr extends BinaryArithmeticOperation, @binary_star { + final override MulExpr::Range range; + + final override string getAPrimaryQlClass() { result = "MulExpr" } +} + +/** + * A divide expression. + * ```rb + * x / y + * ``` + */ +class DivExpr extends BinaryArithmeticOperation, @binary_slash { + final override DivExpr::Range range; + + final override string getAPrimaryQlClass() { result = "DivExpr" } +} + +/** + * A modulo expression. + * ```rb + * x % 2 + * ``` + */ +class ModuloExpr extends BinaryArithmeticOperation, @binary_percent { + final override ModuloExpr::Range range; + + final override string getAPrimaryQlClass() { result = "ModuloExpr" } +} + +/** + * An exponent expression. + * ```rb + * x ** 2 + * ``` + */ +class ExponentExpr extends BinaryArithmeticOperation, @binary_starstar { + final override ExponentExpr::Range range; + + final override string getAPrimaryQlClass() { result = "ExponentExpr" } +} + +/** + * A binary logical operation. + */ +class BinaryLogicalOperation extends BinaryOperation { + override BinaryLogicalOperation::Range range; +} + +/** + * A logical AND operation, using either `and` or `&&`. + * ```rb + * x and y + * a && b + * ``` + */ +class LogicalAndExpr extends BinaryLogicalOperation, LogicalAndExpr::DbUnion { + final override LogicalAndExpr::Range range; + + final override string getAPrimaryQlClass() { result = "LogicalAndExpr" } +} + +/** + * A logical OR operation, using either `or` or `||`. + * ```rb + * x or y + * a || b + * ``` + */ +class LogicalOrExpr extends BinaryLogicalOperation, LogicalOrExpr::DbUnion { + final override LogicalOrExpr::Range range; + + final override string getAPrimaryQlClass() { result = "LogicalOrExpr" } +} + +/** + * A binary bitwise operation. + */ +class BinaryBitwiseOperation extends BinaryOperation { + override BinaryBitwiseOperation::Range range; +} + +/** + * A left-shift operation. + * ```rb + * x << n + * ``` + */ +class LShiftExpr extends BinaryBitwiseOperation, @binary_langlelangle { + final override LShiftExpr::Range range; + + final override string getAPrimaryQlClass() { result = "LShiftExpr" } +} + +/** + * A right-shift operation. + * ```rb + * x >> n + * ``` + */ +class RShiftExpr extends BinaryBitwiseOperation, @binary_ranglerangle { + final override RShiftExpr::Range range; + + final override string getAPrimaryQlClass() { result = "RShiftExpr" } +} + +/** + * A bitwise AND operation. + * ```rb + * x & 0xff + * ``` + */ +class BitwiseAndExpr extends BinaryBitwiseOperation, @binary_ampersand { + final override BitwiseAndExpr::Range range; + + final override string getAPrimaryQlClass() { result = "BitwiseAndExpr" } +} + +/** + * A bitwise OR operation. + * ```rb + * x | 0x01 + * ``` + */ +class BitwiseOrExpr extends BinaryBitwiseOperation, @binary_pipe { + final override BitwiseOrExpr::Range range; + + final override string getAPrimaryQlClass() { result = "BitwiseOrExpr" } +} + +/** + * An XOR (exclusive OR) operation. + * ```rb + * x ^ y + * ``` + */ +class BitwiseXorExpr extends BinaryBitwiseOperation, @binary_caret { + final override BitwiseXorExpr::Range range; + + final override string getAPrimaryQlClass() { result = "BitwiseXorExpr" } +} + +/** + * A comparison operation. That is, either an equality operation or a + * relational operation. + */ +class ComparisonOperation extends BinaryOperation { + override ComparisonOperation::Range range; +} + +/** + * An equality operation. + */ +class EqualityOperation extends ComparisonOperation { + override EqualityOperation::Range range; +} + +/** + * An equals expression. + * ```rb + * x == y + * ``` + */ +class EqExpr extends EqualityOperation, @binary_equalequal { + final override EqExpr::Range range; + + final override string getAPrimaryQlClass() { result = "EqExpr" } +} + +/** + * A not-equals expression. + * ```rb + * x != y + * ``` + */ +class NEExpr extends EqualityOperation, @binary_bangequal { + final override NEExpr::Range range; + + final override string getAPrimaryQlClass() { result = "NEExpr" } +} + +/** + * A case-equality (or 'threequals') expression. + * ```rb + * String === "foo" + * ``` + */ +class CaseEqExpr extends EqualityOperation, @binary_equalequalequal { + final override CaseEqExpr::Range range; + + final override string getAPrimaryQlClass() { result = "CaseEqExpr" } +} + +/** + * A relational operation, that is, one of `<=`, `<`, `>`, or `>=`. + */ +class RelationalOperation extends ComparisonOperation { + override RelationalOperation::Range range; + + Expr getGreaterOperand() { result = range.getGreaterOperand() } + + Expr getLesserOperand() { result = range.getLesserOperand() } +} + +/** + * A greater-than expression. + * ```rb + * x > 0 + * ``` + */ +class GTExpr extends RelationalOperation, @binary_rangle { + final override GTExpr::Range range; + + final override string getAPrimaryQlClass() { result = "GTExpr" } +} + +/** + * A greater-than-or-equal expression. + * ```rb + * x >= 0 + * ``` + */ +class GEExpr extends RelationalOperation, @binary_rangleequal { + final override GEExpr::Range range; + + final override string getAPrimaryQlClass() { result = "GEExpr" } +} + +/** + * A less-than expression. + * ```rb + * x < 10 + * ``` + */ +class LTExpr extends RelationalOperation, @binary_langle { + final override LTExpr::Range range; + + final override string getAPrimaryQlClass() { result = "LTExpr" } +} + +/** + * A less-than-or-equal expression. + * ```rb + * x <= 10 + * ``` + */ +class LEExpr extends RelationalOperation, @binary_langleequal { + final override LEExpr::Range range; + + final override string getAPrimaryQlClass() { result = "LEExpr" } +} + +/** + * A three-way comparison ('spaceship') expression. + * ```rb + * a <=> b + * ``` + */ +class SpaceshipExpr extends BinaryOperation, @binary_langleequalrangle { + final override SpaceshipExpr::Range range; + + final override string getAPrimaryQlClass() { result = "SpaceshipExpr" } +} + +/** + * A regex match expression. + * ```rb + * input =~ /\d/ + * ``` + */ +class RegexMatchExpr extends BinaryOperation, @binary_equaltilde { + final override RegexMatchExpr::Range range; + + final override string getAPrimaryQlClass() { result = "RegexMatchExpr" } +} + +/** + * A regex-doesn't-match expression. + * ```rb + * input !~ /\d/ + * ``` + */ +class NoRegexMatchExpr extends BinaryOperation, @binary_bangtilde { + final override NoRegexMatchExpr::Range range; + + final override string getAPrimaryQlClass() { result = "NoRegexMatchExpr" } +} + +/** + * A binary assignment operation, including `=`, `+=`, `&=`, etc. + * + * This is a QL base class for all assignments. + */ +class Assignment extends Operation { + override Assignment::Range range; + + override string toString() { result = "... " + this.getOperator() + " ..." } + + /** Gets the left hand side of this assignment. */ + Expr getLhs() { result = range.getLhs() } + + /** Gets the right hand side of this assignment. */ + Expr getRhs() { result = range.getRhs() } +} + +/** + * An assignment operation with the operator `=`. + * ```rb + * x = 123 + * ``` + */ +class AssignExpr extends Assignment { + override AssignExpr::Range range; + + override string getAPrimaryQlClass() { result = "AssignExpr" } +} + +/** + * A binary assignment operation other than `=`. + */ +class AssignOperation extends Assignment { + override AssignOperation::Range range; +} + +/** + * An arithmetic assignment operation: `+=`, `-=`, `*=`, `/=`, `**=`, and `%=`. + */ +class AssignArithmeticOperation extends AssignOperation { + override AssignArithmeticOperation::Range range; +} + +/** + * A `+=` assignment expression. + * ```rb + * x += 1 + * ``` + */ +class AssignAddExpr extends AssignArithmeticOperation, @operator_assignment_plusequal { + final override AssignAddExpr::Range range; + + final override string getAPrimaryQlClass() { result = "AssignAddExpr" } +} + +/** + * A `-=` assignment expression. + * ```rb + * x -= 3 + * ``` + */ +class AssignSubExpr extends AssignArithmeticOperation, @operator_assignment_minusequal { + final override AssignSubExpr::Range range; + + final override string getAPrimaryQlClass() { result = "AssignSubExpr" } +} + +/** + * A `*=` assignment expression. + * ```rb + * x *= 10 + * ``` + */ +class AssignMulExpr extends AssignArithmeticOperation, @operator_assignment_starequal { + final override AssignMulExpr::Range range; + + final override string getAPrimaryQlClass() { result = "AssignMulExpr" } +} + +/** + * A `/=` assignment expression. + * ```rb + * x /= y + * ``` + */ +class AssignDivExpr extends AssignArithmeticOperation, @operator_assignment_slashequal { + final override AssignDivExpr::Range range; + + final override string getAPrimaryQlClass() { result = "AssignDivExpr" } +} + +/** + * A `%=` assignment expression. + * ```rb + * x %= 4 + * ``` + */ +class AssignModuloExpr extends AssignArithmeticOperation, @operator_assignment_percentequal { + final override AssignModuloExpr::Range range; + + final override string getAPrimaryQlClass() { result = "AssignModuloExpr" } +} + +/** + * A `**=` assignment expression. + * ```rb + * x **= 2 + * ``` + */ +class AssignExponentExpr extends AssignArithmeticOperation, @operator_assignment_starstarequal { + final override AssignExponentExpr::Range range; + + final override string getAPrimaryQlClass() { result = "AssignExponentExpr" } +} + +/** + * A logical assignment operation: `&&=` and `||=`. + */ +class AssignLogicalOperation extends AssignOperation { + override AssignLogicalOperation::Range range; +} + +/** + * A logical AND assignment operation. + * ```rb + * x &&= y.even? + * ``` + */ +class AssignLogicalAndExpr extends AssignLogicalOperation, + @operator_assignment_ampersandampersandequal { + final override AssignLogicalAndExpr::Range range; + + final override string getAPrimaryQlClass() { result = "AssignLogicalAndExpr" } +} + +/** + * A logical OR assignment operation. + * ```rb + * x ||= y + * ``` + */ +class AssignLogicalOrExpr extends AssignLogicalOperation, @operator_assignment_pipepipeequal { + final override AssignLogicalOrExpr::Range range; + + final override string getAPrimaryQlClass() { result = "AssignLogicalOrExpr" } +} + +/** + * A bitwise assignment operation: `<<=`, `>>=`, `&=`, `|=` and `^=`. + */ +class AssignBitwiseOperation extends AssignOperation { + override AssignBitwiseOperation::Range range; +} + +/** + * A left-shift assignment operation. + * ```rb + * x <<= 3 + * ``` + */ +class AssignLShiftExpr extends AssignBitwiseOperation, @operator_assignment_langlelangleequal { + final override AssignLShiftExpr::Range range; + + final override string getAPrimaryQlClass() { result = "AssignLShiftExpr" } +} + +/** + * A right-shift assignment operation. + * ```rb + * x >>= 3 + * ``` + */ +class AssignRShiftExpr extends AssignBitwiseOperation, @operator_assignment_ranglerangleequal { + final override AssignRShiftExpr::Range range; + + final override string getAPrimaryQlClass() { result = "AssignRShiftExpr" } +} + +/** + * A bitwise AND assignment operation. + * ```rb + * x &= 0xff + * ``` + */ +class AssignBitwiseAndExpr extends AssignBitwiseOperation, @operator_assignment_ampersandequal { + final override AssignBitwiseAndExpr::Range range; + + final override string getAPrimaryQlClass() { result = "AssignBitwiseAndExpr" } +} + +/** + * A bitwise OR assignment operation. + * ```rb + * x |= 0x01 + * ``` + */ +class AssignBitwiseOrExpr extends AssignBitwiseOperation, @operator_assignment_pipeequal { + final override AssignBitwiseOrExpr::Range range; + + final override string getAPrimaryQlClass() { result = "AssignBitwiseOrExpr" } +} + +/** + * An XOR (exclusive OR) assignment operation. + * ```rb + * x ^= y + * ``` + */ +class AssignBitwiseXorExpr extends AssignBitwiseOperation, @operator_assignment_caretequal { + final override AssignBitwiseXorExpr::Range range; + + final override string getAPrimaryQlClass() { result = "AssignBitwiseXorExpr" } +} diff --git a/ql/src/codeql_ruby/ast/Variable.qll b/ql/src/codeql_ruby/ast/Variable.qll index 7c590f0613d..a79080c2b2a 100644 --- a/ql/src/codeql_ruby/ast/Variable.qll +++ b/ql/src/codeql_ruby/ast/Variable.qll @@ -60,21 +60,23 @@ class LocalVariable extends Variable { } /** An access to a variable. */ -class VariableAccess extends AstNode, @token_identifier { - override Generated::Identifier generated; - Variable variable; - - VariableAccess() { access(this, variable) } +class VariableAccess extends Expr, @token_identifier { + override VariableAccess::Range range; /** Gets the variable this identifier refers to. */ - Variable getVariable() { result = variable } + Variable getVariable() { result = range.getVariable() } - final override string toString() { result = variable.getName() } + final override string toString() { result = this.getVariable().getName() } + + override string getAPrimaryQlClass() { result = "VariableAccess" } } /** An access to a local variable. */ class LocalVariableAccess extends VariableAccess { - override LocalVariable variable; + final override LocalVariableAccess::Range range; - override LocalVariable getVariable() { result = variable } + /** Gets the variable this identifier refers to. */ + override LocalVariable getVariable() { result = range.getVariable() } + + final override string getAPrimaryQlClass() { result = "LocalVariableAccess" } } diff --git a/ql/src/codeql_ruby/ast/internal/Expr.qll b/ql/src/codeql_ruby/ast/internal/Expr.qll new file mode 100644 index 00000000000..9acf5421730 --- /dev/null +++ b/ql/src/codeql_ruby/ast/internal/Expr.qll @@ -0,0 +1,61 @@ +import codeql_ruby.AST +private import codeql_ruby.ast.internal.TreeSitter + +module Expr { + abstract class Range extends AstNode { } +} + +module Literal { + abstract class Range extends Expr::Range { + abstract string getValueText(); + } +} + +module IntegerLiteral { + class Range extends Literal::Range, @token_integer { + final override Generated::Integer generated; + + final override string getValueText() { result = generated.getValue() } + } +} + +module NilLiteral { + class Range extends Literal::Range, @token_nil { + final override Generated::Nil generated; + + final override string getValueText() { result = generated.getValue() } + } +} + +module BooleanLiteral { + class DbUnion = @token_true or @token_false; + + class Range extends Literal::Range, DbUnion { + final override Generated::Token generated; + + final override string getValueText() { result = generated.getValue() } + + predicate isTrue() { this instanceof @token_true } + + predicate isFalse() { this instanceof @token_false } + } +} + +// TODO: expand this. It's a minimal placeholder so we can test `=~` and `!~`. +module RegexLiteral { + class Range extends Literal::Range, @regex { + final override Generated::Regex generated; + + final override string getValueText() { + result = + concat(AstNode c, int i, string s | + c = generated.getChild(i) and + if c instanceof Generated::Token + then s = c.(Generated::Token).getValue() + else s = "#{...}" + | + s order by i + ) + } + } +} diff --git a/ql/src/codeql_ruby/ast/internal/Operation.qll b/ql/src/codeql_ruby/ast/internal/Operation.qll new file mode 100644 index 00000000000..02e67a0c1a8 --- /dev/null +++ b/ql/src/codeql_ruby/ast/internal/Operation.qll @@ -0,0 +1,314 @@ +import codeql_ruby.AST +private import codeql_ruby.ast.internal.TreeSitter +private import codeql_ruby.ast.internal.Expr + +module Operation { + abstract class Range extends Expr::Range { + abstract string getOperator(); + + abstract Expr getAnOperand(); + } +} + +module UnaryOperation { + abstract class Range extends Operation::Range, @unary { + final override Generated::Unary generated; + + final override string getOperator() { result = generated.getOperator() } + + Expr getOperand() { result = generated.getOperand() } + + final override Expr getAnOperand() { result = this.getOperand() } + } +} + +module UnaryLogicalOperation { + abstract class Range extends UnaryOperation::Range { } +} + +module UnaryArithmeticOperation { + abstract class Range extends UnaryOperation::Range { } +} + +module UnaryBitwiseOperation { + abstract class Range extends UnaryOperation::Range { } +} + +module NotExpr { + class DbUnion = @unary_bang or @unary_not; + + class Range extends UnaryLogicalOperation::Range, DbUnion { } +} + +module UnaryPlusExpr { + class Range extends UnaryArithmeticOperation::Range, @unary_plus { } +} + +module UnaryMinusExpr { + class Range extends UnaryArithmeticOperation::Range, @unary_minus { } +} + +module ComplementExpr { + class Range extends UnaryBitwiseOperation::Range, @unary_tilde { } +} + +module DefinedExpr { + class Range extends UnaryOperation::Range, @unary_definedquestion { } +} + +module BinaryOperation { + abstract class Range extends Operation::Range, @binary { + final override Generated::Binary generated; + + final override string getOperator() { result = generated.getOperator() } + + final Expr getLeftOperand() { result = generated.getLeft() } + + final Expr getRightOperand() { result = generated.getRight() } + + final override Expr getAnOperand() { + result = this.getLeftOperand() or result = this.getRightOperand() + } + } +} + +module BinaryArithmeticOperation { + abstract class Range extends BinaryOperation::Range { } +} + +module BinaryLogicalOperation { + abstract class Range extends BinaryOperation::Range { } +} + +module BinaryBitwiseOperation { + abstract class Range extends BinaryOperation::Range { } +} + +module ComparisonOperation { + abstract class Range extends BinaryOperation::Range, @binary { } +} + +module AddExpr { + class Range extends BinaryArithmeticOperation::Range, @binary_plus { } +} + +module SubExpr { + class Range extends BinaryArithmeticOperation::Range, @binary_minus { } +} + +module MulExpr { + class Range extends BinaryArithmeticOperation::Range, @binary_star { } +} + +module DivExpr { + class Range extends BinaryArithmeticOperation::Range, @binary_slash { } +} + +module ModuloExpr { + class Range extends BinaryArithmeticOperation::Range, @binary_percent { } +} + +module ExponentExpr { + class Range extends BinaryArithmeticOperation::Range, @binary_starstar { } +} + +module LogicalAndExpr { + class DbUnion = @binary_and or @binary_ampersandampersand; + + class Range extends BinaryLogicalOperation::Range, DbUnion { } +} + +module LogicalOrExpr { + class DbUnion = @binary_or or @binary_pipepipe; + + class Range extends BinaryLogicalOperation::Range, DbUnion { } +} + +module LShiftExpr { + class Range extends BinaryBitwiseOperation::Range, @binary_langlelangle { } +} + +module RShiftExpr { + class Range extends BinaryBitwiseOperation::Range, @binary_ranglerangle { } +} + +module BitwiseAndExpr { + class Range extends BinaryBitwiseOperation::Range, @binary_ampersand { } +} + +module BitwiseOrExpr { + class Range extends BinaryBitwiseOperation::Range, @binary_pipe { } +} + +module BitwiseXorExpr { + class Range extends BinaryBitwiseOperation::Range, @binary_caret { } +} + +module EqualityOperation { + abstract class Range extends ComparisonOperation::Range { } +} + +module EqExpr { + class Range extends EqualityOperation::Range, @binary_equalequal { } +} + +module NEExpr { + class Range extends EqualityOperation::Range, @binary_bangequal { } +} + +module CaseEqExpr { + class Range extends EqualityOperation::Range, @binary_equalequalequal { } +} + +module RelationalOperation { + abstract class Range extends ComparisonOperation::Range { + abstract Expr getGreaterOperand(); + + abstract Expr getLesserOperand(); + } +} + +module GTExpr { + class Range extends RelationalOperation::Range, @binary_rangle { + final override Expr getGreaterOperand() { result = this.getLeftOperand() } + + final override Expr getLesserOperand() { result = this.getRightOperand() } + } +} + +module GEExpr { + class Range extends RelationalOperation::Range, @binary_rangleequal { + final override Expr getGreaterOperand() { result = this.getLeftOperand() } + + final override Expr getLesserOperand() { result = this.getRightOperand() } + } +} + +module LTExpr { + class Range extends RelationalOperation::Range, @binary_langle { + final override Expr getGreaterOperand() { result = this.getRightOperand() } + + final override Expr getLesserOperand() { result = this.getLeftOperand() } + } +} + +module LEExpr { + class Range extends RelationalOperation::Range, @binary_langleequal { + final override Expr getGreaterOperand() { result = this.getRightOperand() } + + final override Expr getLesserOperand() { result = this.getLeftOperand() } + } +} + +module SpaceshipExpr { + class Range extends BinaryOperation::Range, @binary_langleequalrangle { } +} + +module RegexMatchExpr { + class Range extends BinaryOperation::Range, @binary_equaltilde { } +} + +module NoRegexMatchExpr { + class Range extends BinaryOperation::Range, @binary_bangtilde { } +} + +module Assignment { + class DbUnion = @operator_assignment or @assignment; + + abstract class Range extends Operation::Range, DbUnion { + abstract Expr getLhs(); + + abstract Expr getRhs(); + + final override Expr getAnOperand() { result = this.getLhs() or result = this.getRhs() } + } +} + +module AssignExpr { + class Range extends Assignment::Range, @assignment { + final override Generated::Assignment generated; + + final override Expr getLhs() { result = generated.getLeft() } + + final override Expr getRhs() { result = generated.getRight() } + + final override string getOperator() { result = "=" } + } +} + +module AssignOperation { + abstract class Range extends Assignment::Range, @operator_assignment { + final override Generated::OperatorAssignment generated; + + final override string getOperator() { result = generated.getOperator() } + + final override Expr getLhs() { result = generated.getLeft() } + + final override Expr getRhs() { result = generated.getRight() } + } +} + +module AssignArithmeticOperation { + abstract class Range extends AssignOperation::Range { } +} + +module AssignLogicalOperation { + abstract class Range extends AssignOperation::Range { } +} + +module AssignBitwiseOperation { + abstract class Range extends AssignOperation::Range { } +} + +module AssignAddExpr { + class Range extends AssignArithmeticOperation::Range, @operator_assignment_plusequal { } +} + +module AssignSubExpr { + class Range extends AssignArithmeticOperation::Range, @operator_assignment_minusequal { } +} + +module AssignMulExpr { + class Range extends AssignArithmeticOperation::Range, @operator_assignment_starequal { } +} + +module AssignDivExpr { + class Range extends AssignArithmeticOperation::Range, @operator_assignment_slashequal { } +} + +module AssignExponentExpr { + class Range extends AssignArithmeticOperation::Range, @operator_assignment_starstarequal { } +} + +module AssignModuloExpr { + class Range extends AssignArithmeticOperation::Range, @operator_assignment_percentequal { } +} + +module AssignLogicalAndExpr { + class Range extends AssignLogicalOperation::Range, @operator_assignment_ampersandampersandequal { + } +} + +module AssignLogicalOrExpr { + class Range extends AssignLogicalOperation::Range, @operator_assignment_pipepipeequal { } +} + +module AssignLShiftExpr { + class Range extends AssignBitwiseOperation::Range, @operator_assignment_langlelangleequal { } +} + +module AssignRShiftExpr { + class Range extends AssignBitwiseOperation::Range, @operator_assignment_ranglerangleequal { } +} + +module AssignBitwiseAndExpr { + class Range extends AssignBitwiseOperation::Range, @operator_assignment_ampersandequal { } +} + +module AssignBitwiseOrExpr { + class Range extends AssignBitwiseOperation::Range, @operator_assignment_pipeequal { } +} + +module AssignBitwiseXorExpr { + class Range extends AssignBitwiseOperation::Range, @operator_assignment_caretequal { } +} diff --git a/ql/src/codeql_ruby/ast/internal/Variable.qll b/ql/src/codeql_ruby/ast/internal/Variable.qll index cdb58383e79..a1fd920231a 100644 --- a/ql/src/codeql_ruby/ast/internal/Variable.qll +++ b/ql/src/codeql_ruby/ast/internal/Variable.qll @@ -1,6 +1,7 @@ -private import codeql_ruby.AST private import TreeSitter private import codeql.Locations +private import codeql_ruby.AST +private import codeql_ruby.ast.internal.Expr private import codeql_ruby.ast.internal.Pattern private Generated::AstNode parent(Generated::AstNode n) { @@ -224,3 +225,22 @@ module LocalVariable { final override VariableScope getDeclaringScope() { result = scope } } } + +module VariableAccess { + class Range extends Expr::Range, @token_identifier { + override Generated::Identifier generated; + Variable variable; + + Range() { access(this, variable) } + + Variable getVariable() { result = variable } + } +} + +module LocalVariableAccess { + class Range extends VariableAccess::Range { + override LocalVariable variable; + + override LocalVariable getVariable() { result = variable } + } +} diff --git a/ql/test/library-tests/ast/operations/assignment.expected b/ql/test/library-tests/ast/operations/assignment.expected new file mode 100644 index 00000000000..d1f34896b31 --- /dev/null +++ b/ql/test/library-tests/ast/operations/assignment.expected @@ -0,0 +1,62 @@ +assignments +| operations.rb:3:1:3:5 | ... = ... | = | operations.rb:3:1:3:1 | a | operations.rb:3:5:3:5 | 0 | AssignExpr | +| operations.rb:4:1:4:5 | ... = ... | = | operations.rb:4:1:4:1 | b | operations.rb:4:5:4:5 | 0 | AssignExpr | +| operations.rb:5:1:5:7 | ... = ... | = | operations.rb:5:1:5:3 | bar | operations.rb:5:7:5:7 | 0 | AssignExpr | +| operations.rb:6:1:6:8 | ... = ... | = | operations.rb:6:1:6:4 | base | operations.rb:6:8:6:8 | 0 | AssignExpr | +| operations.rb:7:1:7:7 | ... = ... | = | operations.rb:7:1:7:3 | baz | operations.rb:7:7:7:7 | 0 | AssignExpr | +| operations.rb:8:1:8:7 | ... = ... | = | operations.rb:8:1:8:3 | foo | operations.rb:8:7:8:7 | 0 | AssignExpr | +| operations.rb:9:1:9:10 | ... = ... | = | operations.rb:9:1:9:6 | handle | operations.rb:9:10:9:10 | 0 | AssignExpr | +| operations.rb:10:1:10:5 | ... = ... | = | operations.rb:10:1:10:1 | m | operations.rb:10:5:10:5 | 0 | AssignExpr | +| operations.rb:11:1:11:8 | ... = ... | = | operations.rb:11:1:11:4 | mask | operations.rb:11:8:11:8 | 0 | AssignExpr | +| operations.rb:12:1:12:5 | ... = ... | = | operations.rb:12:1:12:1 | n | operations.rb:12:5:12:5 | 0 | AssignExpr | +| operations.rb:13:1:13:8 | ... = ... | = | operations.rb:13:1:13:4 | name | operations.rb:13:8:13:8 | 0 | AssignExpr | +| operations.rb:14:1:14:7 | ... = ... | = | operations.rb:14:1:14:3 | num | operations.rb:14:7:14:7 | 0 | AssignExpr | +| operations.rb:15:1:15:9 | ... = ... | = | operations.rb:15:1:15:5 | power | operations.rb:15:9:15:9 | 0 | AssignExpr | +| operations.rb:16:1:16:7 | ... = ... | = | operations.rb:16:1:16:3 | qux | operations.rb:16:7:16:7 | 0 | AssignExpr | +| operations.rb:17:1:17:5 | ... = ... | = | operations.rb:17:1:17:1 | w | operations.rb:17:5:17:5 | 0 | AssignExpr | +| operations.rb:18:1:18:5 | ... = ... | = | operations.rb:18:1:18:1 | x | operations.rb:18:5:18:5 | 0 | AssignExpr | +| operations.rb:19:1:19:5 | ... = ... | = | operations.rb:19:1:19:1 | y | operations.rb:19:5:19:5 | 0 | AssignExpr | +| operations.rb:20:1:20:5 | ... = ... | = | operations.rb:20:1:20:1 | z | operations.rb:20:5:20:5 | 0 | AssignExpr | +| operations.rb:68:1:68:8 | ... += ... | += | operations.rb:68:1:68:1 | x | operations.rb:68:6:68:8 | 128 | AssignAddExpr | +| operations.rb:69:1:69:7 | ... -= ... | -= | operations.rb:69:1:69:1 | y | operations.rb:69:6:69:7 | 32 | AssignSubExpr | +| operations.rb:70:1:70:7 | ... *= ... | *= | operations.rb:70:1:70:1 | a | operations.rb:70:6:70:7 | 12 | AssignMulExpr | +| operations.rb:71:1:71:6 | ... /= ... | /= | operations.rb:71:1:71:1 | b | operations.rb:71:6:71:6 | 4 | AssignDivExpr | +| operations.rb:72:1:72:6 | ... %= ... | %= | operations.rb:72:1:72:1 | z | operations.rb:72:6:72:6 | 2 | AssignModuloExpr | +| operations.rb:73:1:73:11 | ... **= ... | **= | operations.rb:73:1:73:3 | foo | operations.rb:73:9:73:11 | bar | AssignExponentExpr | +| operations.rb:76:2:76:8 | ... &&= ... | &&= | operations.rb:76:2:76:2 | x | operations.rb:76:8:76:8 | y | AssignLogicalAndExpr | +| operations.rb:77:2:77:8 | ... \|\|= ... | \|\|= | operations.rb:77:2:77:2 | a | operations.rb:77:8:77:8 | b | AssignLogicalOrExpr | +| operations.rb:80:2:80:8 | ... <<= ... | <<= | operations.rb:80:2:80:2 | x | operations.rb:80:8:80:8 | 2 | AssignLShiftExpr | +| operations.rb:81:2:81:8 | ... >>= ... | >>= | operations.rb:81:2:81:2 | y | operations.rb:81:8:81:8 | 3 | AssignRShiftExpr | +| operations.rb:82:2:82:12 | ... &= ... | &= | operations.rb:82:2:82:4 | foo | operations.rb:82:9:82:12 | mask | AssignBitwiseAndExpr | +| operations.rb:83:2:83:12 | ... \|= ... | \|= | operations.rb:83:2:83:4 | bar | operations.rb:83:9:83:12 | 0x01 | AssignBitwiseOrExpr | +| operations.rb:84:2:84:11 | ... ^= ... | ^= | operations.rb:84:2:84:4 | baz | operations.rb:84:9:84:11 | qux | AssignBitwiseXorExpr | +assignOperations +| operations.rb:68:1:68:8 | ... += ... | += | operations.rb:68:1:68:1 | x | operations.rb:68:6:68:8 | 128 | AssignAddExpr | +| operations.rb:69:1:69:7 | ... -= ... | -= | operations.rb:69:1:69:1 | y | operations.rb:69:6:69:7 | 32 | AssignSubExpr | +| operations.rb:70:1:70:7 | ... *= ... | *= | operations.rb:70:1:70:1 | a | operations.rb:70:6:70:7 | 12 | AssignMulExpr | +| operations.rb:71:1:71:6 | ... /= ... | /= | operations.rb:71:1:71:1 | b | operations.rb:71:6:71:6 | 4 | AssignDivExpr | +| operations.rb:72:1:72:6 | ... %= ... | %= | operations.rb:72:1:72:1 | z | operations.rb:72:6:72:6 | 2 | AssignModuloExpr | +| operations.rb:73:1:73:11 | ... **= ... | **= | operations.rb:73:1:73:3 | foo | operations.rb:73:9:73:11 | bar | AssignExponentExpr | +| operations.rb:76:2:76:8 | ... &&= ... | &&= | operations.rb:76:2:76:2 | x | operations.rb:76:8:76:8 | y | AssignLogicalAndExpr | +| operations.rb:77:2:77:8 | ... \|\|= ... | \|\|= | operations.rb:77:2:77:2 | a | operations.rb:77:8:77:8 | b | AssignLogicalOrExpr | +| operations.rb:80:2:80:8 | ... <<= ... | <<= | operations.rb:80:2:80:2 | x | operations.rb:80:8:80:8 | 2 | AssignLShiftExpr | +| operations.rb:81:2:81:8 | ... >>= ... | >>= | operations.rb:81:2:81:2 | y | operations.rb:81:8:81:8 | 3 | AssignRShiftExpr | +| operations.rb:82:2:82:12 | ... &= ... | &= | operations.rb:82:2:82:4 | foo | operations.rb:82:9:82:12 | mask | AssignBitwiseAndExpr | +| operations.rb:83:2:83:12 | ... \|= ... | \|= | operations.rb:83:2:83:4 | bar | operations.rb:83:9:83:12 | 0x01 | AssignBitwiseOrExpr | +| operations.rb:84:2:84:11 | ... ^= ... | ^= | operations.rb:84:2:84:4 | baz | operations.rb:84:9:84:11 | qux | AssignBitwiseXorExpr | +assignArithmeticOperations +| operations.rb:68:1:68:8 | ... += ... | += | operations.rb:68:1:68:1 | x | operations.rb:68:6:68:8 | 128 | AssignAddExpr | +| operations.rb:69:1:69:7 | ... -= ... | -= | operations.rb:69:1:69:1 | y | operations.rb:69:6:69:7 | 32 | AssignSubExpr | +| operations.rb:70:1:70:7 | ... *= ... | *= | operations.rb:70:1:70:1 | a | operations.rb:70:6:70:7 | 12 | AssignMulExpr | +| operations.rb:71:1:71:6 | ... /= ... | /= | operations.rb:71:1:71:1 | b | operations.rb:71:6:71:6 | 4 | AssignDivExpr | +| operations.rb:72:1:72:6 | ... %= ... | %= | operations.rb:72:1:72:1 | z | operations.rb:72:6:72:6 | 2 | AssignModuloExpr | +| operations.rb:73:1:73:11 | ... **= ... | **= | operations.rb:73:1:73:3 | foo | operations.rb:73:9:73:11 | bar | AssignExponentExpr | +assignLogicalOperations +| operations.rb:76:2:76:8 | ... &&= ... | &&= | operations.rb:76:2:76:2 | x | operations.rb:76:8:76:8 | y | AssignLogicalAndExpr | +| operations.rb:77:2:77:8 | ... \|\|= ... | \|\|= | operations.rb:77:2:77:2 | a | operations.rb:77:8:77:8 | b | AssignLogicalOrExpr | +assignBitwiseOperations +| operations.rb:80:2:80:8 | ... <<= ... | <<= | operations.rb:80:2:80:2 | x | operations.rb:80:8:80:8 | 2 | AssignLShiftExpr | +| operations.rb:81:2:81:8 | ... >>= ... | >>= | operations.rb:81:2:81:2 | y | operations.rb:81:8:81:8 | 3 | AssignRShiftExpr | +| operations.rb:82:2:82:12 | ... &= ... | &= | operations.rb:82:2:82:4 | foo | operations.rb:82:9:82:12 | mask | AssignBitwiseAndExpr | +| operations.rb:83:2:83:12 | ... \|= ... | \|= | operations.rb:83:2:83:4 | bar | operations.rb:83:9:83:12 | 0x01 | AssignBitwiseOrExpr | +| operations.rb:84:2:84:11 | ... ^= ... | ^= | operations.rb:84:2:84:4 | baz | operations.rb:84:9:84:11 | qux | AssignBitwiseXorExpr | diff --git a/ql/test/library-tests/ast/operations/assignment.ql b/ql/test/library-tests/ast/operations/assignment.ql new file mode 100644 index 00000000000..caa0294d8a5 --- /dev/null +++ b/ql/test/library-tests/ast/operations/assignment.ql @@ -0,0 +1,44 @@ +import ruby + +query predicate assignments(Assignment a, string operator, Expr left, Expr right, string pClass) { + operator = a.getOperator() and + left = a.getLhs() and + right = a.getRhs() and + pClass = a.getAPrimaryQlClass() +} + +query predicate assignOperations( + AssignOperation o, string operator, Expr left, Expr right, string pClass +) { + operator = o.getOperator() and + left = o.getLhs() and + right = o.getRhs() and + pClass = o.getAPrimaryQlClass() +} + +query predicate assignArithmeticOperations( + AssignArithmeticOperation o, string operator, Expr left, Expr right, string pClass +) { + operator = o.getOperator() and + left = o.getLhs() and + right = o.getRhs() and + pClass = o.getAPrimaryQlClass() +} + +query predicate assignLogicalOperations( + AssignLogicalOperation o, string operator, Expr left, Expr right, string pClass +) { + operator = o.getOperator() and + left = o.getLhs() and + right = o.getRhs() and + pClass = o.getAPrimaryQlClass() +} + +query predicate assignBitwiseOperations( + AssignBitwiseOperation o, string operator, Expr left, Expr right, string pClass +) { + operator = o.getOperator() and + left = o.getLhs() and + right = o.getRhs() and + pClass = o.getAPrimaryQlClass() +} diff --git a/ql/test/library-tests/ast/operations/binary.expected b/ql/test/library-tests/ast/operations/binary.expected new file mode 100644 index 00000000000..af7a4ba3198 --- /dev/null +++ b/ql/test/library-tests/ast/operations/binary.expected @@ -0,0 +1,67 @@ +binaryOperations +| operations.rb:31:1:31:7 | ... + ... | + | operations.rb:31:1:31:1 | w | operations.rb:31:5:31:7 | 234 | AddExpr | +| operations.rb:32:1:32:6 | ... - ... | - | operations.rb:32:1:32:1 | x | operations.rb:32:5:32:6 | 17 | SubExpr | +| operations.rb:33:1:33:6 | ... * ... | * | operations.rb:33:1:33:1 | y | operations.rb:33:5:33:6 | 10 | MulExpr | +| operations.rb:34:1:34:5 | ... / ... | / | operations.rb:34:1:34:1 | z | operations.rb:34:5:34:5 | 2 | DivExpr | +| operations.rb:35:1:35:7 | ... % ... | % | operations.rb:35:1:35:3 | num | operations.rb:35:7:35:7 | 2 | ModuloExpr | +| operations.rb:36:1:36:13 | ... ** ... | ** | operations.rb:36:1:36:4 | base | operations.rb:36:9:36:13 | power | ExponentExpr | +| operations.rb:39:1:39:10 | ... && ... | && | operations.rb:39:1:39:3 | foo | operations.rb:39:8:39:10 | bar | LogicalAndExpr | +| operations.rb:40:1:40:11 | ... and ... | and | operations.rb:40:1:40:3 | baz | operations.rb:40:9:40:11 | qux | LogicalAndExpr | +| operations.rb:41:1:41:6 | ... or ... | or | operations.rb:41:1:41:1 | a | operations.rb:41:6:41:6 | b | LogicalOrExpr | +| operations.rb:42:1:42:6 | ... \|\| ... | \|\| | operations.rb:42:1:42:1 | x | operations.rb:42:6:42:6 | y | LogicalOrExpr | +| operations.rb:45:1:45:6 | ... << ... | << | operations.rb:45:1:45:1 | x | operations.rb:45:6:45:6 | 3 | LShiftExpr | +| operations.rb:46:1:46:7 | ... >> ... | >> | operations.rb:46:1:46:1 | y | operations.rb:46:6:46:7 | 16 | RShiftExpr | +| operations.rb:47:1:47:10 | ... & ... | & | operations.rb:47:1:47:3 | foo | operations.rb:47:7:47:10 | 0xff | BitwiseAndExpr | +| operations.rb:48:1:48:10 | ... \| ... | \| | operations.rb:48:1:48:3 | bar | operations.rb:48:7:48:10 | 0x02 | BitwiseOrExpr | +| operations.rb:49:1:49:9 | ... ^ ... | ^ | operations.rb:49:1:49:3 | baz | operations.rb:49:7:49:9 | qux | BitwiseXorExpr | +| operations.rb:52:1:52:6 | ... == ... | == | operations.rb:52:1:52:1 | x | operations.rb:52:6:52:6 | y | EqExpr | +| operations.rb:53:1:53:8 | ... != ... | != | operations.rb:53:1:53:1 | a | operations.rb:53:6:53:8 | 123 | NEExpr | +| operations.rb:54:1:54:7 | ... === ... | === | operations.rb:54:1:54:1 | m | operations.rb:54:7:54:7 | n | CaseEqExpr | +| operations.rb:57:1:57:5 | ... > ... | > | operations.rb:57:1:57:1 | x | operations.rb:57:5:57:5 | 0 | GTExpr | +| operations.rb:58:1:58:8 | ... >= ... | >= | operations.rb:58:1:58:1 | y | operations.rb:58:6:58:8 | 100 | GEExpr | +| operations.rb:59:1:59:5 | ... < ... | < | operations.rb:59:1:59:1 | a | operations.rb:59:5:59:5 | b | LTExpr | +| operations.rb:60:1:60:8 | ... <= ... | <= | operations.rb:60:1:60:1 | 7 | operations.rb:60:6:60:8 | foo | LEExpr | +| operations.rb:63:1:63:7 | ... <=> ... | <=> | operations.rb:63:1:63:1 | a | operations.rb:63:7:63:7 | b | SpaceshipExpr | +| operations.rb:64:1:64:15 | ... =~ ... | =~ | operations.rb:64:1:64:4 | name | operations.rb:64:9:64:15 | foo.* | RegexMatchExpr | +| operations.rb:65:1:65:17 | ... !~ ... | !~ | operations.rb:65:1:65:6 | handle | operations.rb:65:11:65:17 | .*bar | NoRegexMatchExpr | +binaryArithmeticOperations +| operations.rb:31:1:31:7 | ... + ... | + | operations.rb:31:1:31:1 | w | operations.rb:31:5:31:7 | 234 | AddExpr | +| operations.rb:32:1:32:6 | ... - ... | - | operations.rb:32:1:32:1 | x | operations.rb:32:5:32:6 | 17 | SubExpr | +| operations.rb:33:1:33:6 | ... * ... | * | operations.rb:33:1:33:1 | y | operations.rb:33:5:33:6 | 10 | MulExpr | +| operations.rb:34:1:34:5 | ... / ... | / | operations.rb:34:1:34:1 | z | operations.rb:34:5:34:5 | 2 | DivExpr | +| operations.rb:35:1:35:7 | ... % ... | % | operations.rb:35:1:35:3 | num | operations.rb:35:7:35:7 | 2 | ModuloExpr | +| operations.rb:36:1:36:13 | ... ** ... | ** | operations.rb:36:1:36:4 | base | operations.rb:36:9:36:13 | power | ExponentExpr | +binaryLogicalOperations +| operations.rb:39:1:39:10 | ... && ... | && | operations.rb:39:1:39:3 | foo | operations.rb:39:8:39:10 | bar | LogicalAndExpr | +| operations.rb:40:1:40:11 | ... and ... | and | operations.rb:40:1:40:3 | baz | operations.rb:40:9:40:11 | qux | LogicalAndExpr | +| operations.rb:41:1:41:6 | ... or ... | or | operations.rb:41:1:41:1 | a | operations.rb:41:6:41:6 | b | LogicalOrExpr | +| operations.rb:42:1:42:6 | ... \|\| ... | \|\| | operations.rb:42:1:42:1 | x | operations.rb:42:6:42:6 | y | LogicalOrExpr | +binaryBitwiseOperations +| operations.rb:45:1:45:6 | ... << ... | << | operations.rb:45:1:45:1 | x | operations.rb:45:6:45:6 | 3 | LShiftExpr | +| operations.rb:46:1:46:7 | ... >> ... | >> | operations.rb:46:1:46:1 | y | operations.rb:46:6:46:7 | 16 | RShiftExpr | +| operations.rb:47:1:47:10 | ... & ... | & | operations.rb:47:1:47:3 | foo | operations.rb:47:7:47:10 | 0xff | BitwiseAndExpr | +| operations.rb:48:1:48:10 | ... \| ... | \| | operations.rb:48:1:48:3 | bar | operations.rb:48:7:48:10 | 0x02 | BitwiseOrExpr | +| operations.rb:49:1:49:9 | ... ^ ... | ^ | operations.rb:49:1:49:3 | baz | operations.rb:49:7:49:9 | qux | BitwiseXorExpr | +comparisonOperations +| operations.rb:52:1:52:6 | ... == ... | == | operations.rb:52:1:52:1 | x | operations.rb:52:6:52:6 | y | EqExpr | +| operations.rb:53:1:53:8 | ... != ... | != | operations.rb:53:1:53:1 | a | operations.rb:53:6:53:8 | 123 | NEExpr | +| operations.rb:54:1:54:7 | ... === ... | === | operations.rb:54:1:54:1 | m | operations.rb:54:7:54:7 | n | CaseEqExpr | +| operations.rb:57:1:57:5 | ... > ... | > | operations.rb:57:1:57:1 | x | operations.rb:57:5:57:5 | 0 | GTExpr | +| operations.rb:58:1:58:8 | ... >= ... | >= | operations.rb:58:1:58:1 | y | operations.rb:58:6:58:8 | 100 | GEExpr | +| operations.rb:59:1:59:5 | ... < ... | < | operations.rb:59:1:59:1 | a | operations.rb:59:5:59:5 | b | LTExpr | +| operations.rb:60:1:60:8 | ... <= ... | <= | operations.rb:60:1:60:1 | 7 | operations.rb:60:6:60:8 | foo | LEExpr | +equalityOperations +| operations.rb:52:1:52:6 | ... == ... | == | operations.rb:52:1:52:1 | x | operations.rb:52:6:52:6 | y | EqExpr | +| operations.rb:53:1:53:8 | ... != ... | != | operations.rb:53:1:53:1 | a | operations.rb:53:6:53:8 | 123 | NEExpr | +| operations.rb:54:1:54:7 | ... === ... | === | operations.rb:54:1:54:1 | m | operations.rb:54:7:54:7 | n | CaseEqExpr | +relationalOperations +| operations.rb:57:1:57:5 | ... > ... | > | operations.rb:57:1:57:1 | x | operations.rb:57:5:57:5 | 0 | GTExpr | +| operations.rb:58:1:58:8 | ... >= ... | >= | operations.rb:58:1:58:1 | y | operations.rb:58:6:58:8 | 100 | GEExpr | +| operations.rb:59:1:59:5 | ... < ... | < | operations.rb:59:1:59:1 | a | operations.rb:59:5:59:5 | b | LTExpr | +| operations.rb:60:1:60:8 | ... <= ... | <= | operations.rb:60:1:60:1 | 7 | operations.rb:60:6:60:8 | foo | LEExpr | +spaceshipExprs +| operations.rb:63:1:63:7 | ... <=> ... | <=> | operations.rb:63:1:63:1 | a | operations.rb:63:7:63:7 | b | SpaceshipExpr | +regexMatchExprs +| operations.rb:64:1:64:15 | ... =~ ... | =~ | operations.rb:64:1:64:4 | name | operations.rb:64:9:64:15 | foo.* | RegexMatchExpr | +noRegexMatchExprs +| operations.rb:65:1:65:17 | ... !~ ... | !~ | operations.rb:65:1:65:6 | handle | operations.rb:65:11:65:17 | .*bar | NoRegexMatchExpr | diff --git a/ql/test/library-tests/ast/operations/binary.ql b/ql/test/library-tests/ast/operations/binary.ql new file mode 100644 index 00000000000..1f4b2f2d2fc --- /dev/null +++ b/ql/test/library-tests/ast/operations/binary.ql @@ -0,0 +1,91 @@ +import ruby + +query predicate binaryOperations( + BinaryOperation o, string operator, Expr left, Expr right, string pClass +) { + operator = o.getOperator() and + left = o.getLeftOperand() and + right = o.getRightOperand() and + pClass = o.getAPrimaryQlClass() +} + +query predicate binaryArithmeticOperations( + BinaryArithmeticOperation o, string operator, Expr left, Expr right, string pClass +) { + operator = o.getOperator() and + left = o.getLeftOperand() and + right = o.getRightOperand() and + pClass = o.getAPrimaryQlClass() +} + +query predicate binaryLogicalOperations( + BinaryLogicalOperation o, string operator, Expr left, Expr right, string pClass +) { + operator = o.getOperator() and + left = o.getLeftOperand() and + right = o.getRightOperand() and + pClass = o.getAPrimaryQlClass() +} + +query predicate binaryBitwiseOperations( + BinaryBitwiseOperation o, string operator, Expr left, Expr right, string pClass +) { + operator = o.getOperator() and + left = o.getLeftOperand() and + right = o.getRightOperand() and + pClass = o.getAPrimaryQlClass() +} + +query predicate comparisonOperations( + ComparisonOperation o, string operator, Expr left, Expr right, string pClass +) { + operator = o.getOperator() and + left = o.getLeftOperand() and + right = o.getRightOperand() and + pClass = o.getAPrimaryQlClass() +} + +query predicate equalityOperations( + EqualityOperation o, string operator, Expr left, Expr right, string pClass +) { + operator = o.getOperator() and + left = o.getLeftOperand() and + right = o.getRightOperand() and + pClass = o.getAPrimaryQlClass() +} + +query predicate relationalOperations( + RelationalOperation o, string operator, Expr left, Expr right, string pClass +) { + operator = o.getOperator() and + left = o.getLeftOperand() and + right = o.getRightOperand() and + pClass = o.getAPrimaryQlClass() +} + +query predicate spaceshipExprs( + SpaceshipExpr e, string operator, Expr left, Expr right, string pClass +) { + operator = e.getOperator() and + left = e.getLeftOperand() and + right = e.getRightOperand() and + pClass = e.getAPrimaryQlClass() +} + +query predicate regexMatchExprs( + RegexMatchExpr e, string operator, Expr left, Expr right, string pClass +) { + operator = e.getOperator() and + left = e.getLeftOperand() and + right = e.getRightOperand() and + pClass = e.getAPrimaryQlClass() +} + +query predicate noRegexMatchExprs( + NoRegexMatchExpr e, string operator, Expr left, Expr right, string pClass +) { + operator = e.getOperator() and + left = e.getLeftOperand() and + right = e.getRightOperand() and + pClass = e.getAPrimaryQlClass() +} diff --git a/ql/test/library-tests/ast/operations/operation.expected b/ql/test/library-tests/ast/operations/operation.expected new file mode 100644 index 00000000000..b2ed55dee47 --- /dev/null +++ b/ql/test/library-tests/ast/operations/operation.expected @@ -0,0 +1,118 @@ +| operations.rb:3:1:3:5 | ... = ... | = | operations.rb:3:1:3:1 | a | AssignExpr | +| operations.rb:3:1:3:5 | ... = ... | = | operations.rb:3:5:3:5 | 0 | AssignExpr | +| operations.rb:4:1:4:5 | ... = ... | = | operations.rb:4:1:4:1 | b | AssignExpr | +| operations.rb:4:1:4:5 | ... = ... | = | operations.rb:4:5:4:5 | 0 | AssignExpr | +| operations.rb:5:1:5:7 | ... = ... | = | operations.rb:5:1:5:3 | bar | AssignExpr | +| operations.rb:5:1:5:7 | ... = ... | = | operations.rb:5:7:5:7 | 0 | AssignExpr | +| operations.rb:6:1:6:8 | ... = ... | = | operations.rb:6:1:6:4 | base | AssignExpr | +| operations.rb:6:1:6:8 | ... = ... | = | operations.rb:6:8:6:8 | 0 | AssignExpr | +| operations.rb:7:1:7:7 | ... = ... | = | operations.rb:7:1:7:3 | baz | AssignExpr | +| operations.rb:7:1:7:7 | ... = ... | = | operations.rb:7:7:7:7 | 0 | AssignExpr | +| operations.rb:8:1:8:7 | ... = ... | = | operations.rb:8:1:8:3 | foo | AssignExpr | +| operations.rb:8:1:8:7 | ... = ... | = | operations.rb:8:7:8:7 | 0 | AssignExpr | +| operations.rb:9:1:9:10 | ... = ... | = | operations.rb:9:1:9:6 | handle | AssignExpr | +| operations.rb:9:1:9:10 | ... = ... | = | operations.rb:9:10:9:10 | 0 | AssignExpr | +| operations.rb:10:1:10:5 | ... = ... | = | operations.rb:10:1:10:1 | m | AssignExpr | +| operations.rb:10:1:10:5 | ... = ... | = | operations.rb:10:5:10:5 | 0 | AssignExpr | +| operations.rb:11:1:11:8 | ... = ... | = | operations.rb:11:1:11:4 | mask | AssignExpr | +| operations.rb:11:1:11:8 | ... = ... | = | operations.rb:11:8:11:8 | 0 | AssignExpr | +| operations.rb:12:1:12:5 | ... = ... | = | operations.rb:12:1:12:1 | n | AssignExpr | +| operations.rb:12:1:12:5 | ... = ... | = | operations.rb:12:5:12:5 | 0 | AssignExpr | +| operations.rb:13:1:13:8 | ... = ... | = | operations.rb:13:1:13:4 | name | AssignExpr | +| operations.rb:13:1:13:8 | ... = ... | = | operations.rb:13:8:13:8 | 0 | AssignExpr | +| operations.rb:14:1:14:7 | ... = ... | = | operations.rb:14:1:14:3 | num | AssignExpr | +| operations.rb:14:1:14:7 | ... = ... | = | operations.rb:14:7:14:7 | 0 | AssignExpr | +| operations.rb:15:1:15:9 | ... = ... | = | operations.rb:15:1:15:5 | power | AssignExpr | +| operations.rb:15:1:15:9 | ... = ... | = | operations.rb:15:9:15:9 | 0 | AssignExpr | +| operations.rb:16:1:16:7 | ... = ... | = | operations.rb:16:1:16:3 | qux | AssignExpr | +| operations.rb:16:1:16:7 | ... = ... | = | operations.rb:16:7:16:7 | 0 | AssignExpr | +| operations.rb:17:1:17:5 | ... = ... | = | operations.rb:17:1:17:1 | w | AssignExpr | +| operations.rb:17:1:17:5 | ... = ... | = | operations.rb:17:5:17:5 | 0 | AssignExpr | +| operations.rb:18:1:18:5 | ... = ... | = | operations.rb:18:1:18:1 | x | AssignExpr | +| operations.rb:18:1:18:5 | ... = ... | = | operations.rb:18:5:18:5 | 0 | AssignExpr | +| operations.rb:19:1:19:5 | ... = ... | = | operations.rb:19:1:19:1 | y | AssignExpr | +| operations.rb:19:1:19:5 | ... = ... | = | operations.rb:19:5:19:5 | 0 | AssignExpr | +| operations.rb:20:1:20:5 | ... = ... | = | operations.rb:20:1:20:1 | z | AssignExpr | +| operations.rb:20:1:20:5 | ... = ... | = | operations.rb:20:5:20:5 | 0 | AssignExpr | +| operations.rb:23:1:23:2 | ! ... | ! | operations.rb:23:2:23:2 | a | NotExpr | +| operations.rb:24:1:24:5 | not ... | not | operations.rb:24:5:24:5 | b | NotExpr | +| operations.rb:25:1:25:3 | + ... | + | operations.rb:25:2:25:3 | 14 | UnaryPlusExpr | +| operations.rb:26:1:26:2 | - ... | - | operations.rb:26:2:26:2 | 7 | UnaryMinusExpr | +| operations.rb:27:1:27:2 | ~ ... | ~ | operations.rb:27:2:27:2 | x | ComplementExpr | +| operations.rb:28:1:28:12 | defined? ... | defined? | operations.rb:28:10:28:12 | foo | DefinedExpr | +| operations.rb:31:1:31:7 | ... + ... | + | operations.rb:31:1:31:1 | w | AddExpr | +| operations.rb:31:1:31:7 | ... + ... | + | operations.rb:31:5:31:7 | 234 | AddExpr | +| operations.rb:32:1:32:6 | ... - ... | - | operations.rb:32:1:32:1 | x | SubExpr | +| operations.rb:32:1:32:6 | ... - ... | - | operations.rb:32:5:32:6 | 17 | SubExpr | +| operations.rb:33:1:33:6 | ... * ... | * | operations.rb:33:1:33:1 | y | MulExpr | +| operations.rb:33:1:33:6 | ... * ... | * | operations.rb:33:5:33:6 | 10 | MulExpr | +| operations.rb:34:1:34:5 | ... / ... | / | operations.rb:34:1:34:1 | z | DivExpr | +| operations.rb:34:1:34:5 | ... / ... | / | operations.rb:34:5:34:5 | 2 | DivExpr | +| operations.rb:35:1:35:7 | ... % ... | % | operations.rb:35:1:35:3 | num | ModuloExpr | +| operations.rb:35:1:35:7 | ... % ... | % | operations.rb:35:7:35:7 | 2 | ModuloExpr | +| operations.rb:36:1:36:13 | ... ** ... | ** | operations.rb:36:1:36:4 | base | ExponentExpr | +| operations.rb:36:1:36:13 | ... ** ... | ** | operations.rb:36:9:36:13 | power | ExponentExpr | +| operations.rb:39:1:39:10 | ... && ... | && | operations.rb:39:1:39:3 | foo | LogicalAndExpr | +| operations.rb:39:1:39:10 | ... && ... | && | operations.rb:39:8:39:10 | bar | LogicalAndExpr | +| operations.rb:40:1:40:11 | ... and ... | and | operations.rb:40:1:40:3 | baz | LogicalAndExpr | +| operations.rb:40:1:40:11 | ... and ... | and | operations.rb:40:9:40:11 | qux | LogicalAndExpr | +| operations.rb:41:1:41:6 | ... or ... | or | operations.rb:41:1:41:1 | a | LogicalOrExpr | +| operations.rb:41:1:41:6 | ... or ... | or | operations.rb:41:6:41:6 | b | LogicalOrExpr | +| operations.rb:42:1:42:6 | ... \|\| ... | \|\| | operations.rb:42:1:42:1 | x | LogicalOrExpr | +| operations.rb:42:1:42:6 | ... \|\| ... | \|\| | operations.rb:42:6:42:6 | y | LogicalOrExpr | +| operations.rb:45:1:45:6 | ... << ... | << | operations.rb:45:1:45:1 | x | LShiftExpr | +| operations.rb:45:1:45:6 | ... << ... | << | operations.rb:45:6:45:6 | 3 | LShiftExpr | +| operations.rb:46:1:46:7 | ... >> ... | >> | operations.rb:46:1:46:1 | y | RShiftExpr | +| operations.rb:46:1:46:7 | ... >> ... | >> | operations.rb:46:6:46:7 | 16 | RShiftExpr | +| operations.rb:47:1:47:10 | ... & ... | & | operations.rb:47:1:47:3 | foo | BitwiseAndExpr | +| operations.rb:47:1:47:10 | ... & ... | & | operations.rb:47:7:47:10 | 0xff | BitwiseAndExpr | +| operations.rb:48:1:48:10 | ... \| ... | \| | operations.rb:48:1:48:3 | bar | BitwiseOrExpr | +| operations.rb:48:1:48:10 | ... \| ... | \| | operations.rb:48:7:48:10 | 0x02 | BitwiseOrExpr | +| operations.rb:49:1:49:9 | ... ^ ... | ^ | operations.rb:49:1:49:3 | baz | BitwiseXorExpr | +| operations.rb:49:1:49:9 | ... ^ ... | ^ | operations.rb:49:7:49:9 | qux | BitwiseXorExpr | +| operations.rb:52:1:52:6 | ... == ... | == | operations.rb:52:1:52:1 | x | EqExpr | +| operations.rb:52:1:52:6 | ... == ... | == | operations.rb:52:6:52:6 | y | EqExpr | +| operations.rb:53:1:53:8 | ... != ... | != | operations.rb:53:1:53:1 | a | NEExpr | +| operations.rb:53:1:53:8 | ... != ... | != | operations.rb:53:6:53:8 | 123 | NEExpr | +| operations.rb:54:1:54:7 | ... === ... | === | operations.rb:54:1:54:1 | m | CaseEqExpr | +| operations.rb:54:1:54:7 | ... === ... | === | operations.rb:54:7:54:7 | n | CaseEqExpr | +| operations.rb:57:1:57:5 | ... > ... | > | operations.rb:57:1:57:1 | x | GTExpr | +| operations.rb:57:1:57:5 | ... > ... | > | operations.rb:57:5:57:5 | 0 | GTExpr | +| operations.rb:58:1:58:8 | ... >= ... | >= | operations.rb:58:1:58:1 | y | GEExpr | +| operations.rb:58:1:58:8 | ... >= ... | >= | operations.rb:58:6:58:8 | 100 | GEExpr | +| operations.rb:59:1:59:5 | ... < ... | < | operations.rb:59:1:59:1 | a | LTExpr | +| operations.rb:59:1:59:5 | ... < ... | < | operations.rb:59:5:59:5 | b | LTExpr | +| operations.rb:60:1:60:8 | ... <= ... | <= | operations.rb:60:1:60:1 | 7 | LEExpr | +| operations.rb:60:1:60:8 | ... <= ... | <= | operations.rb:60:6:60:8 | foo | LEExpr | +| operations.rb:63:1:63:7 | ... <=> ... | <=> | operations.rb:63:1:63:1 | a | SpaceshipExpr | +| operations.rb:63:1:63:7 | ... <=> ... | <=> | operations.rb:63:7:63:7 | b | SpaceshipExpr | +| operations.rb:64:1:64:15 | ... =~ ... | =~ | operations.rb:64:1:64:4 | name | RegexMatchExpr | +| operations.rb:64:1:64:15 | ... =~ ... | =~ | operations.rb:64:9:64:15 | foo.* | RegexMatchExpr | +| operations.rb:65:1:65:17 | ... !~ ... | !~ | operations.rb:65:1:65:6 | handle | NoRegexMatchExpr | +| operations.rb:65:1:65:17 | ... !~ ... | !~ | operations.rb:65:11:65:17 | .*bar | NoRegexMatchExpr | +| operations.rb:68:1:68:8 | ... += ... | += | operations.rb:68:1:68:1 | x | AssignAddExpr | +| operations.rb:68:1:68:8 | ... += ... | += | operations.rb:68:6:68:8 | 128 | AssignAddExpr | +| operations.rb:69:1:69:7 | ... -= ... | -= | operations.rb:69:1:69:1 | y | AssignSubExpr | +| operations.rb:69:1:69:7 | ... -= ... | -= | operations.rb:69:6:69:7 | 32 | AssignSubExpr | +| operations.rb:70:1:70:7 | ... *= ... | *= | operations.rb:70:1:70:1 | a | AssignMulExpr | +| operations.rb:70:1:70:7 | ... *= ... | *= | operations.rb:70:6:70:7 | 12 | AssignMulExpr | +| operations.rb:71:1:71:6 | ... /= ... | /= | operations.rb:71:1:71:1 | b | AssignDivExpr | +| operations.rb:71:1:71:6 | ... /= ... | /= | operations.rb:71:6:71:6 | 4 | AssignDivExpr | +| operations.rb:72:1:72:6 | ... %= ... | %= | operations.rb:72:1:72:1 | z | AssignModuloExpr | +| operations.rb:72:1:72:6 | ... %= ... | %= | operations.rb:72:6:72:6 | 2 | AssignModuloExpr | +| operations.rb:73:1:73:11 | ... **= ... | **= | operations.rb:73:1:73:3 | foo | AssignExponentExpr | +| operations.rb:73:1:73:11 | ... **= ... | **= | operations.rb:73:9:73:11 | bar | AssignExponentExpr | +| operations.rb:76:2:76:8 | ... &&= ... | &&= | operations.rb:76:2:76:2 | x | AssignLogicalAndExpr | +| operations.rb:76:2:76:8 | ... &&= ... | &&= | operations.rb:76:8:76:8 | y | AssignLogicalAndExpr | +| operations.rb:77:2:77:8 | ... \|\|= ... | \|\|= | operations.rb:77:2:77:2 | a | AssignLogicalOrExpr | +| operations.rb:77:2:77:8 | ... \|\|= ... | \|\|= | operations.rb:77:8:77:8 | b | AssignLogicalOrExpr | +| operations.rb:80:2:80:8 | ... <<= ... | <<= | operations.rb:80:2:80:2 | x | AssignLShiftExpr | +| operations.rb:80:2:80:8 | ... <<= ... | <<= | operations.rb:80:8:80:8 | 2 | AssignLShiftExpr | +| operations.rb:81:2:81:8 | ... >>= ... | >>= | operations.rb:81:2:81:2 | y | AssignRShiftExpr | +| operations.rb:81:2:81:8 | ... >>= ... | >>= | operations.rb:81:8:81:8 | 3 | AssignRShiftExpr | +| operations.rb:82:2:82:12 | ... &= ... | &= | operations.rb:82:2:82:4 | foo | AssignBitwiseAndExpr | +| operations.rb:82:2:82:12 | ... &= ... | &= | operations.rb:82:9:82:12 | mask | AssignBitwiseAndExpr | +| operations.rb:83:2:83:12 | ... \|= ... | \|= | operations.rb:83:2:83:4 | bar | AssignBitwiseOrExpr | +| operations.rb:83:2:83:12 | ... \|= ... | \|= | operations.rb:83:9:83:12 | 0x01 | AssignBitwiseOrExpr | +| operations.rb:84:2:84:11 | ... ^= ... | ^= | operations.rb:84:2:84:4 | baz | AssignBitwiseXorExpr | +| operations.rb:84:2:84:11 | ... ^= ... | ^= | operations.rb:84:9:84:11 | qux | AssignBitwiseXorExpr | diff --git a/ql/test/library-tests/ast/operations/operation.ql b/ql/test/library-tests/ast/operations/operation.ql new file mode 100644 index 00000000000..2a1db9fd3df --- /dev/null +++ b/ql/test/library-tests/ast/operations/operation.ql @@ -0,0 +1,8 @@ +import ruby + +from Operation o, string operator, Expr operand, string pClass +where + operator = o.getOperator() and + operand = o.getAnOperand() and + pClass = o.getAPrimaryQlClass() +select o, operator, operand, pClass diff --git a/ql/test/library-tests/ast/operations/operations.rb b/ql/test/library-tests/ast/operations/operations.rb new file mode 100644 index 00000000000..707a2d36425 --- /dev/null +++ b/ql/test/library-tests/ast/operations/operations.rb @@ -0,0 +1,84 @@ +# Start with assignments to all the identifiers used below, so that they are +# interpreted as variables. +a = 0 +b = 0 +bar = 0 +base = 0 +baz = 0 +foo = 0 +handle = 0 +m = 0 +mask = 0 +n = 0 +name = 0 +num = 0 +power = 0 +qux = 0 +w = 0 +x = 0 +y = 0 +z = 0 + +# Unary operations +!a +not b ++14 +-7 +~x +defined? foo + +# Binary arithmetic operations +w + 234 +x - 17 +y * 10 +z / 2 +num % 2 +base ** power + +# Binary logical operations +foo && bar +baz and qux +a or b +x || y + +# Binary bitwise operations +x << 3 +y >> 16 +foo & 0xff +bar | 0x02 +baz ^ qux + +# Equality operations +x == y +a != 123 +m === n + +# Relational operations +x > 0 +y >= 100 +a < b +7 <= foo + +# Misc binary operations +a <=> b +name =~ /foo.*/ +handle !~ /.*bar/ + +# Arithmetic assign operations +x += 128 +y -= 32 +a *= 12 +b /= 4 +z %= 2 +foo **= bar + +# Logical assign operations + x &&= y + a ||= b + + # Bitwise assign operations + x <<= 2 + y >>= 3 + foo &= mask + bar |= 0x01 + baz ^= qux \ No newline at end of file diff --git a/ql/test/library-tests/ast/operations/unary.expected b/ql/test/library-tests/ast/operations/unary.expected new file mode 100644 index 00000000000..cf6b76946b6 --- /dev/null +++ b/ql/test/library-tests/ast/operations/unary.expected @@ -0,0 +1,15 @@ +unaryOperations +| operations.rb:23:1:23:2 | ! ... | ! | operations.rb:23:2:23:2 | a | NotExpr | +| operations.rb:24:1:24:5 | not ... | not | operations.rb:24:5:24:5 | b | NotExpr | +| operations.rb:25:1:25:3 | + ... | + | operations.rb:25:2:25:3 | 14 | UnaryPlusExpr | +| operations.rb:26:1:26:2 | - ... | - | operations.rb:26:2:26:2 | 7 | UnaryMinusExpr | +| operations.rb:27:1:27:2 | ~ ... | ~ | operations.rb:27:2:27:2 | x | ComplementExpr | +| operations.rb:28:1:28:12 | defined? ... | defined? | operations.rb:28:10:28:12 | foo | DefinedExpr | +unaryLogicalOperations +| operations.rb:23:1:23:2 | ! ... | ! | operations.rb:23:2:23:2 | a | NotExpr | +| operations.rb:24:1:24:5 | not ... | not | operations.rb:24:5:24:5 | b | NotExpr | +unaryArithmeticOperations +| operations.rb:25:1:25:3 | + ... | + | operations.rb:25:2:25:3 | 14 | UnaryPlusExpr | +| operations.rb:26:1:26:2 | - ... | - | operations.rb:26:2:26:2 | 7 | UnaryMinusExpr | +unaryBitwiseOperations +| operations.rb:27:1:27:2 | ~ ... | ~ | operations.rb:27:2:27:2 | x | ComplementExpr | diff --git a/ql/test/library-tests/ast/operations/unary.ql b/ql/test/library-tests/ast/operations/unary.ql new file mode 100644 index 00000000000..a03bffa3a64 --- /dev/null +++ b/ql/test/library-tests/ast/operations/unary.ql @@ -0,0 +1,31 @@ +import ruby + +query predicate unaryOperations(UnaryOperation o, string operator, Expr operand, string pClass) { + operator = o.getOperator() and + operand = o.getOperand() and + pClass = o.getAPrimaryQlClass() +} + +query predicate unaryLogicalOperations( + UnaryLogicalOperation o, string operator, Expr operand, string pClass +) { + operator = o.getOperator() and + operand = o.getOperand() and + pClass = o.getAPrimaryQlClass() +} + +query predicate unaryArithmeticOperations( + UnaryArithmeticOperation o, string operator, Expr operand, string pClass +) { + operator = o.getOperator() and + operand = o.getOperand() and + pClass = o.getAPrimaryQlClass() +} + +query predicate unaryBitwiseOperations( + UnaryBitwiseOperation o, string operator, Expr operand, string pClass +) { + operator = o.getOperator() and + operand = o.getOperand() and + pClass = o.getAPrimaryQlClass() +}