Skip to content

Ruby: parenthesized patterns #7306

New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Merged
merged 5 commits into from
Dec 3, 2021
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
2 changes: 1 addition & 1 deletion ruby/Cargo.lock

Some generated files are not rendered by default. Learn more about how customized files appear on GitHub.

2 changes: 1 addition & 1 deletion ruby/extractor/Cargo.toml
Original file line number Diff line number Diff line change
Expand Up @@ -11,7 +11,7 @@ flate2 = "1.0"
node-types = { path = "../node-types" }
tree-sitter = "0.19"
tree-sitter-embedded-template = "0.19"
tree-sitter-ruby = { git = "https://github.com/tree-sitter/tree-sitter-ruby.git", rev = "951799c6780deaabb0666b846cb7ad4eab627bbb" }
tree-sitter-ruby = { git = "https://github.com/tree-sitter/tree-sitter-ruby.git", rev = "888e2e563ed3b43c417f17e57f7e29c39ce9aeea" }
clap = "2.33"
tracing = "0.1"
tracing-subscriber = { version = "0.2", features = ["env-filter"] }
Expand Down
2 changes: 1 addition & 1 deletion ruby/generator/Cargo.toml
Original file line number Diff line number Diff line change
Expand Up @@ -12,4 +12,4 @@ node-types = { path = "../node-types" }
tracing = "0.1"
tracing-subscriber = { version = "0.2", features = ["env-filter"] }
tree-sitter-embedded-template = "0.19"
tree-sitter-ruby = { git = "https://github.com/tree-sitter/tree-sitter-ruby.git", rev = "951799c6780deaabb0666b846cb7ad4eab627bbb" }
tree-sitter-ruby = { git = "https://github.com/tree-sitter/tree-sitter-ruby.git", rev = "888e2e563ed3b43c417f17e57f7e29c39ce9aeea" }
27 changes: 26 additions & 1 deletion ruby/ql/lib/codeql/ruby/ast/Pattern.qll
Original file line number Diff line number Diff line change
Expand Up @@ -100,7 +100,7 @@ class TuplePattern extends Pattern, TTuplePattern {

private class TPatternNode =
TArrayPattern or TFindPattern or THashPattern or TAlternativePattern or TAsPattern or
TVariableReferencePattern;
TParenthesizedPattern or TVariableReferencePattern;

private class TPattern =
TPatternNode or TLiteral or TLambda or TConstantAccess or TLocalVariableAccess or
Expand Down Expand Up @@ -389,6 +389,31 @@ class AsPattern extends CasePattern, TAsPattern {
}
}

/**
* A parenthesized pattern:
* ```rb
* in (1 ..)
* in (0 | "" | [] | {})
* ```
*/
class ParenthesizedPattern extends CasePattern, TParenthesizedPattern {
private Ruby::ParenthesizedPattern g;

ParenthesizedPattern() { this = TParenthesizedPattern(g) }

final CasePattern getPattern() { toGenerated(result) = g.getChild() }

final override string getAPrimaryQlClass() { result = "ParenthesizedPattern" }

final override string toString() { result = "( ... )" }

final override AstNode getAChild(string pred) {
result = super.getAChild(pred)
or
pred = "getPattern" and result = this.getPattern()
}
}

