Skip to content

Use declared parameter types for Whitebox.invokeMethod reflection#945

Merged
bmuschko merged 1 commit intomainfrom
bmuschko/fix-whitebox-subclass
Mar 27, 2026
Merged

Use declared parameter types for Whitebox.invokeMethod reflection#945
bmuschko merged 1 commit intomainfrom
bmuschko/fix-whitebox-subclass

Conversation

@bmuschko
Copy link
Copy Markdown
Contributor

@bmuschko bmuschko commented Mar 27, 2026

Summary

The previous implementation used arg.getClass() to determine parameter types for getDeclaredMethod(). This returns the runtime concrete class, which fails when the method's declared parameter type is an interface or parent class (e.g., method expects List but items.getClass() returns ArrayList).

Resolution strategy (three tiers)

  1. Resolve the target method declaration — walks the target object's type hierarchy via getMethods(), finds a unique match by name + arity, and uses the method's declared parameter types. Handles subclass/interface mismatches correctly. Adds necessary imports for parameter types not already in the file.
  2. Fall back to argument's compile-time type — when method resolution fails (ambiguous overloads, missing type info), uses the expression's AST type. Still better than runtime for interface-typed variables.
  3. Fall back to arg.getClass() — when no type info is available at all, preserves the original runtime behavior.

Use cases now covered by tests

  • Single string argumentString.class instead of "World".getClass()
  • Multiple arguments — verifies correct template/arg array indexing with 2+ parameters
  • Primitive argument (int) — generates int.class instead of autoboxed Integer.class
  • Interface-typed variable (List<String> items = new ArrayList<>()) — resolves to List.class
  • Concrete variable but interface parameter (ArrayList<String> items, method expects List) — resolves to List.class via method declaration lookup, adds import java.util.List

Resolve the target method's declared parameter types from the AST
instead of using arg.getClass() which returns the runtime concrete
class and fails when the method parameter is an interface/parent type.

Three-tier resolution strategy:
1. Resolve the target method declaration and use its parameter types
2. Fall back to the argument's compile-time type
3. Fall back to arg.getClass() when no type info is available
@github-project-automation github-project-automation Bot moved this to In Progress in OpenRewrite Mar 27, 2026
@bmuschko bmuschko added the enhancement New feature or request label Mar 27, 2026
@github-project-automation github-project-automation Bot moved this from In Progress to Ready to Review in OpenRewrite Mar 27, 2026
@timtebeek
Copy link
Copy Markdown
Member

Thanks for picking this up still!

@bmuschko bmuschko merged commit cf368d7 into main Mar 27, 2026
1 check passed
@bmuschko bmuschko deleted the bmuschko/fix-whitebox-subclass branch March 27, 2026 16:02
@github-project-automation github-project-automation Bot moved this from Ready to Review to Done in OpenRewrite Mar 27, 2026
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

enhancement New feature or request

Projects

Archived in project

Development

Successfully merging this pull request may close these issues.

2 participants