mirror of
https://gitflic.ru/project/openide/openide.git
synced 2026-09-27 10:03:11 +07:00
[Java. Code Formatting] Rewrite the way of detection type annotation in JavaFormatterUtil
IDEA-353192 GitOrigin-RevId: 34e375e4e1e059be03aad12c2839911b8315ed06
This commit is contained in:
committed by
intellij-monorepo-bot
parent
c7a93d5462
commit
a4d5e41d7f
@@ -19,15 +19,13 @@ import com.intellij.psi.impl.source.tree.ElementType;
|
||||
import com.intellij.psi.impl.source.tree.JavaElementType;
|
||||
import com.intellij.psi.tree.IElementType;
|
||||
import com.intellij.psi.tree.TokenSet;
|
||||
import com.intellij.psi.util.PsiTreeUtil;
|
||||
import com.intellij.util.ArrayUtil;
|
||||
import com.intellij.util.containers.ContainerUtil;
|
||||
import org.jetbrains.annotations.NotNull;
|
||||
import org.jetbrains.annotations.Nullable;
|
||||
|
||||
import java.util.ArrayDeque;
|
||||
import java.util.ArrayList;
|
||||
import java.util.Collections;
|
||||
import java.util.List;
|
||||
import java.util.*;
|
||||
|
||||
public final class JavaFormatterUtil {
|
||||
/**
|
||||
@@ -38,6 +36,11 @@ public final class JavaFormatterUtil {
|
||||
|
||||
private static final int CALL_EXPRESSION_DEPTH = 500;
|
||||
|
||||
private static final Set<String> KNOWN_TYPE_ANNOTATIONS = Set.of(
|
||||
"org.jetbrains.annotations.NotNull",
|
||||
"org.jetbrains.annotations.Nullable"
|
||||
);
|
||||
|
||||
private JavaFormatterUtil() { }
|
||||
|
||||
/**
|
||||
@@ -289,7 +292,8 @@ public final class JavaFormatterUtil {
|
||||
if (prev != null && prev.getElementType() == JavaElementType.MODIFIER_LIST) {
|
||||
ASTNode last = prev.getLastChildNode();
|
||||
if (last != null && last.getElementType() == JavaElementType.ANNOTATION) {
|
||||
if (javaSettings.DO_NOT_WRAP_AFTER_SINGLE_ANNOTATION && isModifierListWithSingleAnnotation(prev, JavaElementType.FIELD) ||
|
||||
if (isTypeAnnotation(last) ||
|
||||
javaSettings.DO_NOT_WRAP_AFTER_SINGLE_ANNOTATION && isModifierListWithSingleAnnotation(prev, JavaElementType.FIELD) ||
|
||||
javaSettings.DO_NOT_WRAP_AFTER_SINGLE_ANNOTATION_IN_PARAMETER &&
|
||||
isModifierListWithSingleAnnotation(prev, JavaElementType.PARAMETER) ||
|
||||
isAnnotationAfterKeyword(last)
|
||||
@@ -311,10 +315,17 @@ public final class JavaFormatterUtil {
|
||||
if (prev instanceof PsiKeyword) {
|
||||
return null;
|
||||
}
|
||||
|
||||
else if (isAnnoInsideModifierListWithAtLeastOneKeyword(child, parent)) {
|
||||
return Wrap.createWrap(WrapType.NONE, false);
|
||||
}
|
||||
|
||||
if (isTypeAnnotation(child)) {
|
||||
if (prev == null || prev.getElementType() != JavaElementType.ANNOTATION || isTypeAnnotation(prev)) {
|
||||
return Wrap.createWrap(WrapType.NONE, false);
|
||||
}
|
||||
}
|
||||
|
||||
return Wrap.createWrap(getWrapType(getAnnotationWrapType(parent.getTreeParent(), child, settings, javaSettings)), true);
|
||||
}
|
||||
else if (childType == JavaTokenType.END_OF_LINE_COMMENT) {
|
||||
@@ -432,6 +443,33 @@ public final class JavaFormatterUtil {
|
||||
return prev != null && prev.getElementType() != JavaElementType.BLOCK_STATEMENT;
|
||||
}
|
||||
|
||||
private static boolean isTypeAnnotation(@NotNull ASTNode child) {
|
||||
PsiElement node = child.getPsi();
|
||||
PsiElement next = PsiTreeUtil.skipSiblingsForward(node, PsiWhiteSpace.class, PsiAnnotation.class);
|
||||
if (next instanceof PsiKeyword) return false;
|
||||
if (!(node instanceof PsiAnnotation psiAnnotation)) return false;
|
||||
|
||||
PsiJavaCodeReferenceElement psiReference = psiAnnotation.getNameReferenceElement();
|
||||
if (psiReference == null) return false;
|
||||
|
||||
if (psiReference.isQualified()) {
|
||||
return KNOWN_TYPE_ANNOTATIONS.contains(psiReference.getText());
|
||||
}
|
||||
else {
|
||||
PsiElement referenceName = psiReference.getReferenceNameElement();
|
||||
if (referenceName == null) return false;
|
||||
if (!(psiReference.getContainingFile() instanceof PsiJavaFile javaFile)) return false;
|
||||
PsiImportList importList = javaFile.getImportList();
|
||||
if (importList == null) return false;
|
||||
String referenceNameText = referenceName.getText();
|
||||
return ContainerUtil.or(KNOWN_TYPE_ANNOTATIONS, fqn -> {
|
||||
if (!fqn.endsWith(referenceNameText)) return false;
|
||||
String packageName = StringUtil.getPackageName(fqn);
|
||||
return importList.findOnDemandImportStatement(packageName) != null || importList.findSingleClassImportStatement(fqn) != null;
|
||||
});
|
||||
}
|
||||
}
|
||||
|
||||
private static void putPreferredWrapInParentBlock(@NotNull AbstractJavaBlock block, @NotNull Wrap preferredWrap) {
|
||||
AbstractJavaBlock parentBlock = block.getParentBlock();
|
||||
if (parentBlock != null) {
|
||||
|
||||
+1
-2
@@ -13,8 +13,7 @@ class Y extends X{
|
||||
}
|
||||
}
|
||||
class Z extends Y {
|
||||
@NotNull
|
||||
String dontAnnotateBase<caret>() {// trigger quick fix for inspection here
|
||||
@NotNull String dontAnnotateBase() {// trigger quick fix for inspection here
|
||||
return "Z";
|
||||
}
|
||||
}
|
||||
|
||||
+2
-4
@@ -9,15 +9,13 @@ abstract class P2 {
|
||||
}
|
||||
|
||||
class PPP extends P2 {
|
||||
@NotNull
|
||||
String foo(P p) {
|
||||
@NotNull String foo(P p) {
|
||||
return super.foo(p);
|
||||
}
|
||||
}
|
||||
class PPP2 extends P2 {
|
||||
|
||||
@NotNull
|
||||
String foo(P p) {
|
||||
@NotNull String foo(P p) {
|
||||
return super.foo(p);
|
||||
}
|
||||
}
|
||||
+1
-2
@@ -9,8 +9,7 @@ import org.jetbrains.annotations.*;
|
||||
}
|
||||
}
|
||||
class XC extends XEM {
|
||||
@NotNull
|
||||
String f() {
|
||||
@NotNull String f() {
|
||||
return "";
|
||||
}
|
||||
}
|
||||
|
||||
+1
-2
@@ -6,8 +6,7 @@ public interface MyTestClass {
|
||||
}
|
||||
|
||||
public class MyRealTestClass implements MyTestClass {
|
||||
@NotNull
|
||||
String implementMe(String arg) {
|
||||
@NotNull String implementMe(String arg) {
|
||||
|
||||
}
|
||||
}
|
||||
+1
-2
@@ -1,6 +1,5 @@
|
||||
package withAnnotation;
|
||||
import org.jetbrains.annotations.Nullable;
|
||||
public class Foo {
|
||||
@Nullable
|
||||
String f<caret>oo() {return null;}
|
||||
@Nullable String f<caret>oo() {return null;}
|
||||
}
|
||||
@@ -39,8 +39,7 @@ class Test {
|
||||
final String myFoo13 = null;
|
||||
final Runnable myFoo14 = new Runnable() {
|
||||
{foo();}
|
||||
@Nullable
|
||||
Object foo() {
|
||||
@Nullable Object foo() {
|
||||
return null;
|
||||
}
|
||||
public void run() {}
|
||||
@@ -59,8 +58,7 @@ class Test {
|
||||
myFoo12 = "";
|
||||
}
|
||||
|
||||
@Nullable
|
||||
String foo10(boolean flag) {
|
||||
@Nullable String foo10(boolean flag) {
|
||||
return flag ? foo2() : foo3();
|
||||
}
|
||||
}
|
||||
@@ -1,13 +1,11 @@
|
||||
import org.jetbrains.annotations.*;
|
||||
|
||||
class Test {
|
||||
@Nullable
|
||||
String foo1() {
|
||||
@Nullable String foo1() {
|
||||
return null;
|
||||
}
|
||||
|
||||
@NotNull
|
||||
String foo2() {
|
||||
@NotNull String foo2() {
|
||||
return "";
|
||||
}
|
||||
|
||||
@@ -15,29 +13,24 @@ class Test {
|
||||
return s;
|
||||
}
|
||||
|
||||
@NotNull
|
||||
String foo4(@NotNull String s) {
|
||||
@NotNull String foo4(@NotNull String s) {
|
||||
return s.substring(0);
|
||||
}
|
||||
|
||||
@NotNull
|
||||
Integer foo5(Integer i) {
|
||||
@NotNull Integer foo5(Integer i) {
|
||||
return i++;
|
||||
}
|
||||
|
||||
@NotNull
|
||||
Integer foo6(Integer i) {
|
||||
@NotNull Integer foo6(Integer i) {
|
||||
if (i == 0) return 1;
|
||||
return i * foo6(i--);
|
||||
}
|
||||
|
||||
@Nullable
|
||||
Integer foo7(boolean flag) {
|
||||
@Nullable Integer foo7(boolean flag) {
|
||||
return flag ? null : 1;
|
||||
}
|
||||
|
||||
@Nullable
|
||||
Integer foo8(boolean flag) {
|
||||
@Nullable Integer foo8(boolean flag) {
|
||||
if (flag) {
|
||||
return null;
|
||||
}
|
||||
@@ -51,8 +44,7 @@ class Test {
|
||||
return foo3("");
|
||||
}
|
||||
|
||||
@Nullable
|
||||
String foo9() {
|
||||
@Nullable String foo9() {
|
||||
return bar9();
|
||||
}
|
||||
|
||||
@@ -67,16 +59,13 @@ class Test {
|
||||
return foo3("");
|
||||
}
|
||||
|
||||
@Nullable
|
||||
String foo10(boolean flag) {
|
||||
@Nullable String foo10(boolean flag) {
|
||||
return flag ? bar10() : bar101();
|
||||
}
|
||||
|
||||
@NotNull
|
||||
String foo11() {
|
||||
@NotNull String foo11() {
|
||||
class Foo{
|
||||
@Nullable
|
||||
String mess() {
|
||||
@Nullable String mess() {
|
||||
return null;
|
||||
}
|
||||
}
|
||||
|
||||
+3
-6
@@ -11,20 +11,17 @@ class Test {
|
||||
return str;
|
||||
}
|
||||
|
||||
@NotNull
|
||||
String foo1(@Nullable String str) {
|
||||
@NotNull String foo1(@Nullable String str) {
|
||||
if (str == null) return "null";
|
||||
return (str);
|
||||
}
|
||||
|
||||
@NotNull
|
||||
String foo2(@Nullable String str) {
|
||||
@NotNull String foo2(@Nullable String str) {
|
||||
if (str == null) return "null";
|
||||
return ((String)str);
|
||||
}
|
||||
|
||||
@NotNull
|
||||
String fram(@Nullable String str, boolean b) {
|
||||
@NotNull String fram(@Nullable String str, boolean b) {
|
||||
if (str != null) {
|
||||
return b ? str : "not null strimg";
|
||||
}
|
||||
|
||||
@@ -0,0 +1,18 @@
|
||||
package org.example;
|
||||
|
||||
import java.lang.annotation.ElementType;
|
||||
import java.lang.annotation.Target;
|
||||
import java.util.List;
|
||||
|
||||
@Target({ElementType.TYPE_USE})
|
||||
@interface CustomAnno {}
|
||||
|
||||
public class Formatter {
|
||||
@CustomAnno String getCustomString() {
|
||||
return null;
|
||||
}
|
||||
|
||||
@CustomAnno <T, V> List<T> getCustomList() {
|
||||
return null;
|
||||
}
|
||||
}
|
||||
+21
@@ -0,0 +1,21 @@
|
||||
package org.example;
|
||||
|
||||
import java.lang.annotation.ElementType;
|
||||
import java.lang.annotation.Target;
|
||||
import java.util.List;
|
||||
|
||||
@Target({ElementType.TYPE_USE})
|
||||
@interface CustomAnno {
|
||||
}
|
||||
|
||||
public class Formatter {
|
||||
@CustomAnno
|
||||
String getCustomString() {
|
||||
return null;
|
||||
}
|
||||
|
||||
@CustomAnno
|
||||
<T, V> List<T> getCustomList() {
|
||||
return null;
|
||||
}
|
||||
}
|
||||
+14
@@ -0,0 +1,14 @@
|
||||
package org.example;
|
||||
|
||||
import org.jetbrains.annotations.NotNull;
|
||||
import org.jetbrains.annotations.Nullable;
|
||||
|
||||
public class Formatter {
|
||||
@NotNull String getNotNullName() {
|
||||
return "";
|
||||
}
|
||||
|
||||
@Nullable String getNullableName() {
|
||||
return null;
|
||||
}
|
||||
}
|
||||
+16
@@ -0,0 +1,16 @@
|
||||
package org.example;
|
||||
|
||||
import org.jetbrains.annotations.NotNull;
|
||||
import org.jetbrains.annotations.Nullable;
|
||||
|
||||
import java.util.List;
|
||||
|
||||
public class Formatter {
|
||||
@NotNull <T, V> List<T> getNotNullList() {
|
||||
return List.of();
|
||||
}
|
||||
|
||||
@Nullable <T, V> List<T> getNullableList() {
|
||||
return null;
|
||||
}
|
||||
}
|
||||
+16
@@ -0,0 +1,16 @@
|
||||
package org.example;
|
||||
|
||||
import org.jetbrains.annotations.NotNull;
|
||||
import org.jetbrains.annotations.Nullable;
|
||||
|
||||
import java.util.List;
|
||||
|
||||
public class Formatter {
|
||||
@NotNull <T, V> List<T> getNotNullList() {
|
||||
return List.of();
|
||||
}
|
||||
|
||||
@Nullable <T, V> List<T> getNullableList() {
|
||||
return null;
|
||||
}
|
||||
}
|
||||
+14
@@ -0,0 +1,14 @@
|
||||
package org.example;
|
||||
|
||||
import org.jetbrains.annotations.NotNull;
|
||||
import org.jetbrains.annotations.Nullable;
|
||||
|
||||
public class Formatter {
|
||||
@NotNull String getNotNullName() {
|
||||
return "";
|
||||
}
|
||||
|
||||
@Nullable String getNullableName() {
|
||||
return null;
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,17 @@
|
||||
package org.example;
|
||||
|
||||
import org.jetbrains.annotations.NotNull;
|
||||
import org.jetbrains.annotations.Nullable;
|
||||
|
||||
import java.util.List;
|
||||
|
||||
|
||||
public class Formatter {
|
||||
@Nullable @NotNull String getCustomString() {
|
||||
return null;
|
||||
}
|
||||
|
||||
@Nullable @NotNull <T, V> List<T> getCustomList() {
|
||||
return null;
|
||||
}
|
||||
}
|
||||
+17
@@ -0,0 +1,17 @@
|
||||
package org.example;
|
||||
|
||||
import org.jetbrains.annotations.NotNull;
|
||||
import org.jetbrains.annotations.Nullable;
|
||||
|
||||
import java.util.List;
|
||||
|
||||
|
||||
public class Formatter {
|
||||
@Nullable @NotNull String getCustomString() {
|
||||
return null;
|
||||
}
|
||||
|
||||
@Nullable @NotNull <T, V> List<T> getCustomList() {
|
||||
return null;
|
||||
}
|
||||
}
|
||||
+20
@@ -0,0 +1,20 @@
|
||||
package org.example;
|
||||
|
||||
import org.jetbrains.annotations.NotNull;
|
||||
import org.jetbrains.annotations.Nullable;
|
||||
|
||||
import java.util.List;
|
||||
|
||||
public class Formatter {
|
||||
@NotNull
|
||||
@Nullable
|
||||
<T, V> List<T> getStrangeList() {
|
||||
return List.of();
|
||||
}
|
||||
|
||||
@NotNull
|
||||
@Nullable
|
||||
String getNotNullName() {
|
||||
return "";
|
||||
}
|
||||
}
|
||||
+19
@@ -0,0 +1,19 @@
|
||||
package org.example;
|
||||
|
||||
import org.jetbrains.annotations.NotNull;
|
||||
import org.jetbrains.annotations.Nullable;
|
||||
|
||||
import java.util.List;
|
||||
|
||||
public class Formatter {
|
||||
@NotNull
|
||||
@Nullable <T, V> List<T> getStrangeList() {
|
||||
return List.of();
|
||||
}
|
||||
|
||||
@NotNull
|
||||
@Nullable
|
||||
String getNotNullName() {
|
||||
return "";
|
||||
}
|
||||
}
|
||||
+28
@@ -0,0 +1,28 @@
|
||||
package org.example;
|
||||
|
||||
import org.jetbrains.annotations.NotNull;
|
||||
import org.jetbrains.annotations.Nullable;
|
||||
|
||||
import java.util.List;
|
||||
|
||||
public class Formatter {
|
||||
@NotNull
|
||||
<T, V> List<T> getNotNullList() {
|
||||
return List.of();
|
||||
}
|
||||
|
||||
@Nullable
|
||||
<T, V> List<T> getNullableList() {
|
||||
return null;
|
||||
}
|
||||
|
||||
@NotNull
|
||||
String getNotNullName() {
|
||||
return "";
|
||||
}
|
||||
|
||||
@Nullable
|
||||
String getNullableName() {
|
||||
return null;
|
||||
}
|
||||
}
|
||||
+26
@@ -0,0 +1,26 @@
|
||||
package org.example;
|
||||
|
||||
import org.jetbrains.annotations.NotNull;
|
||||
import org.jetbrains.annotations.Nullable;
|
||||
|
||||
import java.util.List;
|
||||
|
||||
public class Formatter {
|
||||
@NotNull <T, V> List<T> getNotNullList() {
|
||||
return List.of();
|
||||
}
|
||||
|
||||
@Nullable <T, V> List<T> getNullableList() {
|
||||
return null;
|
||||
}
|
||||
|
||||
@NotNull
|
||||
String getNotNullName() {
|
||||
return "";
|
||||
}
|
||||
|
||||
@Nullable
|
||||
String getNullableName() {
|
||||
return null;
|
||||
}
|
||||
}
|
||||
+44
@@ -0,0 +1,44 @@
|
||||
// Copyright 2000-2024 JetBrains s.r.o. and contributors. Use of this source code is governed by the Apache 2.0 license.
|
||||
package com.intellij.java.psi.formatter.java
|
||||
|
||||
import com.intellij.JavaTestUtil
|
||||
import com.intellij.application.options.CodeStyle
|
||||
import com.intellij.lang.java.JavaLanguage
|
||||
import com.intellij.openapi.command.WriteCommandAction
|
||||
import com.intellij.openapi.roots.ModuleRootModificationUtil
|
||||
import com.intellij.psi.codeStyle.CodeStyleManager
|
||||
import com.intellij.psi.codeStyle.CommonCodeStyleSettings
|
||||
import com.intellij.psi.codeStyle.CommonCodeStyleSettings.WRAP_ALWAYS
|
||||
import com.intellij.testFramework.fixtures.DefaultLightProjectDescriptor
|
||||
import com.intellij.testFramework.fixtures.LightJavaCodeInsightFixtureTestCase
|
||||
|
||||
class TypeAnnotationFormatterTest : LightJavaCodeInsightFixtureTestCase() {
|
||||
private val commonSettings: CommonCodeStyleSettings
|
||||
get() = CodeStyle.getSettings(project).getCommonSettings(JavaLanguage.INSTANCE)
|
||||
|
||||
override fun getTestDataPath() = "${JavaTestUtil.getJavaTestDataPath()}/psi/formatter/java/typeAnnotation/"
|
||||
|
||||
override fun setUp() {
|
||||
super.setUp()
|
||||
commonSettings.METHOD_ANNOTATION_WRAP = WRAP_ALWAYS
|
||||
ModuleRootModificationUtil.updateModel(module, DefaultLightProjectDescriptor::addJetBrainsAnnotations)
|
||||
}
|
||||
|
||||
fun testKnownAnnotationBeforeType() = doTest()
|
||||
|
||||
fun testKnownAnnotationBeforeTypeParameterList() = doTest()
|
||||
|
||||
fun testCustomAnnotation() = doTest()
|
||||
|
||||
fun testManyKnownAnnotations() = doTest()
|
||||
|
||||
fun testPreserveWrappingSingleAnnotation() = doTest()
|
||||
|
||||
fun testPreserveWrappingManyAnnotations() = doTest()
|
||||
private fun doTest() {
|
||||
val testName = getTestName(false)
|
||||
myFixture.configureByFile("$testName.java")
|
||||
WriteCommandAction.runWriteCommandAction(project) { CodeStyleManager.getInstance(project).reformatText(file, 0, editor.document.textLength) }
|
||||
myFixture.checkResultByFile("${testName}_after.java")
|
||||
}
|
||||
}
|
||||
+1
-2
@@ -2,6 +2,5 @@ import org.jetbrains.annotations.Nullable;
|
||||
|
||||
interface A {
|
||||
|
||||
@Nullable
|
||||
<T, U> U foo(U u, T t);
|
||||
@Nullable <T, U> U foo(U u, T t);
|
||||
}
|
||||
Reference in New Issue
Block a user