deduplicate string constantQualifiedName(ConstantWriteAccess) as string ConstantWriteAccess#getQualifiedName

This commit is contained in:
Alex Ford
2021-10-07 11:11:44 +01:00
parent 5b38e06765
commit 168e67dd6d
5 changed files with 48 additions and 40 deletions

View File

@@ -166,6 +166,35 @@ class ConstantWriteAccess extends ConstantAccess {
}
override string getAPrimaryQlClass() { result = "ConstantWriteAccess" }
/**
* Gets the fully qualified name for this constant, based on the context in
* which it is defined.
*
* For example, given
* ```rb
* module Foo
* module Bar
* class Baz
* end
* end
* CONST_A = "a"
* end
* ```
*
* the constant `Baz` has the fully qualified name `Foo::Bar::Baz`, and
* `CONST_A` has the fully qualified name `Foo::CONST_A`.
*/
string getQualifiedName() {
/* get the qualified name for the parent module, then append w */
exists(ConstantWriteAccess parent | parent = this.getEnclosingModule() |
result = parent.getQualifiedName() + "::" + this.getName()
)
or
/* base case - there's no parent module */
not exists(ConstantWriteAccess parent | parent = this.getEnclosingModule()) and
result = this.getName()
}
}
/**

View File

@@ -216,18 +216,6 @@ class ActiveRecordSqlExecutionRange extends SqlExecution::Range {
// TODO: model `ActiveRecord` sanitizers
// https://api.rubyonrails.org/classes/ActiveRecord/Sanitization/ClassMethods.html
// TODO: factor this out
private string constantQualifiedName(ConstantWriteAccess w) {
/* get the qualified name for the parent module, then append w */
exists(ConstantWriteAccess parent | parent = w.getEnclosingModule() |
result = constantQualifiedName(parent) + "::" + w.getName()
)
or
/* base case - there's no parent module */
not exists(ConstantWriteAccess parent | parent = w.getEnclosingModule()) and
result = w.getName()
}
/**
* A node that may evaluate to one or more `ActiveRecordModelClass` instances.
*/
@@ -290,7 +278,7 @@ private class ActiveRecordModelFinderCall extends ActiveRecordModelInstantiation
ActiveRecordModelFinderCall() {
call = this.asExpr().getExpr() and
recv = getUltimateReceiver(call) and
resolveConstant(recv) = constantQualifiedName(cls) and
resolveConstant(recv) = cls.getQualifiedName() and
call.getMethodName() = finderMethodName()
}

View File

@@ -65,32 +65,6 @@ newtype DefLoc =
not exists(MethodBase m | m.getAChild+() = write)
}
/**
* Gets the fully qualified name for a constant, based on the context in which it is defined.
*
* For example, given
* ```ruby
* module Foo
* module Bar
* class Baz
* end
* end
* end
* ```
*
* the constant `Baz` has the fully qualified name `Foo::Bar::Baz`.
*/
string constantQualifiedName(ConstantWriteAccess w) {
/* get the qualified name for the parent module, then append w */
exists(ConstantWriteAccess parent | parent = w.getEnclosingModule() |
result = constantQualifiedName(parent) + "::" + w.getName()
)
or
/* base case - there's no parent module */
not exists(ConstantWriteAccess parent | parent = w.getEnclosingModule()) and
result = w.getName()
}
/**
* Gets the constant write that defines the given constant.
* Modules often don't have a unique definition, as they are opened multiple times in different
@@ -100,7 +74,7 @@ string constantQualifiedName(ConstantWriteAccess w) {
ConstantWriteAccess definitionOf(ConstantReadAccess r) {
result =
min(ConstantWriteAccess w |
constantQualifiedName(w) = resolveConstant(r)
w.getQualifiedName() = resolveConstant(r)
|
w order by w.getLocation().toString()
)

View File

@@ -55,3 +55,16 @@ constantValue
| constants.rb:39:6:39:31 | MAX_SIZE | constants.rb:37:30:37:33 | 1024 |
| constants.rb:41:6:41:13 | GREETING | constants.rb:17:12:17:64 | ... + ... |
| constants.rb:42:6:42:15 | GREETING | constants.rb:17:12:17:64 | ... + ... |
constantWriteAccessQualifiedName
| constants.rb:1:1:15:3 | ModuleA | ModuleA |
| constants.rb:2:5:4:7 | ClassA | ModuleA::ClassA |
| constants.rb:3:9:3:15 | CONST_A | ModuleA::ClassA::CONST_A |
| constants.rb:6:5:6:11 | CONST_B | ModuleA::CONST_B |
| constants.rb:8:5:14:7 | ModuleB | ModuleA::ModuleB |
| constants.rb:9:9:10:11 | ClassB | ModuleA::ModuleB::ClassB |
| constants.rb:12:9:13:11 | ClassC | ModuleA::ModuleB::ClassC |
| constants.rb:17:1:17:8 | GREETING | GREETING |
| constants.rb:20:5:20:9 | Names | Names |
| constants.rb:31:1:32:3 | ClassD | ClassD |
| constants.rb:34:1:35:3 | ModuleC | ModuleC |
| constants.rb:37:1:37:26 | MAX_SIZE | MAX_SIZE |

View File

@@ -16,3 +16,7 @@ query Expr getConst(Module m, string name) { result = M::ExposedForTestingOnly::
query Expr lookupConst(Module m, string name) { result = M::lookupConst(m, name) }
query predicate constantValue(ConstantReadAccess a, Expr e) { e = a.getValue() }
query predicate constantWriteAccessQualifiedName(ConstantWriteAccess w, string qualifiedName) {
w.getQualifiedName() = qualifiedName
}