IG: Make quick fix remove type arguments on qualifiers of references to static inner class (IDEA-317811)

for "Inner class may be 'static'" inspection

GitOrigin-RevId: fb55ca19c35522729f11bbcbd7e4f714b67524cb
This commit is contained in:
Bas Leijdekkers
2023-04-22 00:57:55 +00:00
committed by intellij-monorepo-bot
parent d0766b8618
commit e71f1d2194
15 changed files with 411 additions and 203 deletions
@@ -146,10 +146,6 @@ public class InnerClassMayBeStaticInspection extends BaseInspection {
this.innerClass = innerClass;
}
public List<PsiElement> getReferences() {
return references;
}
public List<PsiElement> getElements() {
final List<PsiElement> elements = new SmartList<>();
elements.add(innerClass);
@@ -171,6 +167,11 @@ public class InnerClassMayBeStaticInspection extends BaseInspection {
}
void makeStatic() {
final PsiModifierList modifiers = innerClass.getModifierList();
if (modifiers == null) {
return;
}
modifiers.setModifierProperty(PsiModifier.STATIC, true);
final Project project = innerClass.getProject();
final JavaCodeStyleManager codeStyleManager = JavaCodeStyleManager.getInstance(project);
final PsiElementFactory factory = JavaPsiFacade.getElementFactory(project);
@@ -178,28 +179,36 @@ public class InnerClassMayBeStaticInspection extends BaseInspection {
.sorted((r1, r2) -> PsiUtilCore.compareElementsByPosition(r2, r1))
.forEach(reference -> {
final PsiElement parent = reference.getParent();
if (!(parent instanceof PsiNewExpression newExpression)) {
return;
if (parent instanceof PsiNewExpression newExpression) {
final PsiJavaCodeReferenceElement classReference = newExpression.getClassReference();
if (classReference == null) {
return;
}
final PsiExpressionList argumentList = newExpression.getArgumentList();
if (argumentList == null) {
return;
}
final PsiReferenceParameterList parameterList = classReference.getParameterList();
final String genericParameters = parameterList != null ? parameterList.getText() : "";
final String text = "new " + classReference.getQualifiedName() + genericParameters + argumentList.getText();
final PsiExpression expression = factory.createExpressionFromText(text, innerClass);
codeStyleManager.shortenClassReferences(newExpression.replace(expression));
}
final PsiJavaCodeReferenceElement classReference = newExpression.getClassReference();
if (classReference == null) {
return;
else if (reference instanceof PsiJavaCodeReferenceElement ref) {
removeTypeArguments(ref);
}
final PsiExpressionList argumentList = newExpression.getArgumentList();
if (argumentList == null) {
return;
}
final PsiReferenceParameterList parameterList = classReference.getParameterList();
final String genericParameters = parameterList != null ? parameterList.getText() : "";
final PsiExpression expression = factory
.createExpressionFromText("new " + classReference.getQualifiedName() + genericParameters + argumentList.getText(), innerClass);
codeStyleManager.shortenClassReferences(newExpression.replace(expression));
});
final PsiModifierList modifiers = innerClass.getModifierList();
if (modifiers == null) {
}
private static void removeTypeArguments(PsiJavaCodeReferenceElement ref) {
if (ref == null || !(ref.getQualifier() instanceof PsiJavaCodeReferenceElement qualifier)) {
return;
}
modifiers.setModifierProperty(PsiModifier.STATIC, true);
removeTypeArguments(qualifier);
PsiReferenceParameterList parameterList = qualifier.getParameterList();
if (parameterList != null && parameterList.getFirstChild() != null) {
parameterList.delete();
}
}
}
}
@@ -1,25 +0,0 @@
class C {
public C(Feedback i) {
}
}
class Feedback {
String getOutputWindowName() {
return null;
}
}
class A {
protected static class B extends C {
public B() {
super(new Feedback() {
public void outputMessage() {
getOutputWindowName();
}
}
);
}
}
}
@@ -1,25 +0,0 @@
class C {
public C(Feedback i) {
}
}
class Feedback {
String getOutputWindowName() {
return null;
}
}
class A {
protected class <caret>B extends C {
public B() {
super(new Feedback() {
public void outputMessage() {
getOutputWindowName();
}
}
);
}
}
}
@@ -1,16 +0,0 @@
class IdeaTest {
public void test(){
print(new InnerClass<Integer>().foo(Integer.valueOf(1)));
}
public void print(Integer foo){
System.out.println(foo);
}
static class InnerClass<T>{
public T foo(T bar){
return bar;
}
}
}
@@ -1,16 +0,0 @@
class IdeaTest {
public void test(){
print(new InnerClass<Integer>().foo(Integer.valueOf(1)));
}
public void print(Integer foo){
System.out.println(foo);
}
class Inn<caret>erClass<T>{
public T foo(T bar){
return bar;
}
}
}
@@ -1,11 +0,0 @@
class Usage {
{
new Node(0, new Node(1, null));
}
private static class N<caret>ode {
Node(int idx, Node next) {
}
}
}
@@ -1,11 +0,0 @@
class Usage {
{
new Node(0, new Node(1, null));
}
private class N<caret>ode {
Node(int idx, Node next) {
}
}
}
@@ -1,18 +0,0 @@
package memory.inner_class_static;
class Simple {
static class Inner {}
void m() {
new Inner();
}
static void s(Simple s) {
new Inner();
}
}
class X {
X() {
new Simple.Inner();
}
}
@@ -1,18 +0,0 @@
package memory.inner_class_static;
class Simple {
class Inner<caret> {}
void m() {
new Inner();
}
static void s(Simple s) {
s.new Inner();
}
}
class X {
X() {
new Simple().new Inner();
}
}
@@ -0,0 +1,261 @@
package com.siyeh.igtest.memory.inner_class_may_be_static;
import javax.swing.*;
public class InnerClassMayBeStatic {
static class Nested {
public void foo() {
bar("InnerClassMayBeStaticInspection.this");
}
private void bar(String string) {
}
}
}
class IDEADEV_5513 {
private static class Inner {
private boolean b = false;
private class InnerInner {
public void foo() {
b = true;
}
}
}
}
class C extends JComponent {
private class I {
public void foo() {
SwingUtilities.invokeLater(new Runnable() {
public void run() {
repaint();
}
});
}
}
}
class D {
void foo() {
new Object() {
class Y {}
};
}
}
class StaticInnerClass {
private int foo;
int bar;
public class Baz extends StaticInnerClass {
Baz() {
foo = -1;
}
}
static class C extends StaticInnerClass {{
bar = 1;
}}
}
class SomeBeanUnitTest {
private static class BeanCreator {
public BeanCreator withQuery() {
return null;
}
}
}
class Outer {
class A { // may be static
B b;
}
class B extends A {} // may not be static
static class C { // may be static
D b;
class D extends C {}
}
static class E {
G.F b;
static class G { // may be static
class F extends E {}
}
}
static class H { // may be static
J.I b;
class J {
class I extends H {}
}
}
}
class Complex {
class C {
void m() {
Complex.super.toString();
}
}
int i;
static void n() {
}
private static class A {
private A() {
}
}
static class B {
}
static class F extends Complex {
class G {
}
{
A a = (A) null;
G g = (G) null;
new A() {};
new B();
i = 10;
new E().m();
Complex.n();
}
void m(A a) {
a.toString();
}
class E {
private void m() {
}
}
}
}
class Test1<T> {
class Inner {
private final T test;
public Inner(T test) {
this.test = test;
}
}
}
class Test2 {
static class Inner<T> {
private final T test;
public Inner(T test) {
this.test = test;
}
}
}
class ImplicitConstructorReference {
class A {
C x = B::new;
}
interface C {
B m();
}
static class B {}
}
class Scratch
{
public static void main(String[] args)
{
class Inner
{
class Nested // can't be static
{}
}
}
}
class JUnit5Test {
@org.junit.jupiter.api.Nested
class Inner {
}
}
abstract class JavaClass<T> {
public static class InnerClass<M> {}
public static <K, L> JavaClass.InnerClass<L> baz(K t) {
return null;
}
}
class Simple {
static class Inner {}
void m() {
new Inner();
}
static void s(Simple s) {
new Inner();
}
}
class X {
X() {
new Simple.Inner();
}
}
class Usage {
{
new Node(0, new Node(1, null));
}
private static class Node {
Node(int idx, Node next) {
}
}
}
class IdeaTest {
public void test(){
print(new InnerClass<Integer>().foo(Integer.valueOf(1)));
}
public void print(Integer foo){
System.out.println(foo);
}
static class InnerClass<T>{
public T foo(T bar){
return bar;
}
}
}
class C1 {
public C1(Feedback i) {
}
}
class Feedback {
String getOutputWindowName() {
return null;
}
}
class A {
protected static class B extends C1 {
public B() {
super(new Feedback() {
public void outputMessage() {
getOutputWindowName();
}
}
);
}
}
}
@@ -3,7 +3,7 @@ package com.siyeh.igtest.memory.inner_class_may_be_static;
import javax.swing.*;
public class InnerClassMayBeStatic {
class <warning descr="Inner class 'Nested' may be 'static'">Nested</warning> {
class <warning descr="Inner class 'Nested' may be 'static'"><caret>Nested</warning> {
public void foo() {
bar("InnerClassMayBeStaticInspection.this");
}
@@ -183,4 +183,79 @@ class JUnit5Test {
class Inner {
}
}
abstract class JavaClass<T> {
public class <warning descr="Inner class 'InnerClass' may be 'static'">InnerClass</warning><M> {}
public static <K, L> JavaClass<K>.InnerClass<L> baz(K t) {
return null;
}
}
class Simple {
class <warning descr="Inner class 'Inner' may be 'static'">Inner</warning> {}
void m() {
new Inner();
}
static void s(Simple s) {
s.new Inner();
}
}
class X {
X() {
new Simple().new Inner();
}
}
class Usage {
{
new Node(0, new Node(1, null));
}
private class <warning descr="Inner class 'Node' may be 'static'">Node</warning> {
Node(int idx, Node next) {
}
}
}
class IdeaTest {
public void test(){
print(new InnerClass<Integer>().foo(Integer.valueOf(1)));
}
public void print(Integer foo){
System.out.println(foo);
}
class <warning descr="Inner class 'InnerClass' may be 'static'">InnerClass</warning><T>{
public T foo(T bar){
return bar;
}
}
}
class C1 {
public C1(Feedback i) {
}
}
class Feedback {
String getOutputWindowName() {
return null;
}
}
class A {
protected class <warning descr="Inner class 'B' may be 'static'">B</warning> extends C1 {
public B() {
super(new Feedback() {
public void outputMessage() {
getOutputWindowName();
}
}
);
}
}
}
@@ -0,0 +1,29 @@
class InnerStaticsJDK16
{
static class One {
static class Two {}
}
public static void main(String[] args)
{
class Inner
{
static class Nested
{}
}
new Object() {
static class Y {}
};
}
}
class One<A> {
private int i;
class Two<B> {
private int j = i;
static class Three<C> {}
}
public static void main(String[] args) {
One.Two.Three<Void> x;
}
}
@@ -1,13 +1,13 @@
class InnerStaticsJDK16
{
class <warning descr="Inner class 'One' may be 'static'">One</warning> {
class <warning descr="Inner class 'One' may be 'static'"><caret>One</warning> {
class <warning descr="Inner class 'Two' may be 'static'">Two</warning> {}
}
public static void main(String[] args)
{
class Inner
{
class <warning descr="Inner class 'Nested' may be 'static'">Nested</warning> // can't be static
class <warning descr="Inner class 'Nested' may be 'static'">Nested</warning>
{}
}
new Object() {
@@ -15,4 +15,15 @@ class InnerStaticsJDK16
};
}
}
class One<A> {
private int i;
class Two<B> {
private int j = i;
class <warning descr="Inner class 'Three' may be 'static'">Three</warning><C> {}
}
public static void main(String[] args) {
One<Void>.Two<Void>.Three<Void> x;
}
}
@@ -1,39 +0,0 @@
/*
* Copyright 2000-2013 JetBrains s.r.o.
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/
package com.siyeh.ig.fixes.memory;
import com.siyeh.InspectionGadgetsBundle;
import com.siyeh.ig.IGQuickFixesTestCase;
import com.siyeh.ig.memory.InnerClassMayBeStaticInspection;
/**
* @author Bas Leijdekkers
*/
public class InnerClassMayBeStaticFixTest extends IGQuickFixesTestCase {
@Override
protected void setUp() throws Exception {
super.setUp();
myFixture.enableInspections(new InnerClassMayBeStaticInspection());
myRelativePath = "memory/inner_class_static";
myDefaultHint = InspectionGadgetsBundle.message("make.static.quickfix");
}
public void testSimple() { doTest(); }
public void testAnonymousInside() { doTest(); }
public void testPreserveGenericSignature() { doTest(); }
public void testRecursiveType() { doTest(); }
}
@@ -19,12 +19,14 @@ public class InnerClassMayBeStaticInspectionTest extends LightJavaInspectionTest
public void testInnerClassMayBeStatic() {
IdeaTestUtil.withLevel(getModule(), LanguageLevel.JDK_15, () -> {
doTest();
checkQuickFixAll();
});
}
public void testInnerStaticsJDK16() {
IdeaTestUtil.withLevel(getModule(), LanguageLevel.JDK_16, () -> {
doTest();
checkQuickFixAll();
});
}