mirror of
https://github.com/github/codeql.git
synced 2026-04-25 08:45:14 +02:00
Merge pull request #19051 from hvitved/rust/path-resolution-cross-crate
Rust: Path resolution improvements
This commit is contained in:
@@ -1,7 +1,7 @@
|
||||
use lib::a_module::hello;
|
||||
use lib::a_module::hello; // $ item=HELLO
|
||||
|
||||
mod a_module;
|
||||
|
||||
fn main() {
|
||||
hello();
|
||||
hello(); // $ item=HELLO
|
||||
}
|
||||
|
||||
@@ -1,3 +1,3 @@
|
||||
pub fn hello() {
|
||||
println!("Hello, world!");
|
||||
}
|
||||
} // HELLO
|
||||
|
||||
@@ -0,0 +1 @@
|
||||
import utils.test.PathResolutionInlineExpectationsTest
|
||||
@@ -2,14 +2,23 @@
|
||||
"sysroot_src": "filled by the rust_project fixture",
|
||||
"crates": [
|
||||
{
|
||||
"display_name": "exe",
|
||||
"version": "0.1.0",
|
||||
"root_module": "exe/src/main.rs",
|
||||
"edition": "2021",
|
||||
"deps": [{"crate": 1, "name": "lib"}]
|
||||
"deps": [
|
||||
{
|
||||
"crate": 1,
|
||||
"name": "lib"
|
||||
}
|
||||
]
|
||||
},
|
||||
{
|
||||
"display_name": "lib",
|
||||
"version": "0.1.0",
|
||||
"root_module": "lib/src/lib.rs",
|
||||
"edition": "2021",
|
||||
"deps": []
|
||||
}
|
||||
]
|
||||
}
|
||||
}
|
||||
@@ -1,4 +1,4 @@
|
||||
| Elements extracted | 87 |
|
||||
| Elements extracted | 90 |
|
||||
| Elements unextracted | 0 |
|
||||
| Extraction errors | 0 |
|
||||
| Extraction warnings | 0 |
|
||||
|
||||
@@ -1,4 +1,4 @@
|
||||
| Elements extracted | 87 |
|
||||
| Elements extracted | 90 |
|
||||
| Elements unextracted | 0 |
|
||||
| Extraction errors | 0 |
|
||||
| Extraction warnings | 0 |
|
||||
|
||||
@@ -13,6 +13,7 @@ private import codeql.rust.elements.internal.generated.Crate
|
||||
module Impl {
|
||||
private import rust
|
||||
private import codeql.rust.elements.internal.NamedCrate
|
||||
private import codeql.rust.internal.PathResolution
|
||||
|
||||
class Crate extends Generated::Crate {
|
||||
override string toStringImpl() {
|
||||
@@ -58,6 +59,14 @@ module Impl {
|
||||
*/
|
||||
Crate getADependency() { result = this.getDependency(_) }
|
||||
|
||||
/** Gets the source file that defines this crate, if any. */
|
||||
SourceFile getSourceFile() { result.getFile() = this.getModule().getFile() }
|
||||
|
||||
/**
|
||||
* Gets a source file that belongs to this crate, if any.
|
||||
*/
|
||||
SourceFile getASourceFile() { result = this.(CrateItemNode).getASourceFile() }
|
||||
|
||||
override Location getLocation() { result = this.getModule().getLocation() }
|
||||
}
|
||||
}
|
||||
|
||||
@@ -73,7 +73,7 @@ final class Namespace extends TNamespace {
|
||||
* - https://doc.rust-lang.org/reference/visibility-and-privacy.html
|
||||
* - https://doc.rust-lang.org/reference/names/namespaces.html
|
||||
*/
|
||||
abstract class ItemNode extends AstNode {
|
||||
abstract class ItemNode extends Locatable {
|
||||
/** Gets the (original) name of this item. */
|
||||
abstract string getName();
|
||||
|
||||
@@ -109,7 +109,11 @@ abstract class ItemNode extends AstNode {
|
||||
|
||||
/** Gets the immediately enclosing module (or source file) of this item. */
|
||||
pragma[nomagic]
|
||||
ModuleLikeNode getImmediateParentModule() { this = result.getAnItemInScope() }
|
||||
ModuleLikeNode getImmediateParentModule() {
|
||||
this = result.getAnItemInScope()
|
||||
or
|
||||
result = this.(SourceFileItemNode).getSuper()
|
||||
}
|
||||
|
||||
pragma[nomagic]
|
||||
private ItemNode getASuccessorRec(string name) {
|
||||
@@ -122,6 +126,10 @@ abstract class ItemNode extends AstNode {
|
||||
or
|
||||
useImportEdge(this, name, result)
|
||||
or
|
||||
crateDefEdge(this, name, result)
|
||||
or
|
||||
crateDependencyEdge(this, name, result)
|
||||
or
|
||||
// items made available through `use` are available to nodes that contain the `use`
|
||||
exists(UseItemNode use |
|
||||
use = this.getASuccessorRec(_) and
|
||||
@@ -168,19 +176,18 @@ abstract class ItemNode extends AstNode {
|
||||
result = this.getASuccessorRec(name)
|
||||
or
|
||||
name = "super" and
|
||||
if this instanceof Module
|
||||
if this instanceof Module or this instanceof SourceFile
|
||||
then result = this.getImmediateParentModule()
|
||||
else result = this.getImmediateParentModule().getImmediateParentModule()
|
||||
or
|
||||
name = "self" and
|
||||
not this instanceof Module and
|
||||
result = this.getImmediateParentModule()
|
||||
if this instanceof Module then result = this else result = this.getImmediateParentModule()
|
||||
or
|
||||
name = "Self" and
|
||||
this = result.(ImplOrTraitItemNode).getAnItemInSelfScope()
|
||||
or
|
||||
name = "crate" and
|
||||
result.(SourceFileItemNode).getFile() = this.getFile()
|
||||
this = result.(CrateItemNode).getASourceFile()
|
||||
}
|
||||
|
||||
/** Gets the location of this item. */
|
||||
@@ -203,6 +210,11 @@ abstract private class ModuleLikeNode extends ItemNode {
|
||||
}
|
||||
|
||||
private class SourceFileItemNode extends ModuleLikeNode, SourceFile {
|
||||
pragma[nomagic]
|
||||
ModuleLikeNode getSuper() {
|
||||
result = any(ModuleItemNode mod | fileImport(mod, this)).getASuccessor("super")
|
||||
}
|
||||
|
||||
override string getName() { result = "(source file)" }
|
||||
|
||||
override Namespace getNamespace() {
|
||||
@@ -211,6 +223,55 @@ private class SourceFileItemNode extends ModuleLikeNode, SourceFile {
|
||||
|
||||
override Visibility getVisibility() { none() }
|
||||
|
||||
override predicate isPublic() { any() }
|
||||
|
||||
override TypeParam getTypeParam(int i) { none() }
|
||||
}
|
||||
|
||||
class CrateItemNode extends ItemNode instanceof Crate {
|
||||
/**
|
||||
* Gets the module node that defines this crate.
|
||||
*
|
||||
* This is either a source file, when the crate is defined in source code,
|
||||
* or a module, when the crate is defined in a dependency.
|
||||
*/
|
||||
pragma[nomagic]
|
||||
ModuleLikeNode getModuleNode() {
|
||||
result = super.getSourceFile()
|
||||
or
|
||||
not exists(super.getSourceFile()) and
|
||||
result = super.getModule()
|
||||
}
|
||||
|
||||
/**
|
||||
* Gets a source file that belongs to this crate, if any.
|
||||
*
|
||||
* This is calculated as those source files that can be reached from the entry
|
||||
* file of this crate using zero or more `mod` imports, without going through
|
||||
* the entry point of some other crate.
|
||||
*/
|
||||
pragma[nomagic]
|
||||
SourceFileItemNode getASourceFile() {
|
||||
result = super.getSourceFile()
|
||||
or
|
||||
exists(SourceFileItemNode mid, Module mod |
|
||||
mid = this.getASourceFile() and
|
||||
mod.getFile() = mid.getFile() and
|
||||
fileImport(mod, result) and
|
||||
not result = any(Crate other).getSourceFile()
|
||||
)
|
||||
}
|
||||
|
||||
override string getName() { result = Crate.super.getName() }
|
||||
|
||||
override Namespace getNamespace() {
|
||||
result.isType() // can be referenced with `crate`
|
||||
}
|
||||
|
||||
override Visibility getVisibility() { none() }
|
||||
|
||||
override predicate isPublic() { any() }
|
||||
|
||||
override TypeParam getTypeParam(int i) { none() }
|
||||
}
|
||||
|
||||
@@ -460,7 +521,7 @@ private class UseItemNode extends ItemNode instanceof Use {
|
||||
|
||||
override Namespace getNamespace() { none() }
|
||||
|
||||
override Visibility getVisibility() { none() }
|
||||
override Visibility getVisibility() { result = Use.super.getVisibility() }
|
||||
|
||||
override TypeParam getTypeParam(int i) { none() }
|
||||
}
|
||||
@@ -586,11 +647,33 @@ private predicate fileImport(Module m, SourceFile f) {
|
||||
* Holds if `mod` is a `mod name;` item targeting a file resulting in `item` being
|
||||
* in scope under the name `name`.
|
||||
*/
|
||||
pragma[nomagic]
|
||||
private predicate fileImportEdge(Module mod, string name, ItemNode item) {
|
||||
item.isPublic() and
|
||||
exists(SourceFile f |
|
||||
exists(SourceFileItemNode f |
|
||||
fileImport(mod, f) and
|
||||
sourceFileEdge(f, name, item)
|
||||
item = f.getASuccessor(name)
|
||||
)
|
||||
}
|
||||
|
||||
/**
|
||||
* Holds if crate `c` defines the item `i` named `name`.
|
||||
*/
|
||||
pragma[nomagic]
|
||||
private predicate crateDefEdge(CrateItemNode c, string name, ItemNode i) {
|
||||
i = c.getModuleNode().getASuccessor(name) and
|
||||
not i instanceof Crate
|
||||
}
|
||||
|
||||
/**
|
||||
* Holds if `m` depends on crate `dep` named `name`.
|
||||
*/
|
||||
private predicate crateDependencyEdge(ModuleLikeNode m, string name, CrateItemNode dep) {
|
||||
exists(CrateItemNode c | dep = c.(Crate).getDependency(name) |
|
||||
// entry module/entry source file
|
||||
m = c.getModuleNode()
|
||||
or
|
||||
// entry/transitive source file
|
||||
m = c.getASourceFile()
|
||||
)
|
||||
}
|
||||
|
||||
@@ -745,13 +828,53 @@ private predicate pathUsesNamespace(Path p, Namespace n) {
|
||||
)
|
||||
}
|
||||
|
||||
/** Gets the item that `path` resolves to, if any. */
|
||||
cached
|
||||
ItemNode resolvePath(RelevantPath path) {
|
||||
pragma[nomagic]
|
||||
private ItemNode resolvePath1(RelevantPath path) {
|
||||
exists(Namespace ns | result = resolvePath0(path, ns) |
|
||||
pathUsesNamespace(path, ns)
|
||||
or
|
||||
not pathUsesNamespace(path, _)
|
||||
not pathUsesNamespace(path, _) and
|
||||
not path = any(MacroCall mc).getPath()
|
||||
)
|
||||
}
|
||||
|
||||
pragma[nomagic]
|
||||
private ItemNode resolvePathPrivate(
|
||||
RelevantPath path, ModuleLikeNode itemParent, ModuleLikeNode pathParent
|
||||
) {
|
||||
result = resolvePath1(path) and
|
||||
itemParent = result.getImmediateParentModule() and
|
||||
not result.isPublic() and
|
||||
(
|
||||
pathParent.getADescendant() = path
|
||||
or
|
||||
pathParent = any(ItemNode mid | path = mid.getADescendant()).getImmediateParentModule()
|
||||
)
|
||||
}
|
||||
|
||||
/**
|
||||
* Gets a module that has access to private items defined inside `itemParent`.
|
||||
*
|
||||
* According to [The Rust Reference][1] this is either `itemParent` itself or any
|
||||
* descendant of `itemParent`.
|
||||
*
|
||||
* [1]: https://doc.rust-lang.org/reference/visibility-and-privacy.html#r-vis.access
|
||||
*/
|
||||
pragma[nomagic]
|
||||
private ModuleLikeNode getAPrivateVisibleModule(ModuleLikeNode itemParent) {
|
||||
exists(resolvePathPrivate(_, itemParent, _)) and
|
||||
result.getImmediateParentModule*() = itemParent
|
||||
}
|
||||
|
||||
/** Gets the item that `path` resolves to, if any. */
|
||||
cached
|
||||
ItemNode resolvePath(RelevantPath path) {
|
||||
result = resolvePath1(path) and
|
||||
result.isPublic()
|
||||
or
|
||||
exists(ModuleLikeNode itemParent, ModuleLikeNode pathParent |
|
||||
result = resolvePathPrivate(path, itemParent, pathParent) and
|
||||
pathParent = getAPrivateVisibleModule(itemParent)
|
||||
)
|
||||
}
|
||||
|
||||
@@ -831,3 +954,44 @@ private predicate useImportEdge(Use use, string name, ItemNode item) {
|
||||
name != "_"
|
||||
)
|
||||
}
|
||||
|
||||
/** Provides predicates for debugging the path resolution implementation. */
|
||||
private module Debug {
|
||||
private Locatable getRelevantLocatable() {
|
||||
exists(string filepath, int startline, int startcolumn, int endline, int endcolumn |
|
||||
result.getLocation().hasLocationInfo(filepath, startline, startcolumn, endline, endcolumn) and
|
||||
filepath.matches("%/main.rs") and
|
||||
startline = 1
|
||||
)
|
||||
}
|
||||
|
||||
predicate debugUnqualifiedPathLookup(RelevantPath p, string name, Namespace ns, ItemNode encl) {
|
||||
p = getRelevantLocatable() and
|
||||
unqualifiedPathLookup(p, name, ns, encl)
|
||||
}
|
||||
|
||||
ItemNode debugResolvePath(RelevantPath path) {
|
||||
path = getRelevantLocatable() and
|
||||
result = resolvePath(path)
|
||||
}
|
||||
|
||||
predicate debugUseImportEdge(Use use, string name, ItemNode item) {
|
||||
use = getRelevantLocatable() and
|
||||
useImportEdge(use, name, item)
|
||||
}
|
||||
|
||||
ItemNode debugGetASuccessorRec(ItemNode i, string name) {
|
||||
i = getRelevantLocatable() and
|
||||
result = i.getASuccessor(name)
|
||||
}
|
||||
|
||||
predicate debugFileImportEdge(Module mod, string name, ItemNode item) {
|
||||
mod = getRelevantLocatable() and
|
||||
fileImportEdge(mod, name, item)
|
||||
}
|
||||
|
||||
predicate debugFileImport(Module m, SourceFile f) {
|
||||
m = getRelevantLocatable() and
|
||||
fileImport(m, f)
|
||||
}
|
||||
}
|
||||
|
||||
@@ -7,6 +7,7 @@ private import PathResolution
|
||||
|
||||
/** Holds if `p` may resolve to multiple items including `i`. */
|
||||
query predicate multiplePathResolutions(Path p, ItemNode i) {
|
||||
p.fromSource() and
|
||||
i = resolvePath(p) and
|
||||
// `use foo::bar` may use both a type `bar` and a value `bar`
|
||||
not p =
|
||||
|
||||
@@ -0,0 +1,48 @@
|
||||
/**
|
||||
* Provides an inline expectations test for path resolution.
|
||||
*/
|
||||
|
||||
private import rust
|
||||
private import codeql.rust.internal.PathResolution
|
||||
private import codeql.rust.internal.TypeInference
|
||||
private import utils.test.InlineExpectationsTest
|
||||
|
||||
private module ResolveTest implements TestSig {
|
||||
string getARelevantTag() { result = "item" }
|
||||
|
||||
private predicate itemAt(ItemNode i, string filepath, int line, boolean inMacro) {
|
||||
i.getLocation().hasLocationInfo(filepath, _, _, line, _) and
|
||||
if i.(AstNode).isInMacroExpansion() then inMacro = true else inMacro = false
|
||||
}
|
||||
|
||||
private predicate commmentAt(string text, string filepath, int line) {
|
||||
exists(Comment c |
|
||||
c.getLocation().hasLocationInfo(filepath, line, _, _, _) and
|
||||
c.getCommentText() = text
|
||||
)
|
||||
}
|
||||
|
||||
private predicate item(ItemNode i, string value) {
|
||||
exists(string filepath, int line, boolean inMacro | itemAt(i, filepath, line, inMacro) |
|
||||
commmentAt(value, filepath, line) and inMacro = false
|
||||
or
|
||||
not (commmentAt(_, filepath, line) and inMacro = false) and
|
||||
value = i.getName()
|
||||
)
|
||||
}
|
||||
|
||||
predicate hasActualResult(Location location, string element, string tag, string value) {
|
||||
exists(AstNode n |
|
||||
not n = any(Path parent).getQualifier() and
|
||||
location = n.getLocation() and
|
||||
element = n.toString() and
|
||||
tag = "item"
|
||||
|
|
||||
item(resolvePath(n), value)
|
||||
or
|
||||
item(n.(MethodCallExpr).getStaticTarget(), value)
|
||||
)
|
||||
}
|
||||
}
|
||||
|
||||
import MakeTest<ResolveTest>
|
||||
@@ -59,6 +59,19 @@ private module Compare<ResolvableSig R, CompareSig<R> RustAnalyzer, CompareSig<R
|
||||
|
||||
predicate qlUniqueCount(int c) { c = count(Source s | qlUnique(s)) }
|
||||
|
||||
// debug predicates to find missing targets in QL implementation
|
||||
private module Debug {
|
||||
predicate qlMissing(Source s, Target t) {
|
||||
t = RustAnalyzer::resolve(s) and
|
||||
not t = Ql::resolve(s)
|
||||
}
|
||||
|
||||
predicate qlMissingWithCount(Source s, Target t, int c) {
|
||||
qlMissing(s, t) and
|
||||
c = strictcount(Source s0 | qlMissing(s0, t))
|
||||
}
|
||||
}
|
||||
|
||||
predicate summary(string key, int value) {
|
||||
key = "rust-analyzer unique" and rustAnalyzerUniqueCount(value)
|
||||
or
|
||||
|
||||
@@ -0,0 +1,3 @@
|
||||
multipleStaticCallTargets
|
||||
| regular.rs:29:5:29:9 | s.g(...) | anonymous.rs:15:9:15:22 | fn g |
|
||||
| regular.rs:29:5:29:9 | s.g(...) | regular.rs:13:5:13:18 | fn g |
|
||||
@@ -0,0 +1,3 @@
|
||||
multipleStaticCallTargets
|
||||
| regular.rs:32:5:32:9 | s.g(...) | anonymous.rs:18:9:18:22 | fn g |
|
||||
| regular.rs:32:5:32:9 | s.g(...) | regular.rs:16:5:16:18 | fn g |
|
||||
@@ -495,4 +495,7 @@ fn main() {
|
||||
m15::f(); // $ item=I75
|
||||
m16::f(); // $ item=I83
|
||||
m17::f(); // $ item=I99
|
||||
nested6::f(); // $ item=I116
|
||||
nested8::f(); // $ item=I119
|
||||
my3::f(); // $ item=I200
|
||||
}
|
||||
|
||||
@@ -1,6 +1,12 @@
|
||||
pub mod nested2; // I8
|
||||
|
||||
fn g() {
|
||||
println!("mod.rs::g");
|
||||
println!("my2/mod.rs::g");
|
||||
nested2::nested3::nested4::f(); // $ item=I12
|
||||
} // I9
|
||||
|
||||
pub use nested2::nested5::*; // $ item=I114
|
||||
|
||||
pub use nested2::nested7::nested8::{self}; // $ item=I118
|
||||
|
||||
pub mod my3;
|
||||
|
||||
@@ -0,0 +1,8 @@
|
||||
pub fn f() {
|
||||
println!("my2/my3/mod.rs::f");
|
||||
g(); // $ item=I9
|
||||
h(); // $ item=I25
|
||||
} // I200
|
||||
|
||||
use super::super::h; // $ item=I25
|
||||
use super::g; // $ item=I9
|
||||
@@ -9,3 +9,19 @@ pub mod nested3 {
|
||||
} // I13
|
||||
} // I11
|
||||
} // I10
|
||||
|
||||
pub mod nested5 {
|
||||
pub mod nested6 {
|
||||
pub fn f() {
|
||||
println!("nested2.rs::nested5::nested6::f");
|
||||
} // I116
|
||||
} // I115
|
||||
} // I114
|
||||
|
||||
pub mod nested7 {
|
||||
pub mod nested8 {
|
||||
pub fn f() {
|
||||
println!("nested2.rs::nested7::nested8::f");
|
||||
} // I119
|
||||
} // I118
|
||||
} // I117
|
||||
|
||||
@@ -22,8 +22,13 @@ mod
|
||||
| main.rs:350:1:442:1 | mod m16 |
|
||||
| main.rs:444:1:474:1 | mod m17 |
|
||||
| my2/mod.rs:1:1:1:16 | mod nested2 |
|
||||
| my2/mod.rs:12:1:12:12 | mod my3 |
|
||||
| my2/nested2.rs:1:1:11:1 | mod nested3 |
|
||||
| my2/nested2.rs:2:5:10:5 | mod nested4 |
|
||||
| my2/nested2.rs:13:1:19:1 | mod nested5 |
|
||||
| my2/nested2.rs:14:5:18:5 | mod nested6 |
|
||||
| my2/nested2.rs:21:1:27:1 | mod nested7 |
|
||||
| my2/nested2.rs:22:5:26:5 | mod nested8 |
|
||||
| my.rs:1:1:1:15 | mod nested |
|
||||
| my/nested.rs:1:1:17:1 | mod nested1 |
|
||||
| my/nested.rs:2:5:11:5 | mod nested2 |
|
||||
@@ -46,7 +51,7 @@ resolvePath
|
||||
| main.rs:30:17:30:21 | super | main.rs:18:5:36:5 | mod m2 |
|
||||
| main.rs:30:17:30:24 | ...::f | main.rs:19:9:21:9 | fn f |
|
||||
| main.rs:33:17:33:17 | f | main.rs:19:9:21:9 | fn f |
|
||||
| main.rs:40:9:40:13 | super | main.rs:1:1:498:2 | SourceFile |
|
||||
| main.rs:40:9:40:13 | super | main.rs:1:1:501:2 | SourceFile |
|
||||
| main.rs:40:9:40:17 | ...::m1 | main.rs:13:1:37:1 | mod m1 |
|
||||
| main.rs:40:9:40:21 | ...::m2 | main.rs:18:5:36:5 | mod m2 |
|
||||
| main.rs:40:9:40:24 | ...::g | main.rs:23:9:27:9 | fn g |
|
||||
@@ -58,7 +63,7 @@ resolvePath
|
||||
| main.rs:61:17:61:19 | Foo | main.rs:59:9:59:21 | struct Foo |
|
||||
| main.rs:64:13:64:15 | Foo | main.rs:53:5:53:17 | struct Foo |
|
||||
| main.rs:66:5:66:5 | f | main.rs:55:5:62:5 | fn f |
|
||||
| main.rs:68:5:68:8 | self | main.rs:1:1:498:2 | SourceFile |
|
||||
| main.rs:68:5:68:8 | self | main.rs:1:1:501:2 | SourceFile |
|
||||
| main.rs:68:5:68:11 | ...::i | main.rs:71:1:83:1 | fn i |
|
||||
| main.rs:74:13:74:15 | Foo | main.rs:48:1:48:13 | struct Foo |
|
||||
| main.rs:81:17:81:19 | Foo | main.rs:77:9:79:9 | struct Foo |
|
||||
@@ -72,7 +77,7 @@ resolvePath
|
||||
| main.rs:87:57:87:66 | ...::g | my2/nested2.rs:7:9:9:9 | fn g |
|
||||
| main.rs:87:80:87:86 | nested4 | my2/nested2.rs:2:5:10:5 | mod nested4 |
|
||||
| main.rs:100:5:100:22 | f_defined_in_macro | main.rs:99:18:99:42 | fn f_defined_in_macro |
|
||||
| main.rs:117:13:117:17 | super | main.rs:1:1:498:2 | SourceFile |
|
||||
| main.rs:117:13:117:17 | super | main.rs:1:1:501:2 | SourceFile |
|
||||
| main.rs:117:13:117:21 | ...::m5 | main.rs:103:1:107:1 | mod m5 |
|
||||
| main.rs:118:9:118:9 | f | main.rs:104:5:106:5 | fn f |
|
||||
| main.rs:118:9:118:9 | f | main.rs:110:5:112:5 | fn f |
|
||||
@@ -127,7 +132,7 @@ resolvePath
|
||||
| main.rs:274:16:274:16 | T | main.rs:268:7:268:7 | T |
|
||||
| main.rs:275:14:275:17 | Self | main.rs:266:5:276:5 | trait MyParamTrait |
|
||||
| main.rs:275:14:275:33 | ...::AssociatedType | main.rs:270:9:270:28 | TypeAlias |
|
||||
| main.rs:284:13:284:17 | crate | main.rs:1:1:498:2 | SourceFile |
|
||||
| main.rs:284:13:284:17 | crate | main.rs:0:0:0:0 | Crate(main@0.0.1) |
|
||||
| main.rs:284:13:284:22 | ...::m13 | main.rs:279:1:292:1 | mod m13 |
|
||||
| main.rs:284:13:284:25 | ...::f | main.rs:280:5:280:17 | fn f |
|
||||
| main.rs:284:13:284:25 | ...::f | main.rs:280:19:281:19 | struct f |
|
||||
@@ -218,7 +223,7 @@ resolvePath
|
||||
| main.rs:479:5:479:32 | ...::f | my2/nested2.rs:3:9:5:9 | fn f |
|
||||
| main.rs:480:5:480:5 | f | my2/nested2.rs:3:9:5:9 | fn f |
|
||||
| main.rs:481:5:481:5 | g | my2/nested2.rs:7:9:9:9 | fn g |
|
||||
| main.rs:482:5:482:9 | crate | main.rs:1:1:498:2 | SourceFile |
|
||||
| main.rs:482:5:482:9 | crate | main.rs:0:0:0:0 | Crate(main@0.0.1) |
|
||||
| main.rs:482:5:482:12 | ...::h | main.rs:50:1:69:1 | fn h |
|
||||
| main.rs:483:5:483:6 | m1 | main.rs:13:1:37:1 | mod m1 |
|
||||
| main.rs:483:5:483:10 | ...::m2 | main.rs:18:5:36:5 | mod m2 |
|
||||
@@ -249,10 +254,29 @@ resolvePath
|
||||
| main.rs:496:5:496:10 | ...::f | main.rs:417:5:441:5 | fn f |
|
||||
| main.rs:497:5:497:7 | m17 | main.rs:444:1:474:1 | mod m17 |
|
||||
| main.rs:497:5:497:10 | ...::f | main.rs:468:5:473:5 | fn f |
|
||||
| main.rs:498:5:498:11 | nested6 | my2/nested2.rs:14:5:18:5 | mod nested6 |
|
||||
| main.rs:498:5:498:14 | ...::f | my2/nested2.rs:15:9:17:9 | fn f |
|
||||
| main.rs:499:5:499:11 | nested8 | my2/nested2.rs:22:5:26:5 | mod nested8 |
|
||||
| main.rs:499:5:499:14 | ...::f | my2/nested2.rs:23:9:25:9 | fn f |
|
||||
| main.rs:500:5:500:7 | my3 | my2/mod.rs:12:1:12:12 | mod my3 |
|
||||
| main.rs:500:5:500:10 | ...::f | my2/my3/mod.rs:1:1:5:1 | fn f |
|
||||
| my2/mod.rs:5:5:5:11 | nested2 | my2/mod.rs:1:1:1:16 | mod nested2 |
|
||||
| my2/mod.rs:5:5:5:20 | ...::nested3 | my2/nested2.rs:1:1:11:1 | mod nested3 |
|
||||
| my2/mod.rs:5:5:5:29 | ...::nested4 | my2/nested2.rs:2:5:10:5 | mod nested4 |
|
||||
| my2/mod.rs:5:5:5:32 | ...::f | my2/nested2.rs:3:9:5:9 | fn f |
|
||||
| my2/mod.rs:8:9:8:15 | nested2 | my2/mod.rs:1:1:1:16 | mod nested2 |
|
||||
| my2/mod.rs:8:9:8:24 | ...::nested5 | my2/nested2.rs:13:1:19:1 | mod nested5 |
|
||||
| my2/mod.rs:10:9:10:15 | nested2 | my2/mod.rs:1:1:1:16 | mod nested2 |
|
||||
| my2/mod.rs:10:9:10:24 | ...::nested7 | my2/nested2.rs:21:1:27:1 | mod nested7 |
|
||||
| my2/mod.rs:10:9:10:33 | ...::nested8 | my2/nested2.rs:22:5:26:5 | mod nested8 |
|
||||
| my2/mod.rs:10:37:10:40 | self | my2/nested2.rs:22:5:26:5 | mod nested8 |
|
||||
| my2/my3/mod.rs:3:5:3:5 | g | my2/mod.rs:3:1:6:1 | fn g |
|
||||
| my2/my3/mod.rs:4:5:4:5 | h | main.rs:50:1:69:1 | fn h |
|
||||
| my2/my3/mod.rs:7:5:7:9 | super | my2/mod.rs:1:1:12:13 | SourceFile |
|
||||
| my2/my3/mod.rs:7:5:7:16 | ...::super | main.rs:1:1:501:2 | SourceFile |
|
||||
| my2/my3/mod.rs:7:5:7:19 | ...::h | main.rs:50:1:69:1 | fn h |
|
||||
| my2/my3/mod.rs:8:5:8:9 | super | my2/mod.rs:1:1:12:13 | SourceFile |
|
||||
| my2/my3/mod.rs:8:5:8:12 | ...::g | my2/mod.rs:3:1:6:1 | fn g |
|
||||
| my.rs:3:5:3:10 | nested | my.rs:1:1:1:15 | mod nested |
|
||||
| my.rs:3:5:3:13 | ...::g | my/nested.rs:19:1:22:1 | fn g |
|
||||
| my.rs:11:5:11:5 | g | my/nested.rs:19:1:22:1 | fn g |
|
||||
|
||||
@@ -1,49 +1,8 @@
|
||||
import rust
|
||||
import codeql.rust.internal.PathResolution
|
||||
import codeql.rust.internal.TypeInference
|
||||
import utils.test.InlineExpectationsTest
|
||||
import utils.test.PathResolutionInlineExpectationsTest
|
||||
import TestUtils
|
||||
|
||||
query predicate mod(Module m) { toBeTested(m) }
|
||||
|
||||
query predicate resolvePath(Path p, ItemNode i) { toBeTested(p) and i = resolvePath(p) }
|
||||
|
||||
module ResolveTest implements TestSig {
|
||||
string getARelevantTag() { result = "item" }
|
||||
|
||||
private predicate itemAt(ItemNode i, string filepath, int line, boolean inMacro) {
|
||||
i.getLocation().hasLocationInfo(filepath, _, _, line, _) and
|
||||
if i.isInMacroExpansion() then inMacro = true else inMacro = false
|
||||
}
|
||||
|
||||
private predicate commmentAt(string text, string filepath, int line) {
|
||||
exists(Comment c |
|
||||
c.getLocation().hasLocationInfo(filepath, line, _, _, _) and
|
||||
c.getCommentText() = text
|
||||
)
|
||||
}
|
||||
|
||||
private predicate item(ItemNode i, string value) {
|
||||
exists(string filepath, int line, boolean inMacro | itemAt(i, filepath, line, inMacro) |
|
||||
commmentAt(value, filepath, line) and inMacro = false
|
||||
or
|
||||
not (commmentAt(_, filepath, line) and inMacro = false) and
|
||||
value = i.getName()
|
||||
)
|
||||
}
|
||||
|
||||
predicate hasActualResult(Location location, string element, string tag, string value) {
|
||||
exists(AstNode n |
|
||||
not n = any(Path parent).getQualifier() and
|
||||
location = n.getLocation() and
|
||||
element = n.toString() and
|
||||
tag = "item"
|
||||
|
|
||||
item(resolvePath(n), value)
|
||||
or
|
||||
item(n.(MethodCallExpr).getStaticTarget(), value)
|
||||
)
|
||||
}
|
||||
}
|
||||
|
||||
import MakeTest<ResolveTest>
|
||||
|
||||
Reference in New Issue
Block a user