IDEA-55146 Autocomplete case inside switch

This commit is contained in:
peter
2016-07-27 17:07:11 +02:00
parent f0c3ede074
commit 9179fa8fea
6 changed files with 75 additions and 18 deletions
@@ -462,6 +462,8 @@ public class JavaCompletionContributor extends CompletionContributor {
result.addElement(element);
}
});
JavaKeywordCompletion.addEnumCases(result, parameters.getPosition());
}
static boolean isClassNamePossible(CompletionParameters parameters) {
@@ -22,7 +22,6 @@ import com.intellij.codeInsight.completion.util.ParenthesesInsertHandler;
import com.intellij.codeInsight.daemon.impl.analysis.LambdaHighlightingUtil;
import com.intellij.codeInsight.lookup.*;
import com.intellij.openapi.util.AtomicNotNullLazyValue;
import com.intellij.openapi.util.Condition;
import com.intellij.openapi.util.NotNullLazyValue;
import com.intellij.patterns.ElementPattern;
import com.intellij.pom.java.LanguageLevel;
@@ -42,6 +41,8 @@ import com.intellij.util.containers.ContainerUtil;
import org.jetbrains.annotations.NotNull;
import org.jetbrains.annotations.Nullable;
import java.util.Set;
import static com.intellij.openapi.util.Conditions.notInstanceOf;
import static com.intellij.patterns.PsiJavaPatterns.*;
import static com.intellij.patterns.StandardPatterns.not;
@@ -295,12 +296,34 @@ public class JavaKeywordCompletion {
}
private static void addCaseDefault(Consumer<LookupElement> result, PsiElement position) {
if (PsiTreeUtil.getParentOfType(position, PsiSwitchStatement.class, false, PsiMember.class) != null) {
if (getSwitchFromLabelPosition(position) != null) {
result.consume(new OverrideableSpace(createKeyword(position, PsiKeyword.CASE), TailType.INSERT_SPACE));
result.consume(new OverrideableSpace(createKeyword(position, PsiKeyword.DEFAULT), TailType.CASE_COLON));
}
}
private static PsiSwitchStatement getSwitchFromLabelPosition(PsiElement position) {
return PsiTreeUtil.getParentOfType(position, PsiSwitchStatement.class, false, PsiMember.class, PsiSwitchLabelStatement.class);
}
static void addEnumCases(CompletionResultSet result, PsiElement position) {
PsiSwitchStatement switchStatement = getSwitchFromLabelPosition(position);
PsiExpression expression = switchStatement == null ? null : switchStatement.getExpression();
PsiClass switchType = expression == null ? null : PsiUtil.resolveClassInClassTypeOnly(expression.getType());
if (switchType == null || !switchType.isEnum()) return;
Set<PsiField> used = ReferenceExpressionCompletionContributor.findConstantsUsedInSwitch(switchStatement);
for (PsiField field : switchType.getAllFields()) {
String name = field.getName();
if (!(field instanceof PsiEnumConstant) || used.contains(field) || name == null) {
continue;
}
String prefix = "case ";
String suffix = name + ":";
result.addElement(LookupElementBuilder.create(field, prefix + suffix).bold().withPresentableText(prefix).withTailText(suffix).withLookupString(name));
}
}
private static void addFinal(Consumer<LookupElement> result, PsiElement position, @Nullable PsiElement prevLeaf) {
PsiStatement statement = PsiTreeUtil.getParentOfType(position, PsiExpressionStatement.class);
if (statement == null) {
@@ -28,6 +28,7 @@ import com.intellij.psi.infos.CandidateInfo;
import com.intellij.psi.util.PsiTreeUtil;
import com.intellij.util.Consumer;
import com.intellij.util.IncorrectOperationException;
import com.intellij.util.ObjectUtils;
import com.intellij.util.containers.ContainerUtil;
import org.jetbrains.annotations.NotNull;
import org.jetbrains.annotations.Nullable;
@@ -178,26 +179,29 @@ public class ReferenceExpressionCompletionContributor {
@NotNull
public static Set<PsiField> findConstantsUsedInSwitch(@Nullable PsiElement position) {
if (IN_SWITCH_LABEL.accepts(position)) {
Set<PsiField> used = ContainerUtil.newLinkedHashSet();
PsiSwitchStatement sw = PsiTreeUtil.getParentOfType(position, PsiSwitchStatement.class);
assert sw != null;
final PsiCodeBlock body = sw.getBody();
assert body != null;
for (PsiStatement statement : body.getStatements()) {
if (statement instanceof PsiSwitchLabelStatement) {
final PsiExpression value = ((PsiSwitchLabelStatement)statement).getCaseValue();
if (value instanceof PsiReferenceExpression) {
final PsiElement target = ((PsiReferenceExpression)value).resolve();
if (target instanceof PsiField) {
used.add(CompletionUtil.getOriginalOrSelf((PsiField)target));
}
return IN_SWITCH_LABEL.accepts(position)
? findConstantsUsedInSwitch(ObjectUtils.assertNotNull(PsiTreeUtil.getParentOfType(position, PsiSwitchStatement.class)))
: Collections.emptySet();
}
@NotNull
public static Set<PsiField> findConstantsUsedInSwitch(@NotNull PsiSwitchStatement sw) {
final PsiCodeBlock body = sw.getBody();
if (body == null) return Collections.emptySet();
Set<PsiField> used = ContainerUtil.newLinkedHashSet();
for (PsiStatement statement : body.getStatements()) {
if (statement instanceof PsiSwitchLabelStatement) {
final PsiExpression value = ((PsiSwitchLabelStatement)statement).getCaseValue();
if (value instanceof PsiReferenceExpression) {
final PsiElement target = ((PsiReferenceExpression)value).resolve();
if (target instanceof PsiField) {
used.add(CompletionUtil.getOriginalOrSelf((PsiField)target));
}
}
}
return used;
}
return Collections.emptySet();
return used;
}
static PsiExpression createExpression(String text, PsiElement element) {
@@ -0,0 +1,13 @@
class A extends Base{
void foo(){
B x = null;
switch(x){
GOO<caret>
}
}
}
enum B{
FOO, BAR, GOO
}
@@ -0,0 +1,13 @@
class A extends Base{
void foo(){
B x = null;
switch(x){
case GOO:<caret>
}
}
}
enum B{
FOO, BAR, GOO
}
@@ -290,6 +290,8 @@ public class NormalCompletionTest extends LightFixtureCompletionTestCase {
assertEquals(3, myItems.length);
}
public void testSwitchCaseWithEnumConstant() { doTest() }
public void testMethodInAnnotation() throws Exception {
configureByFile("Annotation.java");
checkResultByFile("Annotation_after.java");