@@ -269,76 +269,68 @@ private void auxChangeAlias(Map<String, AliasDTO> alias, Context ctx, Factory f)
269269 */
270270 public void validateGhostInvocations (Context ctx , Factory f ) throws LJError {
271271 if (this instanceof FunctionInvocation fi ) {
272-
273272 // get all ghosts with the matching name
274273 List <GhostFunction > candidates = ctx .getGhosts ().stream ().filter (g -> g .matches (fi .name )).toList ();
274+ if (candidates .isEmpty ())
275+ return ;
275276
276- if (!candidates .isEmpty ()) {
277- // search for a matching overload
278- for (GhostFunction g : candidates ) {
279-
280- // check argument count
281- if (fi .children .size () != g .getParametersTypes ().size ())
282- continue ;
283-
284- // check argument types
285- boolean argsMatch = true ;
286- for (int i = 0 ; i < fi .children .size (); i ++) {
287- Expression arg = fi .children .get (i );
288- CtTypeReference <?> expected = g .getParametersTypes ().get (i );
289- Optional <CtTypeReference <?>> actualOpt = TypeInfer .getType (ctx , f , arg );
290-
291- if (actualOpt .isPresent ()) {
292- CtTypeReference <?> actual = actualOpt .get ();
293- if (!actual .equals (expected ) && !actual .isSubtypeOf (expected )) {
294- argsMatch = false ;
295- break ;
296- }
297- }
298- }
299-
300- // found match
301- if (argsMatch ) {
302- if (hasChildren ()) {
303- for (Expression child : children )
304- child .validateGhostInvocations (ctx , f );
305- }
306- return ;
307- }
308- }
309-
277+ // find matching overload
278+ Optional <GhostFunction > match = candidates .stream ().filter (g -> argumentsMatch (fi , g , ctx , f )).findFirst ();
279+ if (match .isEmpty ()) {
310280 // no overload matched, use the first candidate to throw the error
311- GhostFunction g = candidates .get (0 );
312-
313- if (fi .children .size () != g .getParametersTypes ().size ()) {
314- throw new ArgumentMismatchError (
315- String .format ("Wrong number of arguments in ghost invocation '%s': expected %d, got %d" ,
316- fi .name , g .getParametersTypes ().size (), fi .children .size ()));
317-
318- }
319-
320- for (int i = 0 ; i < fi .children .size (); i ++) {
321- CtTypeReference <?> expected = g .getParametersTypes ().get (i );
322- Optional <CtTypeReference <?>> actualOpt = TypeInfer .getType (ctx , f , fi .children .get (i ));
323- if (actualOpt .isPresent ()) {
324- CtTypeReference <?> actual = actualOpt .get ();
325- if (!actual .equals (expected ) && !actual .isSubtypeOf (expected )) {
326- Expression arg = fi .children .get (i );
327- throw new ArgumentMismatchError (String .format (
328- "Argument '%s' and its respective parameter of ghost '%s' types are incompatible: expected %s, got %s" ,
329- arg , fi .name , expected .getSimpleName (), actual .getSimpleName ()));
330- }
331- }
332- }
281+ throwArgumentMismatchError (fi , candidates .get (0 ), ctx , f );
333282 }
334283 }
284+
335285 // recurse children
336286 if (hasChildren ()) {
337287 for (Expression child : children ) {
338288 child .validateGhostInvocations (ctx , f );
339289 }
290+ }
291+ }
340292
293+ private boolean argumentsMatch (FunctionInvocation fi , GhostFunction g , Context ctx , Factory f ) {
294+ // check argument count
295+ if (fi .children .size () != g .getParametersTypes ().size ())
296+ return false ;
297+
298+ // check argument types
299+ for (int i = 0 ; i < fi .children .size (); i ++) {
300+ Expression arg = fi .children .get (i );
301+ CtTypeReference <?> expected = g .getParametersTypes ().get (i );
302+ Optional <CtTypeReference <?>> actualOpt = TypeInfer .getType (ctx , f , arg );
303+
304+ if (actualOpt .isPresent ()) {
305+ CtTypeReference <?> actual = actualOpt .get ();
306+ if (!actual .equals (expected ) && !actual .isSubtypeOf (expected )) {
307+ return false ;
308+ }
309+ }
341310 }
311+ return true ;
342312 }
343313
314+ private void throwArgumentMismatchError (FunctionInvocation fi , GhostFunction g , Context ctx , Factory f )
315+ throws LJError {
316+ if (fi .children .size () != g .getParametersTypes ().size ()) {
317+ throw new ArgumentMismatchError (
318+ String .format ("Wrong number of arguments in ghost invocation '%s': expected %d, got %d" , fi .name ,
319+ g .getParametersTypes ().size (), fi .children .size ()));
320+ }
321+
322+ for (int i = 0 ; i < fi .children .size (); i ++) {
323+ CtTypeReference <?> expected = g .getParametersTypes ().get (i );
324+ Optional <CtTypeReference <?>> actualOpt = TypeInfer .getType (ctx , f , fi .children .get (i ));
325+ if (actualOpt .isPresent ()) {
326+ CtTypeReference <?> actual = actualOpt .get ();
327+ if (!actual .equals (expected ) && !actual .isSubtypeOf (expected )) {
328+ Expression arg = fi .children .get (i );
329+ throw new ArgumentMismatchError (String .format (
330+ "Argument '%s' and its respective parameter of ghost '%s' types are incompatible: expected %s, got %s" ,
331+ arg , fi .name , expected .getSimpleName (), actual .getSimpleName ()));
332+ }
333+ }
334+ }
335+ }
344336}
0 commit comments