[kotlin] Fix rendering parameter info annotations

#KTIJ-29752 Fixed

GitOrigin-RevId: 8d260a57c6baccf18cf7f5dfa1a61f77d01c17ce
This commit is contained in:
Vladimir Dolzhenko
2024-07-29 19:29:16 +00:00
committed by intellij-monorepo-bot
parent 28927af215
commit 90d1ce34b7
6 changed files with 77 additions and 10 deletions
@@ -787,11 +787,21 @@ public final class MethodParameterInfoHandler
return html.replaceAll("<a.*?>", "").replaceAll("</a>", "");
}
private static void appendModifierList(@NotNull StringBuilder buffer, @NotNull PsiModifierListOwner owner) {
private static void appendModifierList(@NotNull StringBuilder buffer, @Nullable PsiType type, @NotNull PsiModifierListOwner owner) {
if (DumbService.isDumb(owner.getProject())) return;
int lastSize = buffer.length();
Set<String> shownAnnotations = new HashSet<>();
if (type != null) {
PsiAnnotation[] annotations = type.getAnnotations();
for (PsiAnnotation annotation : annotations) {
final PsiJavaCodeReferenceElement element = annotation.getNameReferenceElement();
if (element != null) {
String referenceName = element.getReferenceName();
shownAnnotations.add(referenceName);
}
}
}
for (PsiAnnotation annotation : AnnotationUtil.getAllAnnotations(owner, false, null, true)) {
final PsiJavaCodeReferenceElement element = annotation.getNameReferenceElement();
if (element != null) {
@@ -897,7 +907,7 @@ public final class MethodParameterInfoHandler
PsiType paramType = substitutor.substitute(param.getType());
String type = paramType.getPresentableText(!DumbService.isDumb(param.getProject()));
StringBuilder buffer = new StringBuilder();
appendModifierList(buffer, param);
appendModifierList(buffer, paramType, param);
String modifiers = buffer.toString();
String name = param.getName();
String javaDoc = JavaDocInfoGeneratorFactory.create(param.getProject(), param).generateMethodParameterJavaDoc();
@@ -915,7 +925,7 @@ public final class MethodParameterInfoHandler
PsiType returnType = substitutor.substitute(method.getReturnType());
String type = returnType == null ? "" : returnType.getPresentableText(true);
StringBuilder buffer = new StringBuilder();
appendModifierList(buffer, method);
appendModifierList(buffer, returnType, method);
String modifiers = buffer.toString();
List<ParameterPresentation> parameters =
ContainerUtil.map(method.getParameterList().getParameters(), param -> ParameterPresentation.from(param, substitutor));
@@ -326,7 +326,17 @@ public abstract class PsiNameHelper {
else {
PsiJavaCodeReferenceElement refElement = annotation.getNameReferenceElement();
if (refElement != null) {
sb.append('@').append(refElement.getText()).append(' ');
String referenceName = refElement.getReferenceName();
if (referenceName != null) {
sb.append('@').append(referenceName);
} else {
String refElementText = refElement.getText();
if (!refElementText.startsWith("@")) {
sb.append('@');
}
sb.append(refElementText);
}
sb.append(' ');
updated = true;
}
}
@@ -103,6 +103,25 @@ public abstract class FirParameterInfoTestGenerated extends AbstractFirParameter
}
}
@RunWith(JUnit3RunnerWithInners.class)
@TestMetadata("../../idea/tests/testData/parameterInfo/fromJava")
public static class FromJava extends AbstractFirParameterInfoTest {
@java.lang.Override
@org.jetbrains.annotations.NotNull
public final KotlinPluginMode getPluginMode() {
return KotlinPluginMode.K2;
}
private void runTest(String testDataFilePath) throws Exception {
KotlinTestUtils.runTest(this::doTest, this, testDataFilePath);
}
@TestMetadata("Usage.java")
public void testUsage() throws Exception {
runTest("../../idea/tests/testData/parameterInfo/fromJava/Usage.java");
}
}
@RunWith(JUnit3RunnerWithInners.class)
@TestMetadata("../../idea/tests/testData/parameterInfo/functionCall")
public static class FunctionCall extends AbstractFirParameterInfoTest {
@@ -4,8 +4,10 @@ package org.jetbrains.kotlin.idea.parameterInfo
import com.intellij.codeInsight.hint.ShowParameterInfoContext
import com.intellij.codeInsight.hint.ShowParameterInfoHandler
import com.intellij.lang.java.JavaLanguage
import com.intellij.lang.parameterInfo.ParameterInfoHandler
import com.intellij.openapi.util.io.FileUtil
import com.intellij.psi.JavaTokenType
import com.intellij.psi.PsiDocumentManager
import com.intellij.psi.PsiElement
import com.intellij.psi.PsiWhiteSpace
@@ -57,15 +59,16 @@ abstract class AbstractParameterInfoTest : KotlinLightCodeInsightFixtureTestCase
myFixture.configureByFile(File(fileName).canonicalPath)
val file = myFixture.file as KtFile
val file = myFixture.file
withCustomCompilerOptions(file.text, project, myFixture.module) {
val lastChild = file.allChildren.filter { it !is PsiWhiteSpace }.last()
val expectedResultText = run {
val lines = when (lastChild.node.elementType) {
KtTokens.BLOCK_COMMENT -> lastChild.text.substring(2, lastChild.text.length - 2).trim()
JavaTokenType.C_STYLE_COMMENT -> lastChild.text.substring(2, lastChild.text.length - 2).trim()
KtTokens.EOL_COMMENT -> lastChild.text.substring(2).trim()
else -> error("Unexpected last file child")
else -> error("Unexpected last file child ${lastChild.node.elementType}")
}.lines()
lines.mapNotNull { line ->
when {
@@ -83,10 +86,19 @@ abstract class AbstractParameterInfoTest : KotlinLightCodeInsightFixtureTestCase
lateinit var mockCreateParameterInfoContext: MockCreateParameterInfoContext
lateinit var parameterOwner: PsiElement
executeOnPooledThreadInReadAction {
val handlers = ShowParameterInfoHandler.getHandlers(project, KotlinLanguage.INSTANCE)
@Suppress("UNCHECKED_CAST")
handler = handlers.firstOrNull { it.findElementForParameterInfo(context) != null } as? ParameterInfoHandler<PsiElement, Any>
?: error("Could not find parameter info handler")
if (file is KtFile) {
val handlers =
ShowParameterInfoHandler.getHandlers(project, KotlinLanguage.INSTANCE)
@Suppress("UNCHECKED_CAST")
handler =
handlers.firstOrNull { it.findElementForParameterInfo(context) != null } as? ParameterInfoHandler<PsiElement, Any>
?: error("Could not find parameter info handler")
} else {
val handlers =
ShowParameterInfoHandler.getHandlers(project, JavaLanguage.INSTANCE)
handler = handlers.firstOrNull { it.findElementForParameterInfo(context) != null } as? ParameterInfoHandler<PsiElement, Any>
?: error("Could not find parameter info handler")
}
mockCreateParameterInfoContext = MockCreateParameterInfoContext(file, myFixture)
parameterOwner = handler.findElementForParameterInfo(mockCreateParameterInfoContext) as PsiElement
@@ -0,0 +1,6 @@
package p
@Target(AnnotationTarget.TYPE)
annotation class MyAnnotation
class Foo(bar: @MyAnnotation String)
@@ -0,0 +1,10 @@
import p.Foo;
public class Usage {
void usage() {
new Foo(<caret>"");
}
}
/*
Text: (@MyAnnotation @NotNull String bar), Disabled: true, Strikeout: false, Green: false
*/