Skip to content

Kotlin: declare caller-scope type variables on synthetic Template class#7414

Merged
timtebeek merged 4 commits intomainfrom
tim/fix-7407
Apr 17, 2026
Merged

Kotlin: declare caller-scope type variables on synthetic Template class#7414
timtebeek merged 4 commits intomainfrom
tim/fix-7407

Conversation

@timtebeek
Copy link
Copy Markdown
Member

@timtebeek timtebeek commented Apr 17, 2026

Summary

  • The Kotlin BlockStatementTemplateGenerator previously ignored the type variables collected from parameter types, emitting a bare class Template { even when substituted parameters referenced caller-scope generics like Container<T>. The resulting synthetic class failed to parse because T was undeclared.

  • This change declares those type variables on the synthetic class using Kotlin syntax (T : Bound for a single bound, where clause for multi-bound), mirroring the Java generator's Template<T> handling.

  • Fixes BlockStatementTemplateGenerator leaks unbound type variables from caller scope into synthetic template class #7407

Test plan

  • Added KotlinTemplateTest.parameterTypeWithCallerScopeTypeVariable asserting the generated template contains class Template<T
  • ./gradlew :rewrite-kotlin:test

The Kotlin `BlockStatementTemplateGenerator` ignored the `typeVariables`
collected from parameter types, emitting a bare `class Template {`. When a
template parameter's type referenced a caller-scope generic (e.g.
`Container<T>` from an enclosing `fun <T : Any> ...`), the substitution
produced `__P__.p<Container<T>>()` inside a class where `T` was undeclared.

Now the Kotlin generator declares those type variables using Kotlin
syntax (`T : Bound` for a single bound, `where` clause for multiple).

Fixes #7407
}
}

private static String kotlinTypeParameters(Collection<JavaType.GenericTypeVariable> typeVariables) {
Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Not fully sure, can we re-use the printer here?

Copy link
Copy Markdown
Member Author

@timtebeek timtebeek Apr 17, 2026

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

The KotlinPrinter operates on LST nodes (e.g. J.TypeParameter), whereas here we only have JavaType.GenericTypeVariable metadata from Substitutions.getTypeVariables() — there's no direct conversion. To improve reuse I've extracted the string-building helper into KotlinTypeUtils.toKotlinTypeParameters(...) so it's available to other template/code-generation paths that also start from JavaType metadata.

@github-project-automation github-project-automation Bot moved this from In Progress to Ready to Review in OpenRewrite Apr 17, 2026
@timtebeek timtebeek merged commit 30a85e1 into main Apr 17, 2026
1 check passed
@timtebeek timtebeek deleted the tim/fix-7407 branch April 17, 2026 13:39
@github-project-automation github-project-automation Bot moved this from Ready to Review to Done in OpenRewrite Apr 17, 2026
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

Archived in project

Development

Successfully merging this pull request may close these issues.

BlockStatementTemplateGenerator leaks unbound type variables from caller scope into synthetic template class

2 participants