mirror of
https://gitflic.ru/project/openide/openide.git
synced 2026-09-27 10:03:11 +07:00
[java-completion] IDEA-247109 Complete top-level pubic class name based on the file name
GitOrigin-RevId: 867955fe94a6137a21ccd7a46d4a6bf615e75924
This commit is contained in:
committed by
intellij-monorepo-bot
parent
44b38beea9
commit
81fba80b5e
@@ -7,8 +7,12 @@ import com.intellij.codeInsight.TailTypes;
|
||||
import com.intellij.codeInsight.completion.util.CompletionStyleUtil;
|
||||
import com.intellij.codeInsight.completion.util.ParenthesesInsertHandler;
|
||||
import com.intellij.codeInsight.daemon.impl.analysis.HighlightingFeature;
|
||||
import com.intellij.codeInsight.daemon.impl.quickfix.CreateClassKind;
|
||||
import com.intellij.codeInsight.lookup.*;
|
||||
import com.intellij.ide.highlighter.JavaFileType;
|
||||
import com.intellij.openapi.editor.Document;
|
||||
import com.intellij.openapi.util.Conditions;
|
||||
import com.intellij.openapi.util.text.StringUtil;
|
||||
import com.intellij.patterns.ElementPattern;
|
||||
import com.intellij.patterns.PsiElementPattern;
|
||||
import com.intellij.pom.java.LanguageLevel;
|
||||
@@ -17,6 +21,7 @@ import com.intellij.psi.codeStyle.CodeStyleManager;
|
||||
import com.intellij.psi.filters.FilterPositionUtil;
|
||||
import com.intellij.psi.javadoc.PsiDocComment;
|
||||
import com.intellij.psi.templateLanguages.OuterLanguageElement;
|
||||
import com.intellij.psi.tree.IElementType;
|
||||
import com.intellij.psi.util.InheritanceUtil;
|
||||
import com.intellij.psi.util.PsiTreeUtil;
|
||||
import com.intellij.psi.util.PsiUtil;
|
||||
@@ -24,9 +29,11 @@ import com.intellij.util.Consumer;
|
||||
import com.intellij.util.ObjectUtils;
|
||||
import com.intellij.util.containers.ContainerUtil;
|
||||
import org.jetbrains.annotations.NotNull;
|
||||
import org.jetbrains.annotations.Nullable;
|
||||
|
||||
import java.util.ArrayList;
|
||||
import java.util.List;
|
||||
import java.util.Locale;
|
||||
import java.util.Set;
|
||||
|
||||
import static com.intellij.openapi.util.Conditions.notInstanceOf;
|
||||
@@ -557,13 +564,22 @@ public class JavaKeywordCompletion {
|
||||
}
|
||||
if (PsiTreeUtil.getParentOfType(myPosition, PsiExpression.class, true, PsiMember.class) == null &&
|
||||
PsiTreeUtil.getParentOfType(myPosition, PsiCodeBlock.class, true, PsiMember.class) == null) {
|
||||
addKeyword(new OverridableSpace(createKeyword(PsiKeyword.CLASS), TailType.HUMBLE_SPACE_BEFORE_WORD));
|
||||
addKeyword(new OverridableSpace(createKeyword(PsiKeyword.INTERFACE), TailType.HUMBLE_SPACE_BEFORE_WORD));
|
||||
List<String> keywords = new ArrayList<>();
|
||||
keywords.add(PsiKeyword.CLASS);
|
||||
keywords.add(PsiKeyword.INTERFACE);
|
||||
if (HighlightingFeature.RECORDS.isAvailable(myPosition)) {
|
||||
addKeyword(new OverridableSpace(createKeyword(PsiKeyword.RECORD), TailType.HUMBLE_SPACE_BEFORE_WORD));
|
||||
keywords.add(PsiKeyword.RECORD);
|
||||
}
|
||||
if (PsiUtil.isLanguageLevel5OrHigher(myPosition)) {
|
||||
addKeyword(new OverridableSpace(createKeyword(PsiKeyword.ENUM), TailType.INSERT_SPACE));
|
||||
keywords.add(PsiKeyword.ENUM);
|
||||
}
|
||||
String className = recommendClassName();
|
||||
for (String keyword : keywords) {
|
||||
if (className == null) {
|
||||
addKeyword(new OverridableSpace(createKeyword(keyword), TailType.HUMBLE_SPACE_BEFORE_WORD));
|
||||
} else {
|
||||
addKeyword(createTypeDeclaration(keyword, className));
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -574,6 +590,57 @@ public class JavaKeywordCompletion {
|
||||
}
|
||||
}
|
||||
|
||||
@NotNull
|
||||
private LookupElement createTypeDeclaration(String keyword, String className) {
|
||||
LookupElement element;
|
||||
PsiElement nextElement = PsiTreeUtil.skipWhitespacesAndCommentsForward(PsiTreeUtil.nextLeaf(myPosition));
|
||||
IElementType nextToken = nextElement instanceof PsiJavaToken ? ((PsiJavaToken)nextElement).getTokenType() : null;
|
||||
element = LookupElementBuilder.create(keyword + " " + className).withPresentableText(keyword).bold()
|
||||
.withTailText(" " + className, false)
|
||||
.withIcon(CreateClassKind.valueOf(keyword.toUpperCase(Locale.ROOT)).getKindIcon())
|
||||
.withInsertHandler((context, item) -> {
|
||||
Document document = context.getDocument();
|
||||
int offset = context.getTailOffset();
|
||||
String suffix = " ";
|
||||
if (keyword.equals(PsiKeyword.RECORD)) {
|
||||
if (JavaTokenType.LPARENTH.equals(nextToken)) {
|
||||
suffix = "";
|
||||
}
|
||||
else if (JavaTokenType.LBRACE.equals(nextToken)) {
|
||||
suffix = "() ";
|
||||
}
|
||||
else {
|
||||
suffix = "() {\n}";
|
||||
}
|
||||
}
|
||||
else if (!JavaTokenType.LBRACE.equals(nextToken)) {
|
||||
suffix = " {\n}";
|
||||
}
|
||||
if (offset < document.getTextLength() && document.getCharsSequence().charAt(offset) == ' ') {
|
||||
suffix = suffix.trim();
|
||||
}
|
||||
document.insertString(offset, suffix);
|
||||
context.getEditor().getCaretModel().moveToOffset(offset + 1);
|
||||
});
|
||||
return element;
|
||||
}
|
||||
|
||||
@Nullable
|
||||
private String recommendClassName() {
|
||||
if (myPrevLeaf == null) return null;
|
||||
if (!myPrevLeaf.textMatches(PsiKeyword.PUBLIC) || !(myPrevLeaf.getParent() instanceof PsiModifierList)) return null;
|
||||
if (PsiTreeUtil.skipWhitespacesAndCommentsForward(PsiTreeUtil.nextLeaf(myPosition)) instanceof PsiIdentifier) return null;
|
||||
PsiJavaFile file = ObjectUtils.tryCast(myPrevLeaf.getParent().getParent(), PsiJavaFile.class);
|
||||
if (file == null) return null;
|
||||
String name = file.getName();
|
||||
if (!StringUtil.endsWithIgnoreCase(name, JavaFileType.DOT_DEFAULT_EXTENSION)) return null;
|
||||
String candidate = name.substring(0, name.length() - JavaFileType.DOT_DEFAULT_EXTENSION.length());
|
||||
if (StringUtil.isJavaIdentifier(candidate) && !ContainerUtil.exists(file.getClasses(), c -> candidate.equals(c.getName()))) {
|
||||
return candidate;
|
||||
}
|
||||
return null;
|
||||
}
|
||||
|
||||
private void addClassLiteral() {
|
||||
if (isAfterTypeDot(myPosition)) {
|
||||
addKeyword(createKeyword(PsiKeyword.CLASS));
|
||||
|
||||
@@ -1 +1 @@
|
||||
public <caret>
|
||||
public <caret> Cls
|
||||
|
||||
+1
-1
@@ -2,7 +2,7 @@ class A extends Base{
|
||||
void foo(){
|
||||
B x = null;
|
||||
switch(x){
|
||||
case GOO:<caret>
|
||||
case GOO -> <caret>
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@@ -0,0 +1 @@
|
||||
public cl<caret>
|
||||
+1
@@ -0,0 +1 @@
|
||||
public cl<caret> {}
|
||||
+1
@@ -0,0 +1 @@
|
||||
public class TopLevelPublicClassBraceExists <caret>{}
|
||||
+1
@@ -0,0 +1 @@
|
||||
public cl<caret> MyClass
|
||||
+1
@@ -0,0 +1 @@
|
||||
public class<caret> MyClass
|
||||
@@ -0,0 +1,2 @@
|
||||
public class TopLevelPublicClass <caret>{
|
||||
}
|
||||
@@ -0,0 +1 @@
|
||||
public re<caret>
|
||||
+1
@@ -0,0 +1 @@
|
||||
public re<caret> {}
|
||||
+1
@@ -0,0 +1 @@
|
||||
public record TopLevelPublicRecordBraceExists(<caret>) {}
|
||||
+2
@@ -0,0 +1,2 @@
|
||||
public re<caret>() {
|
||||
}
|
||||
+2
@@ -0,0 +1,2 @@
|
||||
public record TopLevelPublicRecordParenthesisExists(<caret>) {
|
||||
}
|
||||
@@ -0,0 +1,2 @@
|
||||
public record TopLevelPublicRecord(<caret>) {
|
||||
}
|
||||
+10
-2
@@ -32,7 +32,7 @@ class NormalCompletionTest extends NormalCompletionTestCase {
|
||||
@NotNull
|
||||
@Override
|
||||
protected LightProjectDescriptor getProjectDescriptor() {
|
||||
return JAVA_9
|
||||
return JAVA_15
|
||||
}
|
||||
|
||||
void testSimple() throws Exception {
|
||||
@@ -954,7 +954,7 @@ public class ListUtils {
|
||||
@NeedsIndex.ForStandardLibrary
|
||||
void testFinalInForLoop2() throws Throwable {
|
||||
configure()
|
||||
myFixture.assertPreferredCompletionItems 0, 'finalize', 'final'
|
||||
myFixture.assertPreferredCompletionItems 1, 'finalize', 'final'
|
||||
}
|
||||
|
||||
void testOnlyClassesInExtends() throws Throwable {
|
||||
@@ -2161,4 +2161,12 @@ class Abc {
|
||||
selectItem(myItems[1])
|
||||
checkResult()
|
||||
}
|
||||
|
||||
void testTopLevelPublicClass() { doTest() }
|
||||
void testTopLevelPublicClassIdentifierExists() { doTest() }
|
||||
void testTopLevelPublicClassBraceExists() { doTest() }
|
||||
|
||||
void testTopLevelPublicRecord() { doTest() }
|
||||
void testTopLevelPublicRecordParenthesisExists() { doTest() }
|
||||
void testTopLevelPublicRecordBraceExists() { doTest() }
|
||||
}
|
||||
|
||||
Reference in New Issue
Block a user