mirror of
https://gitflic.ru/project/openide/openide.git
synced 2025-12-16 14:23:28 +07:00
Java: inner class accessing local variable or parameter can't be static (IDEA-375602)
(cherry picked from commit 1b16d1388c09d51009b288ede89e73d156364619) IJ-CR-168593 GitOrigin-RevId: 7ff7cfa95cdc674c5b1d32a572eec0b95bbfb58d
This commit is contained in:
committed by
intellij-monorepo-bot
parent
5df57ad536
commit
9a906a8753
@@ -1,5 +1,5 @@
|
|||||||
/*
|
/*
|
||||||
* Copyright 2003-2017 Dave Griffith, Bas Leijdekkers
|
* Copyright 2003-2025 Dave Griffith, Bas Leijdekkers
|
||||||
*
|
*
|
||||||
* Licensed under the Apache License, Version 2.0 (the "License");
|
* Licensed under the Apache License, Version 2.0 (the "License");
|
||||||
* you may not use this file except in compliance with the License.
|
* you may not use this file except in compliance with the License.
|
||||||
@@ -24,11 +24,11 @@ import org.jetbrains.annotations.NotNull;
|
|||||||
public class InnerClassReferenceVisitor extends JavaRecursiveElementWalkingVisitor {
|
public class InnerClassReferenceVisitor extends JavaRecursiveElementWalkingVisitor {
|
||||||
|
|
||||||
private final PsiClass innerClass;
|
private final PsiClass innerClass;
|
||||||
|
private final boolean allowReferencesToLocalVariables;
|
||||||
private boolean referencesStaticallyAccessible = true;
|
private boolean referencesStaticallyAccessible = true;
|
||||||
private boolean allowReferencesToLocalVariables = true;
|
|
||||||
|
|
||||||
public InnerClassReferenceVisitor(@NotNull PsiClass innerClass) {
|
public InnerClassReferenceVisitor(@NotNull PsiClass innerClass) {
|
||||||
this.innerClass = innerClass;
|
this(innerClass, false);
|
||||||
}
|
}
|
||||||
|
|
||||||
public InnerClassReferenceVisitor(@NotNull PsiClass innerClass, boolean allowReferencesToLocalVariables) {
|
public InnerClassReferenceVisitor(@NotNull PsiClass innerClass, boolean allowReferencesToLocalVariables) {
|
||||||
@@ -51,8 +51,8 @@ public class InnerClassReferenceVisitor extends JavaRecursiveElementWalkingVisit
|
|||||||
if (PsiTreeUtil.isAncestor(innerClass, aClass, false) || aClass.hasModifierProperty(PsiModifier.STATIC)) {
|
if (PsiTreeUtil.isAncestor(innerClass, aClass, false) || aClass.hasModifierProperty(PsiModifier.STATIC)) {
|
||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
if (aClass instanceof PsiTypeParameter) {
|
if (aClass instanceof PsiTypeParameter parameter) {
|
||||||
PsiTypeParameterListOwner owner = ((PsiTypeParameter)aClass).getOwner();
|
PsiTypeParameterListOwner owner = parameter.getOwner();
|
||||||
return owner != null && PsiTreeUtil.isAncestor(innerClass, owner, false);
|
return owner != null && PsiTreeUtil.isAncestor(innerClass, owner, false);
|
||||||
}
|
}
|
||||||
final PsiClass containingClass = aClass.getContainingClass();
|
final PsiClass containingClass = aClass.getContainingClass();
|
||||||
@@ -98,7 +98,7 @@ public class InnerClassReferenceVisitor extends JavaRecursiveElementWalkingVisit
|
|||||||
}
|
}
|
||||||
final PsiElement target = expression.resolve();
|
final PsiElement target = expression.resolve();
|
||||||
if (target == null) {
|
if (target == null) {
|
||||||
referencesStaticallyAccessible = false; // TODO(bartekpacia): We probably should introduce the 3rd "unknown" state to signal this
|
referencesStaticallyAccessible = false;
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
if (target instanceof PsiLocalVariable || target instanceof PsiParameter) {
|
if (target instanceof PsiLocalVariable || target instanceof PsiParameter) {
|
||||||
@@ -128,7 +128,7 @@ public class InnerClassReferenceVisitor extends JavaRecursiveElementWalkingVisit
|
|||||||
}
|
}
|
||||||
referencesStaticallyAccessible = false;
|
referencesStaticallyAccessible = false;
|
||||||
}
|
}
|
||||||
else if (target instanceof PsiClass && !isClassStaticallyAccessible((PsiClass)target)) {
|
else if (target instanceof PsiClass aClass && !isClassStaticallyAccessible(aClass)) {
|
||||||
referencesStaticallyAccessible = false;
|
referencesStaticallyAccessible = false;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@@ -144,10 +144,7 @@ public class InnerClassReferenceVisitor extends JavaRecursiveElementWalkingVisit
|
|||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
final PsiElement target = classReference.resolve();
|
final PsiElement target = classReference.resolve();
|
||||||
if (!(target instanceof PsiClass)) {
|
if (target instanceof PsiClass aClass && !isClassStaticallyAccessible(aClass)) {
|
||||||
return;
|
|
||||||
}
|
|
||||||
if (!isClassStaticallyAccessible((PsiClass)target)) {
|
|
||||||
referencesStaticallyAccessible = false;
|
referencesStaticallyAccessible = false;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -128,7 +128,7 @@ public final class ConvertToRecordFix implements LocalQuickFix {
|
|||||||
* @see com.siyeh.ig.memory.InnerClassMayBeStaticInspection
|
* @see com.siyeh.ig.memory.InnerClassMayBeStaticInspection
|
||||||
*/
|
*/
|
||||||
private static boolean containsOuterNonStaticReferences(PsiClass psiClass) {
|
private static boolean containsOuterNonStaticReferences(PsiClass psiClass) {
|
||||||
InnerClassReferenceVisitor visitor = new InnerClassReferenceVisitor(psiClass, false);
|
InnerClassReferenceVisitor visitor = new InnerClassReferenceVisitor(psiClass);
|
||||||
psiClass.accept(visitor);
|
psiClass.accept(visitor);
|
||||||
return !visitor.canInnerClassBeStatic();
|
return !visitor.canInnerClassBeStatic();
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -1,5 +1,5 @@
|
|||||||
/*
|
/*
|
||||||
* Copyright 2003-2023 Dave Griffith, Bas Leijdekkers
|
* Copyright 2003-2025 Dave Griffith, Bas Leijdekkers
|
||||||
*
|
*
|
||||||
* Licensed under the Apache License, Version 2.0 (the "License");
|
* Licensed under the Apache License, Version 2.0 (the "License");
|
||||||
* you may not use this file except in compliance with the License.
|
* you may not use this file except in compliance with the License.
|
||||||
@@ -78,7 +78,7 @@ public final class AnonymousInnerClassMayBeStaticInspection extends BaseInspecti
|
|||||||
// strictly speaking can be named static inner class but not when part of the current containing class
|
// strictly speaking can be named static inner class but not when part of the current containing class
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
final InnerClassReferenceVisitor visitor = new InnerClassReferenceVisitor(anonymousClass);
|
final InnerClassReferenceVisitor visitor = new InnerClassReferenceVisitor(anonymousClass, true);
|
||||||
anonymousClass.accept(visitor);
|
anonymousClass.accept(visitor);
|
||||||
if (!visitor.canInnerClassBeStatic()) {
|
if (!visitor.canInnerClassBeStatic()) {
|
||||||
return;
|
return;
|
||||||
@@ -106,7 +106,7 @@ public final class AnonymousInnerClassMayBeStaticInspection extends BaseInspecti
|
|||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
final PsiElement target = reference.resolve();
|
final PsiElement target = reference.resolve();
|
||||||
if (!(target instanceof PsiClass) || !PsiUtil.isLocalClass((PsiClass)target)) {
|
if (!(target instanceof PsiClass aClass) || !PsiUtil.isLocalClass(aClass)) {
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
referenceToLocalClass = true;
|
referenceToLocalClass = true;
|
||||||
|
|||||||
@@ -26,4 +26,15 @@ class One<A> {
|
|||||||
public static void main(String[] args) {
|
public static void main(String[] args) {
|
||||||
One.Two.Three<Void> x;
|
One.Two.Three<Void> x;
|
||||||
}
|
}
|
||||||
|
}
|
||||||
|
class C {
|
||||||
|
void x(int i) {
|
||||||
|
new Object() {
|
||||||
|
class Local { // can't be static
|
||||||
|
int get() {
|
||||||
|
return i;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
};
|
||||||
|
}
|
||||||
}
|
}
|
||||||
@@ -26,4 +26,15 @@ class One<A> {
|
|||||||
public static void main(String[] args) {
|
public static void main(String[] args) {
|
||||||
One<Void>.Two<Void>.Three<Void> x;
|
One<Void>.Two<Void>.Three<Void> x;
|
||||||
}
|
}
|
||||||
|
}
|
||||||
|
class C {
|
||||||
|
void x(int i) {
|
||||||
|
new Object() {
|
||||||
|
class Local { // can't be static
|
||||||
|
int get() {
|
||||||
|
return i;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
};
|
||||||
|
}
|
||||||
}
|
}
|
||||||
@@ -1,18 +1,4 @@
|
|||||||
/*
|
// Copyright 2000-2025 JetBrains s.r.o. and contributors. Use of this source code is governed by the Apache 2.0 license.
|
||||||
* Copyright 2000-2015 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.classlayout;
|
package com.siyeh.ig.classlayout;
|
||||||
|
|
||||||
import com.intellij.codeInspection.InspectionProfileEntry;
|
import com.intellij.codeInspection.InspectionProfileEntry;
|
||||||
@@ -69,6 +55,30 @@ public class ClassMayBeInterfaceInspectionTest extends LightJavaInspectionTestCa
|
|||||||
}""");
|
}""");
|
||||||
}
|
}
|
||||||
|
|
||||||
|
public void testLocalClassAccessingParameter() {
|
||||||
|
doTest("""
|
||||||
|
class Outer {
|
||||||
|
void x(int parameter) {
|
||||||
|
abstract class Example {
|
||||||
|
public static final int MY_CONST = 42;
|
||||||
|
public abstract void foo();
|
||||||
|
|
||||||
|
public void g() {
|
||||||
|
System.out.println(parameter);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
class Inheritor extends Example {
|
||||||
|
@Override
|
||||||
|
public void foo() {
|
||||||
|
System.out.println(MY_CONST);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
""");
|
||||||
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
protected InspectionProfileEntry getInspection() {
|
protected InspectionProfileEntry getInspection() {
|
||||||
final ClassMayBeInterfaceInspection inspection = new ClassMayBeInterfaceInspection();
|
final ClassMayBeInterfaceInspection inspection = new ClassMayBeInterfaceInspection();
|
||||||
|
|||||||
Reference in New Issue
Block a user