@@ -60,6 +60,7 @@ abstract class XTypeRecovery[CompilationUnitType <: AstNode](cpg: Cpg, iteration
60
60
compilationUnit
61
61
.map(unit => generateRecoveryForCompilationUnitTask(unit, builder).fork())
62
62
.foreach(_.get())
63
+
63
64
} finally {
64
65
globalTable.clear()
65
66
addedNodes.clear()
@@ -131,6 +132,26 @@ abstract class RecoverForXCompilationUnit[CompilationUnitType <: AstNode](
131
132
protected def members : Traversal [Member ] =
132
133
cu.ast.isMember
133
134
135
+ protected def visitCall (call : Call ): Unit = {
136
+ symbolTable.get(call).foreach { methodFullName =>
137
+ val index = methodFullName.indexOf(" <returnValue>" )
138
+ if (index != - 1 ) {
139
+ val methodToLookup = methodFullName.substring(0 , index - 1 )
140
+ val remainder = methodFullName.substring(index + " <returnValue>" .length)
141
+ val methods = cpg.method.fullNameExact(methodToLookup).l
142
+ methods match {
143
+ case List (method) =>
144
+ val dynamicTypeHints = method.methodReturn.dynamicTypeHintFullName.toSet
145
+ val newTypes = dynamicTypeHints.map(x => x + remainder)
146
+ symbolTable.put(call, newTypes)
147
+ case List () =>
148
+ case _ =>
149
+ logger.warn(s " More than a single function matches method full name: $methodToLookup" )
150
+ }
151
+ }
152
+ }
153
+ }
154
+
134
155
override def compute (): Unit = try {
135
156
prepopulateSymbolTable()
136
157
// Set known aliases that point to imports for local and external methods/modules
@@ -141,6 +162,9 @@ abstract class RecoverForXCompilationUnit[CompilationUnitType <: AstNode](
141
162
members.foreach(visitMembers)
142
163
// Populate local symbol table with assignments
143
164
assignments.foreach(visitAssignments)
165
+ // Propagate return values
166
+ cpg.method.ast.isCall.foreach(visitCall)
167
+
144
168
// Persist findings
145
169
setTypeInformation()
146
170
} finally {
0 commit comments