Merge pull request #128 from github/aibaars/ast-3

AST: undef and alias
This commit is contained in:
Arthur Baars
2021-02-15 14:59:12 +01:00
committed by GitHub
10 changed files with 171 additions and 15 deletions

View File

@@ -110,9 +110,30 @@ class StringLiteral extends Literal, @string__ {
class SymbolLiteral extends Literal {
final override SymbolLiteral::Range range;
SymbolLiteral() {
not any(UndefStmt u).getAMethodName() = this and
not any(AliasStmt a).getNewName() = this and
not any(AliasStmt a).getOldName() = this
}
final override string getAPrimaryQlClass() { result = "SymbolLiteral" }
}
/**
* A method name literal. For example:
* ```rb
* - method_name # a normal name
* - + # an operator
* - :method_name # a symbol
* - :"eval_#{name}" # a complex symbol
* ```
*/
class MethodName extends Literal {
final override MethodName::Range range;
final override string getAPrimaryQlClass() { result = "MethodName" }
}
/** A sequence of expressions. */
class StmtSequence extends Expr {
override StmtSequence::Range range;

View File

@@ -59,6 +59,46 @@ class EndBlock extends StmtSequence, @end_block {
final override string getAPrimaryQlClass() { result = "EndBlock" }
}
/**
* An `undef` statement. For example:
* ```rb
* - undef method_name
* - undef &&, :method_name
* - undef :"method_#{ name }"
* ```
*/
class UndefStmt extends Stmt, @undef {
final override UndefStmt::Range range;
/** Gets the `n`th method name to undefine. */
final MethodName getMethodName(int n) { result = range.getMethodName(n) }
/** Gets a method name to undefine. */
final MethodName getAMethodName() { result = getMethodName(_) }
final override string getAPrimaryQlClass() { result = "UndefStmt" }
}
/**
* An `alias` statement. For example:
* ```rb
* - alias alias_name method_name
* - alias foo :method_name
* - alias bar :"method_#{ name }"
* ```
*/
class AliasStmt extends Stmt, @alias {
final override AliasStmt::Range range;
/** Gets the new method name. */
final MethodName getNewName() { result = range.getNewName() }
/** Gets the original method name. */
final MethodName getOldName() { result = range.getOldName() }
final override string getAPrimaryQlClass() { result = "AliasStmt" }
}
/**
* A statement that may return a value: `return`, `break` and `next`.
*

View File

@@ -31,8 +31,6 @@ module AstNode {
or
this = any(Generated::RestAssignment ra).getChild()
or
this instanceof Generated::Alias
or
this instanceof Generated::SymbolArray
or
this instanceof Generated::Interpolation
@@ -55,10 +53,6 @@ module AstNode {
or
this instanceof Generated::Character
or
this = any(Generated::Alias a).getName()
or
this = any(Generated::Alias a).getAlias()
or
this instanceof Generated::HeredocBody
or
this instanceof Generated::HeredocBeginning
@@ -72,10 +66,6 @@ module AstNode {
this instanceof Generated::RescueModifier
or
this instanceof Generated::Subshell
or
this instanceof Generated::Undef
or
this = any(Generated::Undef u).getChild(_)
}
override string toString() { result = "AstNode" }

View File

@@ -172,6 +172,36 @@ module SymbolLiteral {
}
}
module MethodName {
private class TokenTypes =
@setter or @token_class_variable or @token_constant or @token_global_variable or
@token_identifier or @token_instance_variable or @token_operator;
abstract class Range extends Literal::Range, @underscore_method_name {
Range() {
exists(Generated::Undef u | u.getChild(_) = generated)
or
exists(Generated::Alias a | a.getName() = generated or a.getAlias() = generated)
}
}
private class TokenMethodName extends MethodName::Range, TokenTypes {
final override Generated::UnderscoreMethodName generated;
final override string getValueText() {
result = generated.(Generated::Token).getValue()
or
result = generated.(Generated::Setter).getName().getValue() + "="
}
}
private class SimpleSymbolMethodName extends MethodName::Range, SymbolLiteral::SimpleSymbolRange,
@token_simple_symbol { }
private class DelimitedSymbolMethodName extends MethodName::Range,
SymbolLiteral::DelimitedSymbolRange, @delimited_symbol { }
}
module StmtSequence {
abstract class Range extends Expr::Range {
abstract Stmt getStmt(int n);

View File

@@ -17,7 +17,6 @@ module Method {
string getName() {
result = generated.getName().(Generated::Token).getValue() or
result = generated.getName().(SymbolLiteral).getValueText() or
result = generated.getName().(Generated::Setter).getName().getValue() + "="
}

View File

@@ -25,6 +25,28 @@ module EndBlock {
}
}
module UndefStmt {
class Range extends Stmt::Range, @undef {
final override Generated::Undef generated;
final MethodName getMethodName(int n) { result = generated.getChild(n) }
final override string toString() { result = "undef ..." }
}
}
module AliasStmt {
class Range extends Stmt::Range, @alias {
final override Generated::Alias generated;
final MethodName getNewName() { result = generated.getName() }
final MethodName getOldName() { result = generated.getAlias() }
final override string toString() { result = "alias ..." }
}
}
module ReturningStmt {
abstract class Range extends Stmt::Range {
abstract Generated::ArgumentList getArgumentList();

View File

@@ -0,0 +1,21 @@
undef
| misc.rb:3:1:3:30 | undef ... | 0 | misc.rb:3:7:3:9 | foo | foo | MethodName |
| misc.rb:3:1:3:30 | undef ... | 1 | misc.rb:3:12:3:15 | :foo | foo | MethodName |
| misc.rb:3:1:3:30 | undef ... | 2 | misc.rb:3:18:3:21 | foo= | foo= | MethodName |
| misc.rb:3:1:3:30 | undef ... | 3 | misc.rb:3:24:3:25 | [] | [] | MethodName |
| misc.rb:3:1:3:30 | undef ... | 4 | misc.rb:3:28:3:30 | []= | []= | MethodName |
| misc.rb:4:1:4:19 | undef ... | 0 | misc.rb:4:7:4:19 | :"foo_#{...}" | (none) | MethodName |
| misc.rb:5:1:5:35 | undef ... | 0 | misc.rb:5:7:5:9 | nil | nil | MethodName |
| misc.rb:5:1:5:35 | undef ... | 1 | misc.rb:5:12:5:15 | true | true | MethodName |
| misc.rb:5:1:5:35 | undef ... | 2 | misc.rb:5:18:5:22 | false | false | MethodName |
| misc.rb:5:1:5:35 | undef ... | 3 | misc.rb:5:25:5:29 | super | super | MethodName |
| misc.rb:5:1:5:35 | undef ... | 4 | misc.rb:5:32:5:35 | self | self | MethodName |
alias
| misc.rb:7:1:7:14 | alias ... | new | misc.rb:7:7:7:9 | new | new | MethodName |
| misc.rb:7:1:7:14 | alias ... | old | misc.rb:7:11:7:14 | :old | old | MethodName |
| misc.rb:8:1:8:14 | alias ... | new | misc.rb:8:7:8:10 | foo= | foo= | MethodName |
| misc.rb:8:1:8:14 | alias ... | old | misc.rb:8:12:8:14 | []= | []= | MethodName |
| misc.rb:9:1:9:16 | alias ... | new | misc.rb:9:7:9:11 | super | super | MethodName |
| misc.rb:9:1:9:16 | alias ... | old | misc.rb:9:13:9:16 | self | self | MethodName |
| misc.rb:10:1:10:24 | alias ... | new | misc.rb:10:7:10:17 | :"\\n#{...}" | (none) | MethodName |
| misc.rb:10:1:10:24 | alias ... | old | misc.rb:10:19:10:24 | :foo | foo | MethodName |

View File

@@ -0,0 +1,23 @@
import ruby
private string getValueText(MethodName m) {
result = m.getValueText()
or
not exists(m.getValueText()) and result = "(none)"
}
query predicate undef(UndefStmt u, int i, MethodName m, string name, string pClass) {
pClass = m.getAPrimaryQlClass() and
u.getMethodName(i) = m and
name = getValueText(m)
}
query predicate alias(AliasStmt a, string prop, MethodName m, string name, string pClass) {
pClass = m.getAPrimaryQlClass() and
name = getValueText(m) and
(
a.getOldName() = m and prop = "old"
or
a.getNewName() = m and prop = "new"
)
}

View File

@@ -0,0 +1,10 @@
bar = "bar"
undef foo, :foo, foo=, [], []=
undef :"foo_#{bar}"
undef nil, true, false, super, self
alias new :old
alias foo= []=
alias super self
alias :"\n#{bar}" :"foo"

View File

@@ -566,12 +566,12 @@ case.rb:
cfg.rb:
# 1| bar
#-----| -> Alias
#-----| -> alias ...
# 1| bar
#-----| -> bar
# 3| Alias
# 3| alias ...
#-----| -> foo
# 3| foo
@@ -1793,7 +1793,7 @@ cfg.rb:
#-----| -> ! ...
# 165| ... = ...
#-----| -> Undef
#-----| -> undef ...
# 165| x
#-----| -> ... = ...
@@ -1804,7 +1804,7 @@ cfg.rb:
# 165| 42
#-----| -> - ...
# 167| Undef
# 167| undef ...
#-----| -> two_parameters
# 167| two_parameters