/**
* A variable reference in a pattern, i.e. `^x` in the following example:
* ```rb
Expand Down
10 changes: 6 additions & 4 deletions ruby/ql/lib/codeql/ruby/ast/internal/AST.qll
Original file line number Diff line number Diff line change
Expand Up @@ -216,6 +216,7 @@ private module Cached {
TOptionalParameter(Ruby::OptionalParameter g) or
TPair(Ruby::Pair g) or
TParenthesizedExpr(Ruby::ParenthesizedStatements g) or
TParenthesizedPattern(Ruby::ParenthesizedPattern g) or
TRShiftExprReal(Ruby::Binary g) { g instanceof @ruby_binary_ranglerangle } or
TRShiftExprSynth(AST::AstNode parent, int i) { mkSynthChild(RShiftExprKind(), parent, i) } or
TRangeLiteralReal(Ruby::Range g) or
Expand Down Expand Up @@ -335,10 +336,10 @@ private module Cached {
TLeftAssignmentList or TLine or TLocalVariableAccessReal or TLogicalAndExprReal or
TLogicalOrExprReal or TMethod or TModuleDeclaration or TModuloExprReal or TMulExprReal or
TNEExpr or TNextStmt or TNilLiteral or TNoRegExpMatchExpr or TNotExpr or
TOptionalParameter or TPair or TParenthesizedExpr or TRShiftExprReal or TRangeLiteralReal or
TRationalLiteral or TRedoStmt or TRegExpLiteral or TRegExpMatchExpr or
TRegularArrayLiteral or TRegularMethodCall or TRegularStringLiteral or TRegularSuperCall or
TRescueClause or TRescueModifierExpr or TRetryStmt or TReturnStmt or
TOptionalParameter or TPair or TParenthesizedExpr or TParenthesizedPattern or
TRShiftExprReal or TRangeLiteralReal or TRationalLiteral or TRedoStmt or TRegExpLiteral or
TRegExpMatchExpr or TRegularArrayLiteral or TRegularMethodCall or TRegularStringLiteral or
TRegularSuperCall or TRescueClause or TRescueModifierExpr or TRetryStmt or TReturnStmt or
TScopeResolutionConstantAccess or TScopeResolutionMethodCall or TSelfReal or
TSimpleParameterReal or TSimpleSymbolLiteral or TSingletonClass or TSingletonMethod or
TSpaceshipExpr or TSplatExprReal or TSplatParameter or TStringArrayLiteral or
Expand Down Expand Up @@ -465,6 +466,7 @@ private module Cached {
n = TOptionalParameter(result) or
n = TPair(result) or
n = TParenthesizedExpr(result) or
n = TParenthesizedPattern(result) or
n = TRangeLiteralReal(result) or
n = TRationalLiteral(result) or
n = TRedoStmt(result) or
Expand Down
2 changes: 2 additions & 0 deletions ruby/ql/lib/codeql/ruby/ast/internal/Pattern.qll
Original file line number Diff line number Diff line change
Expand Up @@ -46,6 +46,8 @@ predicate casePattern(Ruby::AstNode node) {
node = any(Ruby::AsPattern parent).getValue()
or
node = any(Ruby::KeywordPattern parent).getValue()
or
node = any(Ruby::ParenthesizedPattern parent).getChild()
}

/**
Expand Down
15 changes: 15 additions & 0 deletions ruby/ql/lib/codeql/ruby/ast/internal/TreeSitter.qll
Original file line number Diff line number Diff line change
Expand Up @@ -1406,6 +1406,21 @@ module Ruby {
}
}

/** A class representing `parenthesized_pattern` nodes. */
class ParenthesizedPattern extends @ruby_parenthesized_pattern, AstNode {
/** Gets the name of the primary QL class for this element. */
override string getAPrimaryQlClass() { result = "ParenthesizedPattern" }

/** Gets the location of this element. */
override L::Location getLocation() { ruby_parenthesized_pattern_def(this, _, result) }

/** Gets the child of this node. */
UnderscorePatternExpr getChild() { ruby_parenthesized_pattern_def(this, result, _) }

/** Gets a field or child node of this node. */
override AstNode getAFieldOrChild() { ruby_parenthesized_pattern_def(this, result, _) }
}

