mirror of
https://gitflic.ru/project/openide/openide.git
synced 2026-09-27 10:03:11 +07:00
[java-doc] Fix rendering type-annotations on arrays (including non-source annotations)
Fixes IDEA-350503 Type annotations in JavaDoc are shown in wrong order for multi-dimensional array Fixes IDEA-300381 Inferred @NotNull Annotation on Array / VarArg method parameter incorrectly annotates the array elements and not the argument. GitOrigin-RevId: 4a5919df70c3bac9b19fb7019365636b9a56273a
This commit is contained in:
committed by
intellij-monorepo-bot
parent
66abe1b3c6
commit
1ff1f26e15
@@ -79,6 +79,10 @@ public final class AnnotationDocGenerator {
|
||||
public String getAnnotationQualifiedName() {
|
||||
return myAnnotation.getQualifiedName();
|
||||
}
|
||||
|
||||
boolean isNonCodeTypeUseAnnotation() {
|
||||
return (isExternal() || isInferred()) && AnnotationTargetUtil.isTypeAnnotation(myAnnotation);
|
||||
}
|
||||
|
||||
public boolean isInferred() {
|
||||
return AnnotationUtil.isInferredAnnotation(myAnnotation);
|
||||
@@ -291,12 +295,25 @@ public final class AnnotationDocGenerator {
|
||||
}
|
||||
|
||||
public static List<AnnotationDocGenerator> getAnnotationsToShow(@NotNull PsiAnnotationOwner owner, @NotNull PsiElement context) {
|
||||
if (owner instanceof PsiModifierList) {
|
||||
return getAnnotationsToShow(((PsiModifierListOwner)((PsiModifierList)owner).getParent()));
|
||||
if (owner instanceof PsiModifierList modifierList) {
|
||||
return getAnnotationsToShow(((PsiModifierListOwner)modifierList.getParent()));
|
||||
}
|
||||
Set<String> shownAnnotations = new HashSet<>();
|
||||
return ContainerUtil.mapNotNull(owner.getAnnotations(),
|
||||
annotation -> forAnnotation(context, shownAnnotations, annotation));
|
||||
List<AnnotationDocGenerator> generators = ContainerUtil.mapNotNull(
|
||||
owner.getAnnotations(), annotation -> forAnnotation(context, shownAnnotations, annotation));
|
||||
if (owner instanceof PsiArrayType type) {
|
||||
PsiType contextType = getContextType(context);
|
||||
if (type.equals(contextType)) {
|
||||
return StreamEx.of(getAnnotationsToShow((PsiModifierListOwner)context)).filter(anno -> anno.isNonCodeTypeUseAnnotation())
|
||||
.append(generators).toList();
|
||||
}
|
||||
}
|
||||
return generators;
|
||||
}
|
||||
|
||||
static @Nullable PsiType getContextType(@NotNull PsiElement context) {
|
||||
return context instanceof PsiVariable var ? var.getType() :
|
||||
context instanceof PsiMethod method ? method.getReturnType() : null;
|
||||
}
|
||||
|
||||
public static List<AnnotationDocGenerator> getAnnotationsToShow(@NotNull PsiModifierListOwner owner) {
|
||||
|
||||
@@ -1384,6 +1384,7 @@ public class JavaDocInfoGenerator {
|
||||
AnnotationFormat format = place == SignaturePlace.Javadoc ? AnnotationFormat.JavaDocShort : AnnotationFormat.ToolTip;
|
||||
for (AnnotationDocGenerator anno : AnnotationDocGenerator.getAnnotationsToShow(owner)) {
|
||||
if (ignoreNonSourceAnnotations && (anno.isInferred() || anno.isExternal())) continue;
|
||||
if (anno.isNonCodeTypeUseAnnotation() && AnnotationDocGenerator.getContextType(owner) instanceof PsiArrayType) continue;
|
||||
anno.generateAnnotation(buffer, format, generateLink, isRendered(), doHighlightSignatures());
|
||||
|
||||
buffer.append(NBSP);
|
||||
@@ -1621,7 +1622,7 @@ public class JavaDocInfoGenerator {
|
||||
buffer.append(StringUtil.repeatSymbol(' ', indent));
|
||||
PsiParameter parm = parameters[i];
|
||||
generateAnnotations(buffer, parm, place, false, false, true);
|
||||
generateType(buffer, parm.getType(), method, generateLink, isTooltip);
|
||||
generateType(buffer, parm.getType(), parm, generateLink, isTooltip);
|
||||
if (!isTooltip) {
|
||||
buffer.append(NBSP);
|
||||
appendStyledSpan(buffer, getHighlightingManager().getParameterAttributes(), parm.getName());
|
||||
@@ -2898,18 +2899,24 @@ public class JavaDocInfoGenerator {
|
||||
* @return Length of the generated label.
|
||||
*/
|
||||
public int generateType(StringBuilder buffer, PsiType type, PsiElement context, boolean generateLink, boolean useShortNames) {
|
||||
if (type instanceof PsiArrayType) {
|
||||
int rest = generateType(buffer, ((PsiArrayType)type).getComponentType(), context, generateLink, useShortNames);
|
||||
if (type instanceof PsiArrayType arrayType) {
|
||||
int len = generateType(buffer, arrayType.getDeepComponentType(), context, generateLink, useShortNames);
|
||||
|
||||
int len = generateTypeAnnotations(buffer, type, context, generateLink, true);
|
||||
if (type instanceof PsiEllipsisType) {
|
||||
buffer.append("...");
|
||||
return len + rest + 3;
|
||||
}
|
||||
else {
|
||||
appendStyledSpan(buffer, getHighlightingManager().getBracketsAttributes(), "[]");
|
||||
return len + rest + 2;
|
||||
int dimensions = arrayType.getArrayDimensions();
|
||||
PsiType curType = arrayType;
|
||||
for (int i = 0; i < dimensions; i++) {
|
||||
len += generateTypeAnnotations(buffer, curType, context, generateLink, true);
|
||||
if (i == dimensions - 1 && type instanceof PsiEllipsisType) {
|
||||
buffer.append("...");
|
||||
len += 3;
|
||||
}
|
||||
else {
|
||||
appendStyledSpan(buffer, getHighlightingManager().getBracketsAttributes(), "[]");
|
||||
len += 2;
|
||||
}
|
||||
curType = ((PsiArrayType)curType).getComponentType();
|
||||
}
|
||||
return len;
|
||||
}
|
||||
|
||||
int typAnnoLength = generateTypeAnnotations(buffer, type, context, generateLink, false);
|
||||
|
||||
@@ -0,0 +1 @@
|
||||
<html><head><base href="placeholder"></head><body><div class="bottom"><icon src="AllIcons.Nodes.Class"> <a href="psi_element://Test"><code><span style="color:#000000;">Test</span></code></a></div><div class='definition'><pre><span style="color:#000080;font-weight:bold;">void</span> <span style="color:#000000;">test</span><span style="">(</span><br> <a href="psi_element://java.lang.String"><code><span style="color:#000000;">String</span></code></a> <i><span style="color:#808000;">@</span><a href="psi_element://org.jetbrains.annotations.NotNull"><code><span style="color:#808000;">NotNull</span></code></a></i><sup><font color="808080" size="3"><i>i</i></font></sup><a href="inferred.annotations"><icon src="AllIcons.Ide.External_link_arrow"></a> <span style="">[]</span> <span style="color:#000000;">data</span><br><span style="">)</span></pre></div><table class='sections'><p></table>
|
||||
@@ -0,0 +1,7 @@
|
||||
class Test {
|
||||
void test(String[] data) {
|
||||
for (String item : data) {
|
||||
System.out.println(item);
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1 @@
|
||||
<html><head><base href="placeholder"></head><body><div class="bottom"><icon src="AllIcons.Nodes.Class"> <a href="psi_element://Test"><code><span style="color:#000000;">Test</span></code></a></div><div class='definition'><pre><span style="color:#000080;font-weight:bold;">void</span> <span style="color:#000000;">test2d</span><span style="">(</span><br> <a href="psi_element://java.lang.String"><code><span style="color:#000000;">String</span></code></a> <i><span style="color:#808000;">@</span><a href="psi_element://org.jetbrains.annotations.NotNull"><code><span style="color:#808000;">NotNull</span></code></a></i><sup><font color="808080" size="3"><i>i</i></font></sup><a href="inferred.annotations"><icon src="AllIcons.Ide.External_link_arrow"></a> <span style="">[]</span><span style="">[]</span> <span style="color:#000000;">data</span><br><span style="">)</span></pre></div><table class='sections'><p></table>
|
||||
@@ -0,0 +1,9 @@
|
||||
class Test {
|
||||
void test2d(String[][] data) {
|
||||
for (String[] row : data) {
|
||||
for (String item : row) {
|
||||
System.out.println(item);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1 @@
|
||||
<html><head><base href="placeholder"></head><body><div class="bottom"><icon src="AllIcons.Nodes.Class"> <a href="psi_element://Test"><code><span style="color:#000000;">Test</span></code></a></div><div class='definition'><pre><span style="color:#000080;font-weight:bold;">final</span> <a href="psi_element://java.lang.String"><code><span style="color:#000000;">String</span></code></a> <i><span style="color:#808000;">@</span><a href="psi_element://org.jetbrains.annotations.Nullable"><code><span style="color:#808000;">Nullable</span></code></a></i><sup><font color="808080" size="3"><i>i</i></font></sup><a href="inferred.annotations"><icon src="AllIcons.Ide.External_link_arrow"></a> <span style="">[]</span> <span style="color:#000000;">test</span><span style="">(</span><span style="">)</span></pre></div><table class='sections'><p></table>
|
||||
@@ -0,0 +1,5 @@
|
||||
class Test {
|
||||
final String[] test() {
|
||||
return Math.random() > 0.5 ? new String[] { "1", "2", "3" } : null;
|
||||
}
|
||||
}
|
||||
@@ -1,5 +1,4 @@
|
||||
<html><head><base href="placeholder"></head><body><div class="bottom"><icon src="AllIcons.Nodes.Class" /> <a href="psi_element://java.lang.Class"><code><span style="color:#000000;">java.<wbr>lang.<wbr>Class</span><span style=""><</span><span style="color:#20999d;">T</span><span style="">></span></code></a></div><div class="definition"><pre><span style="color:#ff0000">@<span style="color:#808000;">CallerSensitive</span></span>
|
||||
<span style="color:#808000;">@</span><span style="color:#808000;">NotNull</span><a href="external.annotations"><icon src="AllIcons.Ide.External_link_arrow" /></a>
|
||||
<span style="color:#808000;">@</span><span style="color:#808000;">Contract</span><span style="">(</span><span style="">pure</span><span style=""> = </span><span style="color:#000080;font-weight:bold;">true</span><span style="">)</span><a href="external.annotations"><icon src="AllIcons.Ide.External_link_arrow" /></a>
|
||||
<span style="color:#000080;font-weight:bold;">public</span> <a href="psi_element://java.lang.reflect.Constructor"><code><span style="color:#000000;">java.<wbr>lang.<wbr>reflect.<wbr>Constructor</span></code></a><span style=""><</span><span style="">?</span><span style="">></span><span style="">[]</span> <span style="color:#000000;">getDeclaredConstructors</span><span style="">(</span><span style="">)</span>
|
||||
<span style="color:#000080;font-weight:bold;">public</span> <a href="psi_element://java.lang.reflect.Constructor"><code><span style="color:#000000;">java.<wbr>lang.<wbr>reflect.<wbr>Constructor</span></code></a><span style=""><</span><span style="">?</span><span style="">></span> <span style="color:#808000;">@</span><span style="color:#808000;">NotNull</span><a href="external.annotations"><icon src="AllIcons.Ide.External_link_arrow" /></a> <span style="">[]</span> <span style="color:#000000;">getDeclaredConstructors</span><span style="">(</span><span style="">)</span>
|
||||
<span style="color:#000080;font-weight:bold;">throws</span> <a href="psi_element://java.lang.SecurityException"><code><span style="color:#000000;">SecurityException</span></code></a></pre></div><table class="sections"><tbody><tr><td valign="top" class="section"><p>Throws:</p></td><td valign="top"><p><a href="psi_element://java.lang.SecurityException"><code><span style="color:#0000ff;">SecurityException</span></code></a></p></td></tr></tbody></table><div class="bottom"><icon src="AllIcons.Nodes.PpLibFolder" /> < java 10 ></div></body></html>
|
||||
@@ -0,0 +1 @@
|
||||
<html><head><base href="placeholder"></head><body><div class="bottom"><icon src="AllIcons.Nodes.Class"> <a href="psi_element://Test"><code><span style="color:#000000;">Test</span></code></a></div><div class='definition'><pre><span style="color:#000080;font-weight:bold;">void</span> <span style="color:#000000;">test</span><span style="">(</span><br> <span style="color:#808000;">@</span><a href="psi_element://Test.Test"><code><span style="color:#808000;">Test</span></code></a><span style="">(</span><span style="color:#0000ff;">1</span><span style="">)</span> <a href="psi_element://java.lang.String"><code><span style="color:#000000;">String</span></code></a> <span style="color:#808000;">@</span><a href="psi_element://Test.Test"><code><span style="color:#808000;">Test</span></code></a><span style="">(</span><span style="color:#0000ff;">2</span><span style="">)</span> <span style="">[]</span> <span style="color:#808000;">@</span><a href="psi_element://Test.Test"><code><span style="color:#808000;">Test</span></code></a><span style="">(</span><span style="color:#0000ff;">3</span><span style="">)</span> <span style="">[]</span> <span style="color:#000000;">test</span><br><span style="">)</span></pre></div><table class='sections'><p></table>
|
||||
@@ -0,0 +1,13 @@
|
||||
import java.lang.annotation.*;
|
||||
|
||||
class Test {
|
||||
void test(@Test(1) String @Test(2) [] @Test(3) [] test) {
|
||||
|
||||
}
|
||||
|
||||
@Target(ElementType.TYPE_USE)
|
||||
@Documented
|
||||
@interface Test {
|
||||
int value();
|
||||
}
|
||||
}
|
||||
+9
-3
@@ -4,6 +4,7 @@ package com.intellij.java.codeInsight.javadoc;
|
||||
import com.intellij.JavaTestUtil;
|
||||
import com.intellij.codeInsight.AnnotationUtil;
|
||||
import com.intellij.codeInsight.JavaCodeInsightTestCase;
|
||||
import com.intellij.codeInsight.daemon.impl.quickfix.JetBrainsAnnotationsExternalLibraryResolver;
|
||||
import com.intellij.codeInsight.javadoc.JavaDocInfoGenerator;
|
||||
import com.intellij.java.codeInsight.JavaExternalDocumentationTest;
|
||||
import com.intellij.lang.java.JavaDocumentationProvider;
|
||||
@@ -20,14 +21,14 @@ import com.intellij.openapi.roots.libraries.LibraryTablesRegistrar;
|
||||
import com.intellij.openapi.util.io.FileUtil;
|
||||
import com.intellij.openapi.util.text.StringUtil;
|
||||
import com.intellij.openapi.vfs.VirtualFile;
|
||||
import com.intellij.platform.testFramework.core.FileComparisonFailedError;
|
||||
import com.intellij.pom.java.LanguageLevel;
|
||||
import com.intellij.psi.*;
|
||||
import com.intellij.psi.util.PsiTreeUtil;
|
||||
import com.intellij.platform.testFramework.core.FileComparisonFailedError;
|
||||
import com.intellij.testFramework.DumbModeTestUtils;
|
||||
import com.intellij.testFramework.IdeaTestUtil;
|
||||
import com.intellij.testFramework.PsiTestUtil;
|
||||
import com.intellij.testFramework.fixtures.DefaultLightProjectDescriptor;
|
||||
import com.intellij.testFramework.fixtures.MavenDependencyUtil;
|
||||
import com.intellij.util.lang.JavaVersion;
|
||||
import com.intellij.util.ui.UIUtil;
|
||||
import org.intellij.lang.annotations.Flow;
|
||||
@@ -59,7 +60,8 @@ public class JavaDocInfoGeneratorTest extends JavaCodeInsightTestCase {
|
||||
super.setUpModule();
|
||||
if (!getTestName(false).equals("HideNonDocumentedFlowAnnotations")) {
|
||||
ModuleRootModificationUtil.updateModel(
|
||||
myModule, model -> DefaultLightProjectDescriptor.addJetBrainsAnnotations(model));
|
||||
myModule, model -> MavenDependencyUtil.addFromMaven(
|
||||
model, "org.jetbrains:annotations:" + JetBrainsAnnotationsExternalLibraryResolver.getVersion()));
|
||||
}
|
||||
}
|
||||
|
||||
@@ -90,6 +92,10 @@ public class JavaDocInfoGeneratorTest extends JavaCodeInsightTestCase {
|
||||
public void testInitializerWithReference() { doTestField(); }
|
||||
public void testAnnotations() { doTestField(); }
|
||||
public void testAnnotationsInParams() { doTestMethod(); }
|
||||
public void testInferredAnnotationsOnArray() { doTestMethod(); }
|
||||
public void testInferredAnnotationsOnArrayMethod() { doTestMethod(); }
|
||||
public void testInferredAnnotationsOnArray2d() { doTestMethod(); }
|
||||
public void testTypeAnnoMultiDimArray() { doTestMethod(); }
|
||||
public void testApiNotes() { doTestMethod(); }
|
||||
public void testLiteral() { doTestField(); }
|
||||
public void testEscapingInLiteral() { doTestField(); }
|
||||
|
||||
Reference in New Issue
Block a user