@@ -1164,15 +1164,27 @@ class DataFlowCall extends TDataFlowCall {
1164
1164
Function getStaticCallSourceTarget ( ) { none ( ) }
1165
1165
1166
1166
/**
1167
- * Gets the target of this call. If a summarized callable exists for the
1168
- * target this is chosen, and otherwise the callable is the implementation
1169
- * from the source code.
1167
+ * Gets the target of this call. We use the following strategy for deciding
1168
+ * between the source callable and a summarized callable:
1169
+ * - If there is a manual summary then we always use the manual summary.
1170
+ * - If there is a source callable and we only have generated summaries
1171
+ * we use the source callable.
1172
+ * - If there is no source callable then we use the summary regardless of
1173
+ * whether is it manual or generated.
1170
1174
*/
1171
- DataFlowCallable getStaticCallTarget ( ) {
1175
+ final DataFlowCallable getStaticCallTarget ( ) {
1172
1176
exists ( Function target | target = this .getStaticCallSourceTarget ( ) |
1173
- not exists ( TSummarizedCallable ( target ) ) and
1177
+ // Don't use the source callable if there is a manual model for the
1178
+ // target
1179
+ not exists ( SummarizedCallable sc |
1180
+ sc .asSummarizedCallable ( ) = target and
1181
+ sc .asSummarizedCallable ( ) .applyManualModel ( )
1182
+ ) and
1174
1183
result .asSourceCallable ( ) = target
1175
1184
or
1185
+ // When there is no function body, or when we have a manual model then
1186
+ // we dispatch to the summary.
1187
+ ( not target .hasDefinition ( ) or result .asSummarizedCallable ( ) .applyManualModel ( ) ) and
1176
1188
result .asSummarizedCallable ( ) = target
1177
1189
)
1178
1190
}
0 commit comments