Thanks to visit codestin.com
Credit goes to github.com

Skip to content

Commit 156964b

Browse files
committed
Ruby: add getEnclosingModule and getNestedModule
1 parent 67772bb commit 156964b

2 files changed

Lines changed: 57 additions & 0 deletions

File tree

ruby/ql/lib/codeql/ruby/ast/Module.qll

Lines changed: 38 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -118,6 +118,44 @@ class Module extends TModule {
118118
or
119119
result.(SelfVariableAccess).getVariable().getDeclaringScope() = this.getAnOwnSingletonMethod()
120120
}
121+
122+
pragma[nomagic]
123+
private string getEnclosingModuleName() {
124+
exists(string qname |
125+
qname = this.getQualifiedName() and
126+
result = qname.regexpReplaceAll("::[^:]*$", "") and
127+
qname != result
128+
)
129+
}
130+
131+
pragma[nomagic]
132+
private string getOwnModuleName() {
133+
result = this.getQualifiedName().regexpReplaceAll("^.*::", "")
134+
}
135+
136+
/**
137+
* Gets the enclosing module, as it appears in the qualified name of this module.
138+
*
139+
* For example, the canonical enclosing module of `A::B` is `A`, and `A` itself has no canonical enclosing module.
140+
*/
141+
pragma[nomagic]
142+
Module getCanonicalEnclosingModule() { result.getQualifiedName() = this.getEnclosingModuleName() }
143+
144+
/**
145+
* Gets a module named `name` declared inside this one (not aliased), provided
146+
* that such a module is defined or reopened in the current codebase.
147+
*
148+
* For example, for `A::B` the canonical nested module named `C` would be `A::B::C`.
149+
*
150+
* Note that this is not the same as constant lookup. If `A::B::C` would resolve to a
151+
* module whose qualified name is not `A::B::C`, then it will not be found by
152+
* this predicate.
153+
*/
154+
pragma[nomagic]
155+
Module getCanonicalNestedModule(string name) {
156+
result.getCanonicalEnclosingModule() = this and
157+
result.getOwnModuleName() = name
158+
}
121159
}
122160

123161
/**

ruby/ql/lib/codeql/ruby/dataflow/internal/DataFlowPublic.qll

Lines changed: 19 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -857,6 +857,25 @@ class ModuleNode instanceof Module {
857857
* from ancestors.
858858
*/
859859
MethodNode getAnInstanceMethod() { result = this.getInstanceMethod(_) }
860+
861+
/**
862+
* Gets the enclosing module, as it appears in the qualified name of this module.
863+
*
864+
* For example, the canonical enclosing module of `A::B` is `A`, and `A` itself has no canonical enclosing module.
865+
*/
866+
ModuleNode getCanonicalEnclosingModule() { result = super.getCanonicalEnclosingModule() }
867+
868+
/**
869+
* Gets a module named `name` declared inside this one (not aliased), provided
870+
* that such a module is defined or reopened in the current codebase.
871+
*
872+
* For example, for `A::B` the canonical nested module named `C` would be `A::B::C`.
873+
*
874+
* Note that this is not the same as constant lookup. If `A::B::C` would resolve to a
875+
* module whose qualified name is not `A::B::C`, then it will not be found by
876+
* this predicate.
877+
*/
878+
ModuleNode getCanonicalNestedModule(string name) { result = super.getCanonicalNestedModule(name) }
860879
}
861880

862881
/**

0 commit comments

Comments
 (0)