@@ -29,7 +29,11 @@ import semmle.python.dataflow.new.DataFlow::DataFlow as DataFlow
29
29
/**
30
30
* Holds if models describing `type` may be relevant for the analysis of this database.
31
31
*/
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
+ }
33
37
34
38
/**
35
39
* Holds if `type` can be obtained from an instance of `otherType` due to
@@ -41,8 +45,59 @@ predicate hasImplicitTypeModel(string type, string otherType) { none() }
41
45
bindingset [ type, path]
42
46
API:: Node getExtraNodeFromPath ( string type , AccessPath path , int n ) { none ( ) }
43
47
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
+
44
86
/** 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
+ }
46
101
47
102
/**
48
103
* Gets a Python-specific API graph successor of `node` reachable by resolving `token`.
0 commit comments