mirror of
https://github.com/github/codeql.git
synced 2025-12-20 02:44:30 +01:00
This turned out to be fairly simple. Given an import such as ```python from foo.bar.baz import quux ``` we create an API-graph node for each valid dotted prefix of `foo.bar.baz`, i.e. `foo`, `foo.bar`, and `foo.bar.baz`. For these, we then insert nodes in the API graph, such that `foo` steps to `foo.bar` along an edge labeled `bar`, etc. Finally, we only allow undotted names to hang off of the API-graph root. Thus, `foo` will have a `moduleImport` edge off of the root, and a `getMember` edge for `bar` (which in turn has a `getMember` edge for `baz`). Relative imports are explicitly ignored. Finally, this commit also adds inline tests for a variety of ways of importing modules, including a copy of the "import-helper" tests (with a few modifications to allow a single annotation per line, as these get rather long quickly!).
31 lines
939 B
Plaintext
31 lines
939 B
Plaintext
import python
|
|
import semmle.python.dataflow.new.DataFlow
|
|
import TestUtilities.InlineExpectationsTest
|
|
import semmle.python.ApiGraphs
|
|
|
|
class ApiUseTest extends InlineExpectationsTest {
|
|
ApiUseTest() { this = "ApiUseTest" }
|
|
|
|
override string getARelevantTag() { result = "use" }
|
|
|
|
private predicate relevant_node(API::Node a, DataFlow::Node n, Location l) {
|
|
n = a.getAUse() and l = n.getLocation()
|
|
}
|
|
|
|
override predicate hasActualResult(Location location, string element, string tag, string value) {
|
|
exists(API::Node a, DataFlow::Node n | relevant_node(a, n, location) |
|
|
tag = "use" and
|
|
// Only report the longest path on this line:
|
|
value =
|
|
max(API::Node a2, Location l2 |
|
|
relevant_node(a2, _, l2) and
|
|
l2.getFile() = location.getFile() and
|
|
l2.getStartLine() = location.getStartLine()
|
|
|
|
|
a2.getPath()
|
|
) and
|
|
element = n.toString()
|
|
)
|
|
}
|
|
}
|