mirror of
https://gitflic.ru/project/openide/openide.git
synced 2026-09-27 10:03:11 +07:00
[java] module 'exports' package completion
This commit is contained in:
+2
-15
@@ -34,6 +34,7 @@ import com.intellij.openapi.util.TextRange;
|
||||
import com.intellij.openapi.vfs.VirtualFile;
|
||||
import com.intellij.psi.*;
|
||||
import com.intellij.psi.search.FilenameIndex;
|
||||
import com.intellij.psi.util.PsiUtil;
|
||||
import com.intellij.util.containers.ContainerUtil;
|
||||
import com.intellij.util.graph.Graph;
|
||||
import org.jetbrains.annotations.NotNull;
|
||||
@@ -161,7 +162,7 @@ public class ModuleHighlightUtil {
|
||||
String message = JavaErrorMessages.message("package.not.found", packageName);
|
||||
return HighlightInfo.newHighlightInfo(HighlightInfoType.ERROR).range(refElement).description(message).create();
|
||||
}
|
||||
if (isEmpty(directories, packageName)) {
|
||||
if (PsiUtil.isPackageEmpty(directories, packageName)) {
|
||||
String message = JavaErrorMessages.message("package.is.empty", packageName);
|
||||
return HighlightInfo.newHighlightInfo(HighlightInfoType.ERROR).range(refElement).description(message).create();
|
||||
}
|
||||
@@ -227,18 +228,4 @@ public class ModuleHighlightUtil {
|
||||
private static TextRange range(PsiJavaModule module) {
|
||||
return new TextRange(module.getTextOffset(), module.getNameElement().getTextRange().getEndOffset());
|
||||
}
|
||||
|
||||
private static boolean isEmpty(PsiDirectory[] directories, String packageName) {
|
||||
for (PsiDirectory directory : directories) {
|
||||
for (PsiFile file : directory.getFiles()) {
|
||||
if (file instanceof PsiClassOwner &&
|
||||
packageName.equals(((PsiClassOwner)file).getPackageName()) &&
|
||||
((PsiClassOwner)file).getClasses().length > 0) {
|
||||
return false;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
return true;
|
||||
}
|
||||
}
|
||||
@@ -19,8 +19,13 @@ import com.intellij.codeInsight.TailType;
|
||||
import com.intellij.codeInsight.completion.JavaKeywordCompletion.OverrideableSpace;
|
||||
import com.intellij.codeInsight.lookup.LookupElement;
|
||||
import com.intellij.codeInsight.lookup.LookupElementBuilder;
|
||||
import com.intellij.openapi.components.ServiceManager;
|
||||
import com.intellij.openapi.module.Module;
|
||||
import com.intellij.openapi.module.ModuleUtilCore;
|
||||
import com.intellij.openapi.module.impl.scopes.ModulesScope;
|
||||
import com.intellij.openapi.project.Project;
|
||||
import com.intellij.psi.*;
|
||||
import com.intellij.psi.impl.file.impl.JavaFileManager;
|
||||
import com.intellij.psi.impl.java.stubs.index.JavaModuleNameIndex;
|
||||
import com.intellij.psi.search.GlobalSearchScope;
|
||||
import com.intellij.psi.search.ProjectScope;
|
||||
@@ -48,7 +53,10 @@ class JavaModuleCompletion {
|
||||
addModuleStatementKeywords(position, result);
|
||||
}
|
||||
else if (context instanceof PsiJavaModuleReferenceElement) {
|
||||
addModuleReferences(position, result);
|
||||
addModuleReferences(context, result);
|
||||
}
|
||||
else if (context instanceof PsiJavaCodeReferenceElement) {
|
||||
addCodeReferences(context, result);
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -66,11 +74,11 @@ class JavaModuleCompletion {
|
||||
result.consume(new OverrideableSpace(createKeyword(position, PsiKeyword.PROVIDES), TailType.HUMBLE_SPACE_BEFORE_WORD));
|
||||
}
|
||||
|
||||
private static void addModuleReferences(PsiElement position, Consumer<LookupElement> result) {
|
||||
PsiJavaModule host = PsiTreeUtil.getParentOfType(position, PsiJavaModule.class);
|
||||
private static void addModuleReferences(PsiElement context, Consumer<LookupElement> result) {
|
||||
PsiJavaModule host = PsiTreeUtil.getParentOfType(context, PsiJavaModule.class);
|
||||
if (host != null) {
|
||||
String hostName = host.getModuleName();
|
||||
Project project = position.getProject();
|
||||
Project project = context.getProject();
|
||||
JavaModuleNameIndex index = JavaModuleNameIndex.getInstance();
|
||||
GlobalSearchScope scope = ProjectScope.getAllScope(project);
|
||||
index.processAllKeys(project, name -> {
|
||||
@@ -81,4 +89,25 @@ class JavaModuleCompletion {
|
||||
});
|
||||
}
|
||||
}
|
||||
|
||||
private static void addCodeReferences(PsiElement context, Consumer<LookupElement> result) {
|
||||
PsiElement statement = PsiTreeUtil.skipParentsOfType(context, PsiJavaCodeReferenceElement.class);
|
||||
if (statement instanceof PsiExportsStatement) {
|
||||
Module module = ModuleUtilCore.findModuleForPsiElement(context);
|
||||
PsiPackage topPackage = ServiceManager.getService(context.getProject(), JavaFileManager.class).findPackage("");
|
||||
if (module != null && topPackage != null) {
|
||||
processPackage(topPackage, new ModulesScope(module), result);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
private static void processPackage(PsiPackage pkg, ModulesScope scope, Consumer<LookupElement> result) {
|
||||
String packageName = pkg.getQualifiedName();
|
||||
if (packageName.indexOf('.') > 0 && !PsiUtil.isPackageEmpty(pkg.getDirectories(scope), packageName)) {
|
||||
result.consume(new OverrideableSpace(LookupElementBuilder.create(packageName), TailType.SEMICOLON));
|
||||
}
|
||||
for (PsiPackage subPackage : pkg.getSubPackages(scope)) {
|
||||
processPackage(subPackage, scope, result);
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -1277,4 +1277,18 @@ public final class PsiUtil extends PsiUtilCore {
|
||||
public static boolean isModuleFile(@NotNull PsiFile file) {
|
||||
return file instanceof PsiJavaFile && ((PsiJavaFile)file).getModuleDeclaration() != null;
|
||||
}
|
||||
|
||||
public static boolean isPackageEmpty(@NotNull PsiDirectory[] directories, @NotNull String packageName) {
|
||||
for (PsiDirectory directory : directories) {
|
||||
for (PsiFile file : directory.getFiles()) {
|
||||
if (file instanceof PsiClassOwner &&
|
||||
packageName.equals(((PsiClassOwner)file).getPackageName()) &&
|
||||
((PsiClassOwner)file).getClasses().length > 0) {
|
||||
return false;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
return true;
|
||||
}
|
||||
}
|
||||
@@ -15,8 +15,10 @@
|
||||
*/
|
||||
package com.intellij.codeInsight.completion
|
||||
|
||||
import com.intellij.testFramework.LightPlatformTestCase
|
||||
import com.intellij.testFramework.LightProjectDescriptor
|
||||
import com.intellij.testFramework.MultiModuleJava9ProjectDescriptor
|
||||
import com.intellij.testFramework.VfsTestUtil
|
||||
import org.assertj.core.api.Assertions.assertThat
|
||||
|
||||
class ModuleCompletionTest : LightFixtureCompletionTestCase() {
|
||||
@@ -27,7 +29,16 @@ class ModuleCompletionTest : LightFixtureCompletionTestCase() {
|
||||
fun testStatements2() = complete("module M { requires X; ex<caret> }", "module M { requires X; exports <caret> }")
|
||||
fun testModuleRef() = complete("module M { requires M<caret> }", "module M { requires M2;<caret> }")
|
||||
|
||||
fun testExports() {
|
||||
addFile("pkg/empty/package-info.java", "package pkg.empty;")
|
||||
addFile("pkg/main/C.java", "package pkg.main;\nclass C { }")
|
||||
addFile("pkg/other/C.groovy", "package pkg.other\nclass C { }")
|
||||
variants("module M { exports pkg.<caret> }", "pkg.main", "pkg.other")
|
||||
}
|
||||
|
||||
//<editor-fold desc="Helpers.">
|
||||
private fun addFile(path: String, text: String) = VfsTestUtil.createFile(LightPlatformTestCase.getSourceRoot(), path, text)
|
||||
|
||||
private fun complete(text: String, expected: String) {
|
||||
myFixture.configureByText("module-info.java", text)
|
||||
myFixture.completeBasic()
|
||||
|
||||
Reference in New Issue
Block a user