mirror of
https://gitflic.ru/project/openide/openide.git
synced 2026-03-22 15:19:59 +07:00
[java-highlighting] IDEA-363617 Support JEP 494: Module Import Declarations (Second Preview)
- support shadowing module imports by package-on-demand (cherry picked from commit 643fc10bcbfee2f1d41ec02e624b30bc3a48e4bb) GitOrigin-RevId: d1e49b2d48f0b69f8e15393cb823e5529f9b4452
This commit is contained in:
committed by
intellij-monorepo-bot
parent
2ce2af7f8e
commit
aea70bba3b
@@ -123,6 +123,7 @@ feature.foreign.functions=Foreign Function & Memory API
|
||||
feature.virtual.threads=Virtual Threads
|
||||
feature.statements.before.super=Statements before super()
|
||||
feature.module.import.declarations=Module Import Declarations
|
||||
feature.package.import.shadow.module.import=Import-on-demand over module import
|
||||
|
||||
else.without.if='else' without 'if'
|
||||
enum.constant.context=Enum constant ''{0}'' in ''{1}''
|
||||
|
||||
@@ -117,7 +117,9 @@ public enum JavaFeature {
|
||||
IMPLICIT_IMPORT_IN_IMPLICIT_CLASSES(LanguageLevel.JDK_23_PREVIEW, "feature.implicit.import.in.implicit.classes"),
|
||||
PRIMITIVE_TYPES_IN_PATTERNS(LanguageLevel.JDK_23_PREVIEW, "feature.primitive.types.in.patterns"),
|
||||
|
||||
//see together with PACKAGE_IMPORTS_SHADOW_MODULE_IMPORTS
|
||||
MODULE_IMPORT_DECLARATIONS(LanguageLevel.JDK_23_PREVIEW, "feature.module.import.declarations"),
|
||||
PACKAGE_IMPORTS_SHADOW_MODULE_IMPORTS(LanguageLevel.JDK_24_PREVIEW, "feature.package.import.shadow.module.import"),
|
||||
;
|
||||
|
||||
private final @NotNull LanguageLevel myLevel;
|
||||
|
||||
@@ -5,6 +5,7 @@ import com.intellij.openapi.diagnostic.Logger;
|
||||
import com.intellij.openapi.util.Comparing;
|
||||
import com.intellij.openapi.util.Key;
|
||||
import com.intellij.openapi.util.text.StringUtil;
|
||||
import com.intellij.pom.java.JavaFeature;
|
||||
import com.intellij.psi.*;
|
||||
import com.intellij.psi.impl.source.PsiAnonymousClassImpl;
|
||||
import com.intellij.psi.infos.CandidateInfo;
|
||||
@@ -14,9 +15,11 @@ import com.intellij.psi.scope.JavaScopeProcessorEvent;
|
||||
import com.intellij.psi.scope.NameHint;
|
||||
import com.intellij.psi.scope.PsiScopeProcessor;
|
||||
import com.intellij.psi.util.PsiTreeUtil;
|
||||
import com.intellij.psi.util.PsiUtil;
|
||||
import com.intellij.util.ArrayUtil;
|
||||
import com.intellij.util.SmartList;
|
||||
import org.jetbrains.annotations.NotNull;
|
||||
import org.jetbrains.annotations.Nullable;
|
||||
|
||||
import java.util.Iterator;
|
||||
import java.util.List;
|
||||
@@ -171,9 +174,25 @@ public class ClassResolverProcessor implements PsiScopeProcessor, NameHint, Elem
|
||||
return Domination.DOMINATES;
|
||||
}
|
||||
|
||||
// on-demand wins over module import
|
||||
if (PsiUtil.isAvailable(JavaFeature.PACKAGE_IMPORTS_SHADOW_MODULE_IMPORTS, myPlace)) {
|
||||
boolean myIsModule = isImportedByModule(myCurrentFileContext);
|
||||
boolean otherIsModule = isImportedByModule(info.getCurrentFileResolveScope());
|
||||
if (myIsModule && otherOnDemand && !otherIsModule) {
|
||||
return Domination.DOMINATED_BY;
|
||||
}
|
||||
if (myOnDemand && !myIsModule && otherIsModule) {
|
||||
return Domination.DOMINATES;
|
||||
}
|
||||
}
|
||||
|
||||
return Domination.EQUAL;
|
||||
}
|
||||
|
||||
private static boolean isImportedByModule(@Nullable PsiElement context) {
|
||||
return context instanceof PsiImportModuleStatement;
|
||||
}
|
||||
|
||||
private boolean isAccessible(PsiClass otherClass) {
|
||||
if (otherClass.hasModifierProperty(PsiModifier.PRIVATE)) {
|
||||
final PsiClass containingClass = otherClass.getContainingClass();
|
||||
|
||||
@@ -0,0 +1,5 @@
|
||||
import module java.sql;
|
||||
|
||||
public static void main(String[] args) {
|
||||
Date date = new Date();
|
||||
}
|
||||
@@ -0,0 +1,6 @@
|
||||
import a.b.*;
|
||||
|
||||
<error descr="Reference to 'List' is ambiguous, both 'a.b.List' and 'java.util.List' match">List</error><caret> a;
|
||||
|
||||
void main() {
|
||||
}
|
||||
@@ -0,0 +1,6 @@
|
||||
import a.b.*;
|
||||
|
||||
List<caret> a;
|
||||
|
||||
void main() {
|
||||
}
|
||||
@@ -0,0 +1,4 @@
|
||||
List<caret> a;
|
||||
|
||||
void main() {
|
||||
}
|
||||
@@ -0,0 +1,6 @@
|
||||
import a.b.List;
|
||||
|
||||
List<caret> a;
|
||||
|
||||
void main() {
|
||||
}
|
||||
@@ -0,0 +1,5 @@
|
||||
import module my.source.moduleB;
|
||||
import module my.source.moduleA;
|
||||
class AmbiguousModuleImport {
|
||||
<error descr="Reference to 'Imported' is ambiguous, both 'my.source.moduleB.Imported' and 'my.source.moduleA.Imported' match">Imported</error> <caret>module;
|
||||
}
|
||||
@@ -0,0 +1,7 @@
|
||||
import module my.source.moduleB;
|
||||
|
||||
import my.source.moduleA.*;
|
||||
|
||||
class AmbiguousModuleImportWithPackageImport {
|
||||
<error descr="Reference to 'Imported' is ambiguous, both 'my.source.moduleA.Imported' and 'my.source.moduleB.Imported' match">Imported</error> module;
|
||||
}
|
||||
@@ -0,0 +1,5 @@
|
||||
import module my.source.moduleB;
|
||||
|
||||
class ModuleImportWithDefaultPackageImport {
|
||||
String<caret> a;
|
||||
}
|
||||
@@ -0,0 +1,7 @@
|
||||
import module my.source.moduleB;
|
||||
|
||||
import my.source.moduleA.*;
|
||||
|
||||
class ModuleImportWithPackageImport {
|
||||
Imported <caret>module;
|
||||
}
|
||||
@@ -0,0 +1,7 @@
|
||||
import module my.source.moduleB;
|
||||
|
||||
import my.source.moduleA.Imported;
|
||||
|
||||
class ModuleImportWithSingleImport {
|
||||
Imported <caret>module;
|
||||
}
|
||||
@@ -6,9 +6,11 @@ import com.intellij.pom.java.JavaFeature
|
||||
import com.intellij.pom.java.LanguageLevel
|
||||
import com.intellij.psi.*
|
||||
import com.intellij.psi.util.PsiUtil
|
||||
import com.intellij.psi.util.parentOfType
|
||||
import com.intellij.testFramework.IdeaTestUtil
|
||||
import com.intellij.testFramework.UsefulTestCase
|
||||
import com.intellij.testFramework.fixtures.LightJavaCodeInsightFixtureTestCase
|
||||
import org.jetbrains.plugins.groovy.intentions.style.inference.resolve
|
||||
|
||||
class ImplicitClassHighlightingTest : LightJavaCodeInsightFixtureTestCase() {
|
||||
override fun getProjectDescriptor() = JAVA_21
|
||||
@@ -105,6 +107,63 @@ class ImplicitClassHighlightingTest : LightJavaCodeInsightFixtureTestCase() {
|
||||
})
|
||||
}
|
||||
|
||||
fun testImplicitWithPackages() {
|
||||
IdeaTestUtil.withLevel(module, JavaFeature.IMPLICIT_IMPORT_IN_IMPLICIT_CLASSES.minimumLevel, Runnable {
|
||||
myFixture.addClass("""
|
||||
package a.b;
|
||||
|
||||
public final class List {
|
||||
}
|
||||
""".trimIndent())
|
||||
val psiFile = myFixture.configureByFile(getTestName(false) + ".java")
|
||||
myFixture.checkHighlighting()
|
||||
})
|
||||
}
|
||||
|
||||
fun testImplicitWithPackagesPackagesOverModule() {
|
||||
IdeaTestUtil.withLevel(module, JavaFeature.PACKAGE_IMPORTS_SHADOW_MODULE_IMPORTS.minimumLevel, Runnable {
|
||||
myFixture.addClass("""
|
||||
package a.b;
|
||||
|
||||
public final class List {
|
||||
}
|
||||
""".trimIndent())
|
||||
val psiFile = myFixture.configureByFile(getTestName(false) + ".java")
|
||||
myFixture.checkHighlighting()
|
||||
val element = psiFile.findElementAt(myFixture.caretOffset)
|
||||
assertEquals("a.b.List", element?.parentOfType<PsiField>()?.type.resolve()?.qualifiedName)
|
||||
})
|
||||
}
|
||||
|
||||
|
||||
fun testImplicitWithSingleImport() {
|
||||
IdeaTestUtil.withLevel(module, JavaFeature.PACKAGE_IMPORTS_SHADOW_MODULE_IMPORTS.minimumLevel, Runnable {
|
||||
myFixture.addClass("""
|
||||
package a.b;
|
||||
|
||||
public final class List {
|
||||
}
|
||||
""".trimIndent())
|
||||
val psiFile = myFixture.configureByFile(getTestName(false) + ".java")
|
||||
myFixture.checkHighlighting()
|
||||
val element = psiFile.findElementAt(myFixture.caretOffset)
|
||||
assertEquals("a.b.List", element?.parentOfType<PsiField>()?.type.resolve()?.qualifiedName)
|
||||
})
|
||||
}
|
||||
|
||||
fun testImplicitWithSamePackage() {
|
||||
IdeaTestUtil.withLevel(module, JavaFeature.PACKAGE_IMPORTS_SHADOW_MODULE_IMPORTS.minimumLevel, Runnable {
|
||||
myFixture.addClass("""
|
||||
public final class List {
|
||||
}
|
||||
""".trimIndent())
|
||||
val psiFile = myFixture.configureByFile(getTestName(false) + ".java")
|
||||
myFixture.checkHighlighting()
|
||||
val element = psiFile.findElementAt(myFixture.caretOffset)
|
||||
assertEquals("List", element?.parentOfType<PsiField>()?.type.resolve()?.qualifiedName)
|
||||
})
|
||||
}
|
||||
|
||||
private fun doTest() {
|
||||
myFixture.configureByFile(getTestName(false) + ".java")
|
||||
myFixture.checkHighlighting()
|
||||
|
||||
@@ -9,9 +9,11 @@ import com.intellij.openapi.module.ModuleManager;
|
||||
import com.intellij.openapi.roots.DependencyScope;
|
||||
import com.intellij.openapi.roots.ModuleRootModificationUtil;
|
||||
import com.intellij.openapi.vfs.VfsUtil;
|
||||
import com.intellij.pom.java.JavaFeature;
|
||||
import com.intellij.psi.*;
|
||||
import com.intellij.psi.util.PsiTreeUtil;
|
||||
import com.intellij.psi.util.PsiUtil;
|
||||
import com.intellij.testFramework.IdeaTestUtil;
|
||||
import org.intellij.lang.annotations.Language;
|
||||
import org.jetbrains.annotations.NotNull;
|
||||
import org.jetbrains.annotations.Nullable;
|
||||
@@ -298,6 +300,86 @@ public class ResolveModuleImportTest extends LightJava9ModulesCodeInsightFixture
|
||||
assertEquals("my.source.moduleC.SourceTestC", psiClass.getQualifiedName());
|
||||
}
|
||||
|
||||
public void testAmbiguousModuleImport() {
|
||||
IdeaTestUtil.withLevel(getModule(), JavaFeature.PACKAGE_IMPORTS_SHADOW_MODULE_IMPORTS.getMinimumLevel(), ()->{
|
||||
prepareAmbiguousModuleTests();
|
||||
myFixture.configureByFile(getTestName(false) + ".java");
|
||||
myFixture.checkHighlighting();
|
||||
});
|
||||
}
|
||||
|
||||
public void testModuleImportWithPackageImport() {
|
||||
IdeaTestUtil.withLevel(getModule(), JavaFeature.PACKAGE_IMPORTS_SHADOW_MODULE_IMPORTS.getMinimumLevel(), ()->{
|
||||
prepareAmbiguousModuleTests();
|
||||
myFixture.configureByFile(getTestName(false) + ".java");
|
||||
myFixture.checkHighlighting();
|
||||
PsiClass psiClass = getPsiClass();
|
||||
assertNotNull(psiClass);
|
||||
assertEquals("my.source.moduleA.Imported", psiClass.getQualifiedName());
|
||||
});
|
||||
}
|
||||
|
||||
public void testModuleImportWithDefaultPackageImport() {
|
||||
IdeaTestUtil.withLevel(getModule(), JavaFeature.PACKAGE_IMPORTS_SHADOW_MODULE_IMPORTS.getMinimumLevel(), ()->{
|
||||
addCode("module-info.java", """
|
||||
module my.source.moduleB {
|
||||
exports my.source.moduleB;
|
||||
}
|
||||
""", M2);
|
||||
addCode("my/source/moduleB/String.java", """
|
||||
package my.source.moduleB;
|
||||
public class String {}
|
||||
""", M2);
|
||||
myFixture.configureByFile(getTestName(false) + ".java");
|
||||
myFixture.checkHighlighting();
|
||||
PsiClass psiClass = getPsiClass();
|
||||
assertNotNull(psiClass);
|
||||
assertEquals("java.lang.String", psiClass.getQualifiedName());
|
||||
});
|
||||
}
|
||||
|
||||
public void testAmbiguousModuleImportWithPackageImport() {
|
||||
IdeaTestUtil.withLevel(getModule(), JavaFeature.MODULE_IMPORT_DECLARATIONS.getMinimumLevel(), ()->{
|
||||
prepareAmbiguousModuleTests();
|
||||
myFixture.configureByFile(getTestName(false) + ".java");
|
||||
myFixture.checkHighlighting();
|
||||
});
|
||||
}
|
||||
|
||||
public void testModuleImportWithSingleImport() {
|
||||
IdeaTestUtil.withLevel(getModule(), JavaFeature.PACKAGE_IMPORTS_SHADOW_MODULE_IMPORTS.getMinimumLevel(), ()->{
|
||||
prepareAmbiguousModuleTests();
|
||||
myFixture.configureByFile(getTestName(false) + ".java");
|
||||
myFixture.checkHighlighting();
|
||||
PsiClass psiClass = getPsiClass();
|
||||
assertNotNull(psiClass);
|
||||
assertEquals("my.source.moduleA.Imported", psiClass.getQualifiedName());
|
||||
});
|
||||
}
|
||||
|
||||
private void prepareAmbiguousModuleTests() {
|
||||
addCode("module-info.java", """
|
||||
module my.source.moduleB {
|
||||
exports my.source.moduleB;
|
||||
}
|
||||
""", M2);
|
||||
addCode("my/source/moduleB/Imported.java", """
|
||||
package my.source.moduleB;
|
||||
public class Imported {}
|
||||
""", M2);
|
||||
addCode("module-info.java", """
|
||||
module my.source.moduleA {
|
||||
exports my.source.moduleA;
|
||||
}
|
||||
""", M4);
|
||||
addCode("my/source/moduleA/Imported.java", """
|
||||
package my.source.moduleA;
|
||||
public class Imported {}
|
||||
""", M4);
|
||||
addCode("Test.java", """
|
||||
""");
|
||||
}
|
||||
|
||||
@Nullable
|
||||
private PsiClass getPsiClass() {
|
||||
PsiField field = PsiTreeUtil.getParentOfType(myFixture.getFile().findElementAt(myFixture.getCaretOffset()), PsiField.class);
|
||||
|
||||
Reference in New Issue
Block a user