mirror of
https://gitflic.ru/project/openide/openide.git
synced 2026-04-19 04:51:24 +07:00
[java-highlighting] IDEA-341371 highlight duplicated classes with implicit classes
GitOrigin-RevId: 37e436871498d0c9470f164daaf2edb892082667
This commit is contained in:
committed by
intellij-monorepo-bot
parent
7cbbfe6b03
commit
39b2be10ff
@@ -29,6 +29,7 @@ import com.intellij.openapi.util.io.FileUtil;
|
||||
import com.intellij.openapi.vfs.VirtualFile;
|
||||
import com.intellij.pom.java.LanguageLevel;
|
||||
import com.intellij.psi.*;
|
||||
import com.intellij.psi.impl.java.stubs.index.JavaImplicitClassIndex;
|
||||
import com.intellij.psi.impl.source.resolve.JavaResolveUtil;
|
||||
import com.intellij.psi.search.GlobalSearchScope;
|
||||
import com.intellij.psi.search.searches.DirectClassInheritorsSearch;
|
||||
@@ -173,6 +174,7 @@ public final class HighlightClassUtil {
|
||||
}
|
||||
|
||||
static HighlightInfo.Builder checkDuplicateTopLevelClass(@NotNull PsiClass aClass) {
|
||||
if (aClass instanceof PsiImplicitClass) return null; //check in HighlightImplicitClassUtil
|
||||
if (!(aClass.getParent() instanceof PsiFile)) return null;
|
||||
String qualifiedName = aClass.getQualifiedName();
|
||||
if (qualifiedName == null) return null;
|
||||
@@ -181,12 +183,31 @@ public final class HighlightClassUtil {
|
||||
qualifiedName = qualifiedName.replace('$', '.');
|
||||
numOfClassesToFind = 1;
|
||||
}
|
||||
PsiManager manager = aClass.getManager();
|
||||
|
||||
Module module = ModuleUtilCore.findModuleForPsiElement(aClass);
|
||||
if (module == null) return null;
|
||||
|
||||
PsiClass[] classes = JavaPsiFacade.getInstance(aClass.getProject()).findClasses(qualifiedName, GlobalSearchScope.moduleScope(module).intersectWith(aClass.getResolveScope()));
|
||||
GlobalSearchScope scope = GlobalSearchScope.moduleScope(module).intersectWith(aClass.getResolveScope());
|
||||
PsiClass[] classes = JavaPsiFacade.getInstance(aClass.getProject()).findClasses(qualifiedName, scope);
|
||||
if (aClass.getContainingFile() instanceof PsiJavaFile javaFile && javaFile.getPackageStatement() == null) {
|
||||
Collection<? extends PsiClass> implicitClasses =
|
||||
JavaImplicitClassIndex.getInstance().getElements(qualifiedName, javaFile.getProject(), scope);
|
||||
if (!implicitClasses.isEmpty()) {
|
||||
ArrayList<PsiClass> newClasses = new ArrayList<>();
|
||||
ContainerUtil.addAll(newClasses, classes);
|
||||
ContainerUtil.addAll(newClasses, implicitClasses);
|
||||
classes = newClasses.toArray(PsiClass.EMPTY_ARRAY);
|
||||
}
|
||||
}
|
||||
if (classes.length < numOfClassesToFind) return null;
|
||||
return checkDuplicateClasses(aClass, classes);
|
||||
}
|
||||
|
||||
@Nullable
|
||||
static HighlightInfo.Builder checkDuplicateClasses(@NotNull PsiClass aClass, @NotNull PsiClass @NotNull[] classes) {
|
||||
PsiManager manager = aClass.getManager();
|
||||
Module module = ModuleUtilCore.findModuleForPsiElement(aClass);
|
||||
if (module == null) return null;
|
||||
ModuleFileIndex fileIndex = ModuleRootManager.getInstance(module).getFileIndex();
|
||||
VirtualFile virtualFile = PsiUtilCore.getVirtualFile(aClass);
|
||||
if (virtualFile == null) return null;
|
||||
@@ -362,12 +383,27 @@ public final class HighlightClassUtil {
|
||||
@NotNull @PropertyKey(resourceBundle = JavaErrorBundle.BUNDLE) String key) {
|
||||
String message = JavaErrorBundle.message(key, name);
|
||||
PsiIdentifier identifier = aClass.getNameIdentifier();
|
||||
if (identifier == null) return null;
|
||||
TextRange textRange = identifier.getTextRange();
|
||||
HighlightInfo.Builder info = HighlightInfo.newHighlightInfo(HighlightInfoType.ERROR).range(textRange).descriptionAndTooltip(message);
|
||||
IntentionAction action = QuickFixFactory.getInstance().createRenameFix(aClass);
|
||||
if (action != null) {
|
||||
info.registerFix(action, null, null, null, null);
|
||||
HighlightInfo.Builder info;
|
||||
if (aClass instanceof PsiImplicitClass) {
|
||||
info = HighlightInfo.newHighlightInfo(HighlightInfoType.ERROR)
|
||||
.range(aClass)
|
||||
.fileLevelAnnotation()
|
||||
.description(message);
|
||||
IntentionAction action = QuickFixFactory.getInstance().createRenameFix(aClass);
|
||||
if (action != null) {
|
||||
info.registerFix(action, null, null, null, null);
|
||||
}
|
||||
}
|
||||
else {
|
||||
if (identifier == null) return null;
|
||||
TextRange textRange = identifier.getTextRange();
|
||||
info = HighlightInfo.newHighlightInfo(HighlightInfoType.ERROR)
|
||||
.range(textRange)
|
||||
.descriptionAndTooltip(message);
|
||||
IntentionAction action = QuickFixFactory.getInstance().createRenameFix(aClass);
|
||||
if (action != null) {
|
||||
info.registerFix(action, null, null, null, null);
|
||||
}
|
||||
}
|
||||
return info;
|
||||
}
|
||||
|
||||
@@ -5,7 +5,10 @@ import com.intellij.codeInsight.daemon.JavaErrorBundle;
|
||||
import com.intellij.codeInsight.daemon.impl.HighlightInfo;
|
||||
import com.intellij.codeInsight.daemon.impl.HighlightInfoType;
|
||||
import com.intellij.codeInsight.intention.QuickFixFactory;
|
||||
import com.intellij.openapi.module.Module;
|
||||
import com.intellij.openapi.module.ModuleUtilCore;
|
||||
import com.intellij.psi.*;
|
||||
import com.intellij.psi.search.GlobalSearchScope;
|
||||
import com.intellij.psi.util.JavaImplicitClassUtil;
|
||||
import com.intellij.psi.util.PsiMethodUtil;
|
||||
import com.intellij.util.containers.ContainerUtil;
|
||||
@@ -63,4 +66,22 @@ public final class HighlightImplicitClassUtil {
|
||||
}
|
||||
return null;
|
||||
}
|
||||
|
||||
@Nullable
|
||||
static HighlightInfo.Builder checkDuplicateClasses(@NotNull PsiJavaFile file) {
|
||||
if (!HighlightingFeature.IMPLICIT_CLASSES.isAvailable(file)) return null;
|
||||
PsiImplicitClass implicitClass = JavaImplicitClassUtil.getImplicitClassFor(file);
|
||||
if (implicitClass == null) return null;
|
||||
|
||||
Module module = ModuleUtilCore.findModuleForPsiElement(file);
|
||||
if (module == null) return null;
|
||||
|
||||
GlobalSearchScope scope = GlobalSearchScope.moduleScope(module).intersectWith(implicitClass.getResolveScope());
|
||||
String qualifiedName = implicitClass.getQualifiedName();
|
||||
if (qualifiedName == null) {
|
||||
return null;
|
||||
}
|
||||
PsiClass[] classes = JavaPsiFacade.getInstance(implicitClass.getProject()).findClasses(qualifiedName, scope);
|
||||
return HighlightClassUtil.checkDuplicateClasses(implicitClass, classes);
|
||||
}
|
||||
}
|
||||
|
||||
@@ -375,6 +375,7 @@ public class HighlightVisitorImpl extends JavaElementVisitor implements Highligh
|
||||
super.visitJavaFile(file);
|
||||
if (!hasErrorResults()) add(HighlightImplicitClassUtil.checkImplicitClassHasMainMethod(file));
|
||||
if (!hasErrorResults()) add(HighlightImplicitClassUtil.checkImplicitClassFileIsValidIdentifier(file));
|
||||
if (!hasErrorResults()) add(HighlightImplicitClassUtil.checkDuplicateClasses(file));
|
||||
}
|
||||
|
||||
@Override
|
||||
|
||||
@@ -0,0 +1,3 @@
|
||||
public static void main(String[] args) {
|
||||
System.out.println("I am an implicitly declared class");
|
||||
}
|
||||
@@ -4,6 +4,7 @@ package com.intellij.java.codeInsight.daemon
|
||||
import com.intellij.JavaTestUtil
|
||||
import com.intellij.pom.java.LanguageLevel
|
||||
import com.intellij.testFramework.IdeaTestUtil
|
||||
import com.intellij.testFramework.UsefulTestCase
|
||||
import com.intellij.testFramework.fixtures.LightJavaCodeInsightFixtureTestCase
|
||||
|
||||
class ImplicitClassHighlightingTest : LightJavaCodeInsightFixtureTestCase() {
|
||||
@@ -41,6 +42,30 @@ class ImplicitClassHighlightingTest : LightJavaCodeInsightFixtureTestCase() {
|
||||
doTest()
|
||||
}
|
||||
|
||||
fun testDuplicateImplicitClass() {
|
||||
myFixture.configureByText("T.java", """
|
||||
class DuplicateImplicitClass {
|
||||
|
||||
}
|
||||
""".trimIndent())
|
||||
myFixture.configureByFile(getTestName(false) + ".java")
|
||||
val highlightings = myFixture.doHighlighting().filter { it?.description?.contains("Duplicate class") ?: false }
|
||||
UsefulTestCase.assertNotEmpty(highlightings)
|
||||
}
|
||||
|
||||
fun testDuplicateImplicitClass2() {
|
||||
myFixture.configureByText("DuplicateImplicitClass2.java", """
|
||||
public static void main(String[] args) {
|
||||
System.out.println("I am an implicitly declared class");
|
||||
}
|
||||
""".trimIndent())
|
||||
myFixture.configureByText("T.java", """
|
||||
class DuplicateImplicitClass2 {}
|
||||
""".trimIndent())
|
||||
val highlightings = myFixture.doHighlighting().filter { it?.description?.contains("Duplicate class") ?: false }
|
||||
UsefulTestCase.assertNotEmpty(highlightings)
|
||||
}
|
||||
|
||||
private fun doTest() {
|
||||
myFixture.configureByFile(getTestName(false) + ".java")
|
||||
myFixture.checkHighlighting()
|
||||
|
||||
Reference in New Issue
Block a user