Repository navigation
fix: Offer and resolve bean names in Kotlin @Qualifier values (#697) - #706
Merged
Merged
Conversation
|
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment
Add this suggestion to a batch that can be applied as a single commit.This suggestion is invalid because no changes were made to the code.Suggestions cannot be applied while the pull request is closed.Suggestions cannot be applied while viewing a subset of changes.Only one suggestion per line can be applied in a batch.Add this suggestion to a batch that can be applied as a single commit.Applying suggestions on deleted lines is not supported.You must change the existing code in this line in order to create a valid suggestion.Outdated suggestions cannot be applied.This suggestion has been applied or marked resolved.Suggestions cannot be applied from pending reviews.Suggestions cannot be applied on multi-line comments.Suggestions cannot be applied while the pull request is queued to merge.Suggestion cannot be applied right now. Please check back later.
Closes #697
A Kotlin
@Qualifier("…")value had no bean-name reference: no completion, no resolve, no rename — while the same code in Javahad all three.
Why
Three blockers in a row, each verified on
public/main:QualifierReferenceContributor.getReferencesForInjectionHoststarted withuExpression as? ULiteralExpression. For theinjection host the provider is asked about, Kotlin UAST builds a
KotlinStringTemplateUPolyadicExpression, not aULiteralExpression, so the provider returnedEMPTY_ARRAYimmediately.valueLiteral.javaPsi, which is alwaysnullfor Kotlin.CompleteBeanReference.getPsiType()resolved the injection point throughelement.parentOfType<PsiAnnotation>()?.parent?.parent.A
KtStringTemplateExpressionhas noPsiAnnotationancestor, so even with a reference the completion would have been untyped.What changed
evaluateString()and the range withElementManipulators.getValueTextRange(host), the sameshape
CommonAnnotationReferenceProvideralready uses. The annotation type now comes fromuAnnotation.resolve()(one resolveinstead of the previous two).
getPsiType()walks UAST instead: annotation → owningUVariable→ its type. That covers a field, a Kotlin property, and aconstructor, setter or function parameter, in both languages.
isPlainStringLiteral()keeps interpolated templates out: aULiteralExpression, or aUPolyadicExpressionwhose operands areall literals, is a reference;
"${PREFIX}a"is not, even thoughevaluateString()would happily fold it.Two consequences worth naming:
TextRange(0, decodedLength)shifted to the value start, whichcut off the tail of an escaped value. It is now the host's whole value range. There is a Java test for it.
SpringCoreClasses.QUALIFIERSincludes the JSR-330 qualifier, so Kotlin@Named("…")and custom meta-qualifiers gain the samereference.
Tests
modules/spring-core/src/test/kotlin/com/explyt/spring/core/reference/{java,kotlin}/QualifierBeanReferenceTest.kt, written redfirst (8 Kotlin failures on the first commit), with the Java twin as the green control: completion filtered by the injection
point's type, resolve to the
@Beanfactory, Kotlin property /@field:use site / constructorval/ setter parameter /function parameter / meta-qualifier, plus two controls — an interpolated template yields no reference, and an escaped value keeps
the whole value range.
The range assertions are deliberately independent of the production call: they compare against
TextRange(1, textLength - 1)andthe decoded
reference.value, not againstElementManipulators.getValueTextRange. Forcing the production range toTextRange(0, 1)fails exactly those two tests (expected:<(1,9)> but was:<(0,1)>), so they can actually fail.Verification
:spring-core:test --tests 'com.explyt.spring.core.reference.*'— 190 tests, 0 failures.:spring-core:test --tests '*Qualifier*' --tests '*Autowir*'— 258 tests, 0 failures.:spring-core:test— 2504 tests, 0 failures, 0 errors.Backport
All lines 242–262: both touched files are identical on every
release/*branch and on every gen35 head, and the fix uses onlylong-standing UAST/platform API (
evaluateString,ElementManipulators.getValueTextRange,getParentOfType,UAnnotation.resolve,UVariable.type,UPolyadicExpression.operands). It goes into the generation-35 refresh pass, not as a separate cherry-pick.