Implement method lookup

This commit is contained in:
Arthur Baars
2021-04-13 16:48:06 +02:00
parent 5837af0936
commit bf556a2b53
3 changed files with 105 additions and 0 deletions

View File

@@ -11,6 +11,12 @@ class Method extends TMethod {
/** Get a declaration of this module, if any. */
MethodBase getADeclaration() { result.getMethod() = this }
/** Get the name of this method */
string getName() { this = TInstanceMethod(_, result) }
/** Get the module in which this method is defined */
Module getModule() { this = TInstanceMethod(result, _) }
/** Gets a textual representation of this method. */
string toString() {
exists(Module m, string name |

View File

@@ -11,6 +11,21 @@ class Module extends TModule {
/** Get a declaration of this module, if any. */
ModuleBase getADeclaration() { result.getModule() = this }
/** Get the super class of this module, if any. */
Module getSuperClass() { result = getSuperClass(this) }
/** Get a method defined in this module by name. */
Method getMethod(string name) { result.getName() = name and result.getModule() = this }
/** Look up a method in this module's ancestor chain. */
Method lookupMethod(string name) { result = lookupMethod(this, name) }
/** Get a `prepend`ed module. */
Module getAPrependedModule() { result = getAPrependedModule(this) }
/** Get an `include`d module. */
Module getAnIncludedModule() { result = getAnIncludedModule(this) }
/** Gets a textual representation of this module. */
string toString() {
this = TResolved(result)

View File

@@ -34,6 +34,66 @@ private module Cached {
result = scopeAppend(container, n.getName())
)
}
cached
Module getSuperClass(Module cls) {
cls = TResolved("Object") and result = TResolved("BasicObject")
or
cls = TResolved("Module") and result = TResolved("Object")
or
cls = TResolved("Class") and result = TResolved("Module")
or
not cls = TResolved(builtin()) and
(
exists(ClassDeclaration d |
d = cls.getADeclaration() and
result = resolveScopeExpr(d.getSuperclassExpr())
)
or
result = TResolved("Object") and
forex(ClassDeclaration d | d = cls.getADeclaration() |
not exists(resolveScopeExpr(d.getSuperclassExpr()))
)
)
}
cached
Module getAnIncludedModule(Module m) {
m = TResolved("Object") and result = TResolved("Kernel")
or
exists(IncludeOrPrependCall c |
c.getMethodName() = "include" and
(
m = resolveScopeExpr(c.getReceiver())
or
m = enclosingModule(c).getModule() and
(
c.getReceiver() instanceof Self
or
not exists(c.getReceiver())
)
) and
result = resolveScopeExpr(c.getAnArgument())
)
}
cached
Module getAPrependedModule(Module m) {
exists(IncludeOrPrependCall c |
c.getMethodName() = "prepend" and
(
m = resolveScopeExpr(c.getReceiver())
or
m = enclosingModule(c).getModule() and
(
c.getReceiver() instanceof Self
or
not exists(c.getReceiver())
)
) and
result = resolveScopeExpr(c.getAnArgument())
)
}
}
import Cached
@@ -242,3 +302,27 @@ private string qualifiedModuleName(string container, string name) {
container = "Object" and name = result
)
}
private Module getAncestors(Module m) {
result = m or
result = getAncestors(m.getAnIncludedModule()) or
result = getAncestors(m.getAPrependedModule())
}
private Method lookupMethod0(Module m, string name) {
result = lookupMethod0(m.getAPrependedModule(), name)
or
not exists(getAncestors(m.getAPrependedModule()).getMethod(name)) and
(
result = m.getMethod(name)
or
not exists(m.getMethod(name)) and result = lookupMethod0(m.getAnIncludedModule(), name)
)
}
Method lookupMethod(Module m, string name) {
result = lookupMethod0(m, name)
or
not exists(lookupMethod0(m, name)) and
result = lookupMethod(m.getSuperClass(), name)
}