From a7ddd642eac9396bb9dabdc03a3e6e5413155fa2 Mon Sep 17 00:00:00 2001 From: Arthur Baars Date: Fri, 19 Feb 2021 13:34:27 +0100 Subject: [PATCH] AST: introduce 'Namespace' as super class of Class/Module --- ql/src/codeql_ruby/ast/Module.qll | 174 +++++++++------------ ql/src/codeql_ruby/ast/internal/Module.qll | 23 ++- 2 files changed, 87 insertions(+), 110 deletions(-) diff --git a/ql/src/codeql_ruby/ast/Module.qll b/ql/src/codeql_ruby/ast/Module.qll index bc5b105331b..cfc04371a5e 100644 --- a/ql/src/codeql_ruby/ast/Module.qll +++ b/ql/src/codeql_ruby/ast/Module.qll @@ -53,6 +53,76 @@ class Toplevel extends ModuleBase, @program { final BeginBlock getABeginBlock() { result = getBeginBlock(_) } } +/** + * A class or method definition. + * + * ```rb + * class Foo + * def bar + * end + * end + * module Bar + * class Baz + * end + * end + * ``` + */ +class Namespace extends ModuleBase, ConstantWriteAccess { + override Namespace::Range range; + + override string getAPrimaryQlClass() { result = "Namespace" } + + /** + * Gets the name of the module/class. In the following example, the result is + * `"Foo"`. + * ```rb + * class Foo + * end + * ``` + * + * N.B. in the following example, where the module/class name uses the scope + * resolution operator, the result is the name being resolved, i.e. `"Bar"`. + * Use `getScopeExpr` to get the `Foo` for `Foo`. + * ```rb + * module Foo::Bar + * end + * ``` + */ + override string getName() { result = range.getName() } + + /** + * Gets the scope expression used in the module/class name's scope resolution + * operation, if any. + * + * In the following example, the result is the `Expr` for `Foo`. + * + * ```rb + * module Foo::Bar + * end + * ``` + * + * However, there is no result for the following example, since there is no + * scope resolution operation. + * + * ```rb + * module Baz + * end + * ``` + */ + override Expr getScopeExpr() { result = range.getScopeExpr() } + + /** + * Holds if the module/class name uses the scope resolution operator to access the + * global scope, as in this example: + * + * ```rb + * class ::Foo + * end + * ``` + */ + override predicate hasGlobalScope() { range.hasGlobalScope() } +} + /** * A class definition. * @@ -63,61 +133,11 @@ class Toplevel extends ModuleBase, @program { * end * ``` */ -class Class extends ModuleBase, ConstantWriteAccess { +class Class extends Namespace, @class { final override Class::Range range; final override string getAPrimaryQlClass() { result = "Class" } - /** - * Gets the name of the class. In the following example, the result is - * `"Foo"`. - * ```rb - * class Foo - * end - * ``` - * - * N.B. in the following example, where the class name uses the scope - * resolution operator, the result is the name being resolved, i.e. `"Bar"`. - * Use `getScopeExpr` to get the `Foo` for `Foo`. - * ```rb - * class Foo::Bar - * end - * ``` - */ - final override string getName() { result = range.getName() } - - /** - * Gets the scope expression used in the class name's scope resolution - * operation, if any. - * - * In the following example, the result is the `Expr` for `Foo`. - * - * ```rb - * class Foo::Bar - * end - * ``` - * - * However, there is no result for the following example, since there is no - * scope resolution operation. - * - * ```rb - * class Baz - * end - * ``` - */ - final override Expr getScopeExpr() { result = range.getScopeExpr() } - - /** - * Holds if the class name uses the scope resolution operator to access the - * global scope, as in this example: - * - * ```rb - * class ::Foo - * end - * ``` - */ - final override predicate hasGlobalScope() { range.hasGlobalScope() } - /** * Gets the `Expr` used as the superclass in the class definition, if any. * @@ -190,58 +210,8 @@ class SingletonClass extends ModuleBase, @singleton_class { * end * ``` */ -class Module extends ModuleBase, ConstantWriteAccess, @module { +class Module extends Namespace, @module { final override Module::Range range; final override string getAPrimaryQlClass() { result = "Module" } - - /** - * Gets the name of the module. In the following example, the result is - * `"Foo"`. - * ```rb - * module Foo - * end - * ``` - * - * N.B. in the following example, where the module name uses the scope - * resolution operator, the result is the name being resolved, i.e. `"Bar"`. - * Use `getScopeExpr` to get the `Expr` for `Foo`. - * ```rb - * module Foo::Bar - * end - * ``` - */ - final override string getName() { result = range.getName() } - - /** - * Gets the scope expression used in the module name's scope resolution - * operation, if any. - * - * In the following example, the result is the `Expr` for `Foo`. - * - * ```rb - * module Foo::Bar - * end - * ``` - * - * However, there is no result for the following example, since there is no - * scope resolution operation. - * - * ```rb - * module Baz - * end - * ``` - */ - final override Expr getScopeExpr() { result = range.getScopeExpr() } - - /** - * Holds if the module name uses the scope resolution operator to access the - * global scope, as in this example: - * - * ```rb - * module ::Foo - * end - * ``` - */ - final override predicate hasGlobalScope() { range.hasGlobalScope() } } diff --git a/ql/src/codeql_ruby/ast/internal/Module.qll b/ql/src/codeql_ruby/ast/internal/Module.qll index 79bb29429cd..e5b28b92df2 100644 --- a/ql/src/codeql_ruby/ast/internal/Module.qll +++ b/ql/src/codeql_ruby/ast/internal/Module.qll @@ -8,6 +8,17 @@ module ModuleBase { abstract class Range extends BodyStatement::Range { } } +module Namespace { + abstract class Range extends ModuleBase::Range, ConstantWriteAccess::Range { + override predicate child(string label, AstNode::Range child) { + ModuleBase::Range.super.child(label, child) or + ConstantWriteAccess::Range.super.child(label, child) + } + + override string toString() { result = ModuleBase::Range.super.toString() } + } +} + module Toplevel { class Range extends ModuleBase::Range, @program { final override Generated::Program generated; @@ -34,7 +45,7 @@ module Toplevel { } module Class { - class Range extends ModuleBase::Range, ConstantWriteAccess::Range, @class { + class Range extends Namespace::Range, @class { final override Generated::Class generated; final override Generated::AstNode getChild(int i) { result = generated.getChild(i) } @@ -61,9 +72,7 @@ module Class { final override string toString() { result = this.getName() } override predicate child(string label, AstNode::Range child) { - ModuleBase::Range.super.child(label, child) - or - ConstantWriteAccess::Range.super.child(label, child) + Namespace::Range.super.child(label, child) or label = "getSuperclassExpr" and child = getSuperclassExpr() } @@ -89,7 +98,7 @@ module SingletonClass { } module Module { - class Range extends ModuleBase::Range, ConstantWriteAccess::Range, @module { + class Range extends Namespace::Range, @module { final override Generated::Module generated; final override Generated::AstNode getChild(int i) { result = generated.getChild(i) } @@ -114,9 +123,7 @@ module Module { final override string toString() { result = this.getName() } override predicate child(string label, AstNode::Range child) { - ModuleBase::Range.super.child(label, child) - or - ConstantWriteAccess::Range.super.child(label, child) + Namespace::Range.super.child(label, child) } } }