/** A class representing `parenthesized_statements` nodes. */
class ParenthesizedStatements extends @ruby_parenthesized_statements, AstNode {
/** Gets the name of the primary QL class for this element. */
Expand Down
10 changes: 8 additions & 2 deletions ruby/ql/lib/ruby.dbscheme
Original file line number Diff line number Diff line change
Expand Up @@ -62,7 +62,7 @@ case @diagnostic.severity of

@ruby_underscore_pattern_expr = @ruby_alternative_pattern | @ruby_as_pattern | @ruby_underscore_pattern_expr_basic

@ruby_underscore_pattern_expr_basic = @ruby_array_pattern | @ruby_find_pattern | @ruby_hash_pattern | @ruby_range | @ruby_token_identifier | @ruby_underscore_pattern_constant | @ruby_underscore_pattern_primitive | @ruby_variable_reference_pattern
@ruby_underscore_pattern_expr_basic = @ruby_array_pattern | @ruby_find_pattern | @ruby_hash_pattern | @ruby_parenthesized_pattern | @ruby_range | @ruby_token_identifier | @ruby_underscore_pattern_constant | @ruby_underscore_pattern_primitive | @ruby_variable_reference_pattern

@ruby_underscore_pattern_primitive = @ruby_delimited_symbol | @ruby_lambda | @ruby_regex | @ruby_string__ | @ruby_string_array | @ruby_symbol_array | @ruby_token_encoding | @ruby_token_false | @ruby_token_file | @ruby_token_line | @ruby_token_nil | @ruby_token_self | @ruby_token_simple_symbol | @ruby_token_true | @ruby_unary | @ruby_underscore_simple_numeric

Expand Down Expand Up @@ -912,6 +912,12 @@ ruby_pair_def(
int loc: @location ref
);

ruby_parenthesized_pattern_def(
unique int id: @ruby_parenthesized_pattern,
int child: @ruby_underscore_pattern_expr ref,
int loc: @location ref
);

@ruby_parenthesized_statements_child_type = @ruby_token_empty_statement | @ruby_underscore_statement

#keyset[ruby_parenthesized_statements, index]
Expand Down Expand Up @@ -1392,7 +1398,7 @@ case @ruby_token.kind of
;


@ruby_ast_node = @ruby_alias | @ruby_alternative_pattern | @ruby_argument_list | @ruby_array | @ruby_array_pattern | @ruby_as_pattern | @ruby_assignment | @ruby_bare_string | @ruby_bare_symbol | @ruby_begin | @ruby_begin_block | @ruby_binary | @ruby_block | @ruby_block_argument | @ruby_block_parameter | @ruby_block_parameters | @ruby_break | @ruby_call | @ruby_case__ | @ruby_case_match | @ruby_chained_string | @ruby_class | @ruby_conditional | @ruby_delimited_symbol | @ruby_destructured_left_assignment | @ruby_destructured_parameter | @ruby_do | @ruby_do_block | @ruby_element_reference | @ruby_else | @ruby_elsif | @ruby_end_block | @ruby_ensure | @ruby_exception_variable | @ruby_exceptions | @ruby_find_pattern | @ruby_for | @ruby_hash | @ruby_hash_pattern | @ruby_hash_splat_argument | @ruby_hash_splat_parameter | @ruby_heredoc_body | @ruby_if | @ruby_if_guard | @ruby_if_modifier | @ruby_in | @ruby_in_clause | @ruby_interpolation | @ruby_keyword_parameter | @ruby_keyword_pattern | @ruby_lambda | @ruby_lambda_parameters | @ruby_left_assignment_list | @ruby_method | @ruby_method_parameters | @ruby_module | @ruby_next | @ruby_operator_assignment | @ruby_optional_parameter | @ruby_pair | @ruby_parenthesized_statements | @ruby_pattern | @ruby_program | @ruby_range | @ruby_rational | @ruby_redo | @ruby_regex | @ruby_rescue | @ruby_rescue_modifier | @ruby_rest_assignment | @ruby_retry | @ruby_return | @ruby_right_assignment_list | @ruby_scope_resolution | @ruby_setter | @ruby_singleton_class | @ruby_singleton_method | @ruby_splat_argument | @ruby_splat_parameter | @ruby_string__ | @ruby_string_array | @ruby_subshell | @ruby_superclass | @ruby_symbol_array | @ruby_then | @ruby_token | @ruby_unary | @ruby_undef | @ruby_unless | @ruby_unless_guard | @ruby_unless_modifier | @ruby_until | @ruby_until_modifier | @ruby_variable_reference_pattern | @ruby_when | @ruby_while | @ruby_while_modifier | @ruby_yield
@ruby_ast_node = @ruby_alias | @ruby_alternative_pattern | @ruby_argument_list | @ruby_array | @ruby_array_pattern | @ruby_as_pattern | @ruby_assignment | @ruby_bare_string | @ruby_bare_symbol | @ruby_begin | @ruby_begin_block | @ruby_binary | @ruby_block | @ruby_block_argument | @ruby_block_parameter | @ruby_block_parameters | @ruby_break | @ruby_call | @ruby_case__ | @ruby_case_match | @ruby_chained_string | @ruby_class | @ruby_conditional | @ruby_delimited_symbol | @ruby_destructured_left_assignment | @ruby_destructured_parameter | @ruby_do | @ruby_do_block | @ruby_element_reference | @ruby_else | @ruby_elsif | @ruby_end_block | @ruby_ensure | @ruby_exception_variable | @ruby_exceptions | @ruby_find_pattern | @ruby_for | @ruby_hash | @ruby_hash_pattern | @ruby_hash_splat_argument | @ruby_hash_splat_parameter | @ruby_heredoc_body | @ruby_if | @ruby_if_guard | @ruby_if_modifier | @ruby_in | @ruby_in_clause | @ruby_interpolation | @ruby_keyword_parameter | @ruby_keyword_pattern | @ruby_lambda | @ruby_lambda_parameters | @ruby_left_assignment_list | @ruby_method | @ruby_method_parameters | @ruby_module | @ruby_next | @ruby_operator_assignment | @ruby_optional_parameter | @ruby_pair | @ruby_parenthesized_pattern | @ruby_parenthesized_statements | @ruby_pattern | @ruby_program | @ruby_range | @ruby_rational | @ruby_redo | @ruby_regex | @ruby_rescue | @ruby_rescue_modifier | @ruby_rest_assignment | @ruby_retry | @ruby_return | @ruby_right_assignment_list | @ruby_scope_resolution | @ruby_setter | @ruby_singleton_class | @ruby_singleton_method | @ruby_splat_argument | @ruby_splat_parameter | @ruby_string__ | @ruby_string_array | @ruby_subshell | @ruby_superclass | @ruby_symbol_array | @ruby_then | @ruby_token | @ruby_unary | @ruby_undef | @ruby_unless | @ruby_unless_guard | @ruby_unless_modifier | @ruby_until | @ruby_until_modifier | @ruby_variable_reference_pattern | @ruby_when | @ruby_while | @ruby_while_modifier | @ruby_yield

@ruby_ast_node_parent = @file | @ruby_ast_node

Expand Down
Loading