@@ -29,7 +29,11 @@ import semmle.python.dataflow.new.DataFlow::DataFlow as DataFlow
2929/**
3030 * Holds if models describing `type` may be relevant for the analysis of this database.
3131 */
32- predicate isTypeUsed ( string type ) { API:: moduleImportExists ( type ) }
32+ bindingset [ type]
33+ predicate isTypeUsed ( string type ) {
34+ // If `type` is a path, then it is the first component that should be imported.
35+ API:: moduleImportExists ( type .splitAt ( "." , 0 ) )
36+ }
3337
3438/**
3539 * Holds if `type` can be obtained from an instance of `otherType` due to
@@ -41,8 +45,59 @@ predicate hasImplicitTypeModel(string type, string otherType) { none() }
4145bindingset [ type, path]
4246API:: Node getExtraNodeFromPath ( string type , AccessPath path , int n ) { none ( ) }
4347
48+ /**
49+ * Holds if `type` = `typePath`+`suffix` and `suffix` is either empty or "!".
50+ */
51+ bindingset [ type]
52+ private predicate parseType ( string type , string typePath , string suffix ) {
53+ exists ( string regexp |
54+ regexp = "([^!]+)(!|)" and
55+ typePath = type .regexpCapture ( regexp , 1 ) and
56+ suffix = type .regexpCapture ( regexp , 2 )
57+ )
58+ }
59+
60+ private predicate parseRelevantType ( string type , string typePath , string suffix ) {
61+ isRelevantType ( type ) and
62+ parseType ( type , typePath , suffix )
63+ }
64+
65+ pragma [ nomagic]
66+ private string getTypePathComponent ( string typePath , int n ) {
67+ parseRelevantType ( _, typePath , _) and
68+ result = typePath .splitAt ( "." , n )
69+ }
70+
71+ private int getNumTypePathomponents ( string typePath ) {
72+ result = strictcount ( int n | exists ( getTypePathComponent ( typePath , n ) ) )
73+ }
74+
75+ private API:: Node getNodeFromTypePath ( string typePath , int n ) {
76+ n = 1 and
77+ result = API:: moduleImport ( getTypePathComponent ( typePath , 0 ) )
78+ or
79+ result = getNodeFromTypePath ( typePath , n - 1 ) .getMember ( getTypePathComponent ( typePath , n - 1 ) )
80+ }
81+
82+ private API:: Node getNodeFromTypePath ( string typePath ) {
83+ result = getNodeFromTypePath ( typePath , getNumTypePathomponents ( typePath ) )
84+ }
85+
4486/** Gets a Python-specific interpretation of the given `type`. */
45- API:: Node getExtraNodeFromType ( string type ) { result = API:: moduleImport ( type ) }
87+ API:: Node getExtraNodeFromType ( string type ) {
88+ result = API:: moduleImport ( type )
89+ or
90+ exists ( string typePath , string suffix , API:: Node node |
91+ parseRelevantType ( type , typePath , suffix ) and
92+ node = getNodeFromTypePath ( typePath )
93+ |
94+ suffix = "!" and
95+ result = node
96+ or
97+ suffix = "" and
98+ result = node .getAnInstance ( )
99+ )
100+ }
46101
47102/**
48103 * Gets a Python-specific API graph successor of `node` reachable by resolving `token`.
0 commit comments