@@ -12,6 +12,7 @@ module TypeResolution {
1212 * We track through underlying types as an approximate way to handle calls to a type
1313 * that is a union/intersection involving functions.
1414 */
15+ pragma [ nomagic]
1516 Node trackUnderlyingFunctionType ( Function fun ) {
1617 result = fun
1718 or
@@ -139,6 +140,28 @@ module TypeResolution {
139140 )
140141 }
141142
143+ /**
144+ * `ContentSet.getAReadContent` restricted to the content sets and contents relevant for type resolution.
145+ */
146+ pragma [ nomagic]
147+ private DataFlow:: Content getAReadContentRestricted ( DataFlow:: ContentSet cs ) {
148+ valueReadStep ( _, cs , _) and
149+ result = cs .getAReadContent ( ) and
150+ typeMember ( _, result , _)
151+ }
152+
153+ /**
154+ * `valueReadStep` where the `ContentSet` has been mapped to the set of relevant read-contents.
155+ */
156+ pragma [ nomagic]
157+ private predicate valueReadStepOnContent ( Node object , DataFlow:: Content content , Node member ) {
158+ exists ( DataFlow:: ContentSet contents |
159+ valueReadStep ( object , contents , member ) and
160+ content = getAReadContentRestricted ( contents )
161+ )
162+ }
163+
164+ pragma [ nomagic]
142165 predicate callTarget ( InvokeExpr call , Function target ) {
143166 exists ( ClassDefinition cls |
144167 valueHasType ( call .( NewExpr ) .getCallee ( ) , trackClassValue ( cls ) ) and
@@ -198,6 +221,7 @@ module TypeResolution {
198221 )
199222 }
200223
224+ pragma [ nomagic]
201225 predicate contextualType ( Node value , Node type ) {
202226 exists ( LocalVariableLike v |
203227 type = v .getADeclaration ( ) .getTypeAnnotation ( ) and
@@ -239,6 +263,7 @@ module TypeResolution {
239263 /**
240264 * Holds if `value` has the given `type`.
241265 */
266+ cached
242267 predicate valueHasType ( Node value , Node type ) {
243268 value .( BindingPattern ) .getTypeAnnotation ( ) = type
244269 or
@@ -293,11 +318,18 @@ module TypeResolution {
293318 or
294319 exists ( Node mid | valueHasType ( mid , type ) | ValueFlow:: step ( mid , value ) )
295320 or
296- exists ( Node mid , Node midType , DataFlow:: ContentSet contents , Node host |
297- valueReadStep ( mid , contents , value ) and
321+ exists ( DataFlow:: Content content , Node host |
322+ typeMemberHostRead ( host , content , value ) and
323+ typeMember ( host , content , type )
324+ )
325+ }
326+
327+ pragma [ nomagic]
328+ private predicate typeMemberHostRead ( Node host , DataFlow:: Content content , Node target ) {
329+ exists ( Node mid , Node midType |
330+ valueReadStepOnContent ( mid , content , target ) and
298331 valueHasType ( mid , midType ) and
299- typeMemberHostReaches ( host , midType ) and
300- typeMember ( host , contents .getAReadContent ( ) , type )
332+ typeMemberHostReaches ( host , midType )
301333 )
302334 }
303335
@@ -309,6 +341,7 @@ module TypeResolution {
309341 * - a union type has the property if all its members have the property
310342 */
311343 module TrackMustProp< nodeSig / 1 directlyHasProperty> {
344+ pragma [ nomagic]
312345 predicate hasProperty ( Node node ) {
313346 directlyHasProperty ( node )
314347 or
@@ -341,6 +374,7 @@ module TypeResolution {
341374 }
342375
343376 module ValueHasProperty< nodeSig / 1 typeHasProperty> {
377+ pragma [ nomagic]
344378 predicate valueHasProperty ( Node value ) {
345379 exists ( Node type |
346380 valueHasType ( value , type ) and
@@ -405,6 +439,7 @@ module TypeResolution {
405439 /**
406440 * Holds if `type` contains `string` or `any`, possibly wrapped in a promise.
407441 */
442+ pragma [ nomagic]
408443 predicate hasUnderlyingStringOrAnyType ( Node type ) {
409444 type .( TypeAnnotation ) .isStringy ( )
410445 or
0 commit comments