mirror of
https://gitflic.ru/project/openide/openide.git
synced 2026-04-19 04:51:24 +07:00
[java-intentions] IDEA-313226. Suggest the correct type for switch. Generics and tests
GitOrigin-RevId: 4814c85fd7721fb7866210825a0d2286c61e2043
This commit is contained in:
committed by
intellij-monorepo-bot
parent
ce216843a0
commit
016ba5fb84
@@ -619,20 +619,33 @@ public final class ExpectedTypesProvider {
|
||||
}
|
||||
}
|
||||
result.addAll(processedExpressionTypes(labeledExpressionTypes, mustBeReference, statement));
|
||||
result.addAll(processedPatternTypes(labeledPatternsTypes));
|
||||
result.addAll(processedPatternTypes(labeledPatternsTypes, statement));
|
||||
return result;
|
||||
}
|
||||
|
||||
|
||||
private static List<ExpectedTypeInfo> processedPatternTypes(@NotNull List<PsiType> expectedTypes) {
|
||||
LinkedHashSet<PsiClass> processedTypes = new LinkedHashSet<>();
|
||||
|
||||
private static List<ExpectedTypeInfo> processedPatternTypes(@NotNull List<PsiType> expectedTypes, @NotNull PsiSwitchBlock statement) {
|
||||
LinkedHashSet<PsiType> processedTypes = new LinkedHashSet<>();
|
||||
for (PsiType type : expectedTypes) {
|
||||
PsiClass currentClass = PsiUtil.resolveClassInClassTypeOnly(type);
|
||||
if (currentClass == null) {
|
||||
continue;
|
||||
}
|
||||
LinkedHashSet<PsiClass> allSuperClasses = InheritanceUtil.getSuperClasses(currentClass);
|
||||
if (!(type instanceof PsiClassType classType)) {
|
||||
continue;
|
||||
}
|
||||
PsiSubstitutor substitutor = classType.resolveGenerics().getSubstitutor();
|
||||
LinkedHashSet<PsiType> allSuperClasses = new LinkedHashSet<>();
|
||||
InheritanceUtil.processSuperTypes(classType, true, nextType -> {
|
||||
PsiClass superClass = PsiUtil.resolveClassInClassTypeOnly(nextType);
|
||||
if (superClass != null) {
|
||||
PsiSubstitutor superClassSubstitutor = TypeConversionUtil.getSuperClassSubstitutor(superClass, currentClass, substitutor);
|
||||
PsiType substituted = superClassSubstitutor.substitute(nextType);
|
||||
allSuperClasses.add(substituted);
|
||||
}
|
||||
|
||||
return true;
|
||||
});
|
||||
if (processedTypes.isEmpty()) {
|
||||
processedTypes = allSuperClasses;
|
||||
}
|
||||
@@ -642,9 +655,13 @@ public final class ExpectedTypesProvider {
|
||||
}
|
||||
|
||||
List<ExpectedTypeInfo> result = new ArrayList<>();
|
||||
for (PsiClass psiClass : processedTypes) {
|
||||
PsiClassType type = PsiTypesUtil.getClassType(psiClass);
|
||||
result.add(createInfo(type, ExpectedTypeInfo.TYPE_STRICTLY, type, TailType.NONE));
|
||||
for (PsiType parent : processedTypes) {
|
||||
result.add(createInfo(parent, ExpectedTypeInfo.TYPE_STRICTLY, parent, TailType.NONE));
|
||||
}
|
||||
//return Object if it is impossible to find common types
|
||||
if (result.isEmpty() && !expectedTypes.isEmpty()) {
|
||||
PsiClassType objectType = TypeUtils.getObjectType(statement);
|
||||
result.add(createInfo(objectType, ExpectedTypeInfo.TYPE_STRICTLY, objectType, TailType.NONE));
|
||||
}
|
||||
return result;
|
||||
}
|
||||
|
||||
@@ -0,0 +1,22 @@
|
||||
class Test {
|
||||
|
||||
String testSwitch() {
|
||||
BaseInterface k = new BaseInterface.Record1();
|
||||
int i2 = 0;
|
||||
return switch (k<caret>)
|
||||
{
|
||||
case BaseInterface.Record1 record1 -> "1";
|
||||
case BaseInterface.Record2 record2 -> "2";
|
||||
default -> "3";
|
||||
};
|
||||
}
|
||||
|
||||
sealed interface BaseInterface permits BaseInterface.Record1, BaseInterface.Record2{
|
||||
|
||||
record Record1() implements BaseInterface {
|
||||
}
|
||||
|
||||
record Record2() implements BaseInterface {
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,22 @@
|
||||
class Test {
|
||||
|
||||
String testSwitch() {
|
||||
BaseInterface k = new BaseInterface.Record1();
|
||||
int i2 = 0;
|
||||
return switch (<caret>)
|
||||
{
|
||||
case BaseInterface.Record1 record1 -> "1";
|
||||
case BaseInterface.Record2 record2 -> "2";
|
||||
default -> "3";
|
||||
};
|
||||
}
|
||||
|
||||
sealed interface BaseInterface permits BaseInterface.Record1, BaseInterface.Record2{
|
||||
|
||||
record Record1() implements BaseInterface {
|
||||
}
|
||||
|
||||
record Record2() implements BaseInterface {
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,21 @@
|
||||
class Test {
|
||||
|
||||
String testSwitch() {
|
||||
BaseInterface<String> i = null;
|
||||
BaseInterface<Character> j = null;
|
||||
return switch (i<caret>) {
|
||||
case BaseInterface.Record1<String> record1 -> "1";
|
||||
case BaseInterface.Record2 record2 -> "2";
|
||||
default -> "3";
|
||||
};
|
||||
}
|
||||
|
||||
sealed interface BaseInterface<T> permits BaseInterface.Record1, BaseInterface.Record2 {
|
||||
|
||||
record Record1<T>() implements BaseInterface<T> {
|
||||
}
|
||||
|
||||
record Record2() implements BaseInterface<String> {
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,21 @@
|
||||
class Test {
|
||||
|
||||
String testSwitch() {
|
||||
BaseInterface<String> i = null;
|
||||
BaseInterface<Character> j = null;
|
||||
return switch (<caret>) {
|
||||
case BaseInterface.Record1<String> record1 -> "1";
|
||||
case BaseInterface.Record2 record2 -> "2";
|
||||
default -> "3";
|
||||
};
|
||||
}
|
||||
|
||||
sealed interface BaseInterface<T> permits BaseInterface.Record1, BaseInterface.Record2 {
|
||||
|
||||
record Record1<T>() implements BaseInterface<T> {
|
||||
}
|
||||
|
||||
record Record2() implements BaseInterface<String> {
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,22 @@
|
||||
// "Create local variable 'i'" "true-preview"
|
||||
|
||||
class A {
|
||||
String testPattern() {
|
||||
BaseInterface<String> i;
|
||||
return switch (i)
|
||||
{
|
||||
case BaseInterface.Record1<String> record1 -> "1";
|
||||
case BaseInterface.Record2 record2 -> "2";
|
||||
default -> "3";
|
||||
};
|
||||
}
|
||||
}
|
||||
|
||||
sealed interface BaseInterface<T> permits BaseInterface.Record1, BaseInterface.Record2{
|
||||
|
||||
record Record1<T>() implements BaseInterface<T> {
|
||||
}
|
||||
|
||||
record Record2() implements BaseInterface<String> {
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,21 @@
|
||||
// "Create local variable 'i'" "true-preview"
|
||||
|
||||
class A {
|
||||
String testPattern() {
|
||||
return switch (i<caret>)
|
||||
{
|
||||
case BaseInterface.Record1<String> record1 -> "1";
|
||||
case BaseInterface.Record2 record2 -> "2";
|
||||
default -> "3";
|
||||
};
|
||||
}
|
||||
}
|
||||
|
||||
sealed interface BaseInterface<T> permits BaseInterface.Record1, BaseInterface.Record2{
|
||||
|
||||
record Record1<T>() implements BaseInterface<T> {
|
||||
}
|
||||
|
||||
record Record2() implements BaseInterface<String> {
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,56 @@
|
||||
/*
|
||||
* Copyright 2000-2017 JetBrains s.r.o.
|
||||
*
|
||||
* Licensed under the Apache License, Version 2.0 (the "License");
|
||||
* you may not use this file except in compliance with the License.
|
||||
* You may obtain a copy of the License at
|
||||
*
|
||||
* http://www.apache.org/licenses/LICENSE-2.0
|
||||
*
|
||||
* Unless required by applicable law or agreed to in writing, software
|
||||
* distributed under the License is distributed on an "AS IS" BASIS,
|
||||
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
* See the License for the specific language governing permissions and
|
||||
* limitations under the License.
|
||||
*/
|
||||
package com.intellij.java.codeInsight.completion;
|
||||
|
||||
import com.intellij.JavaTestUtil;
|
||||
import com.intellij.codeInsight.completion.CompletionType;
|
||||
import com.intellij.codeInsight.completion.LightFixtureCompletionTestCase;
|
||||
import com.intellij.codeInsight.lookup.Lookup;
|
||||
import com.intellij.testFramework.LightProjectDescriptor;
|
||||
import org.jetbrains.annotations.NotNull;
|
||||
|
||||
public class SmartType20CompletionTest extends LightFixtureCompletionTestCase {
|
||||
|
||||
@NotNull
|
||||
@Override
|
||||
protected LightProjectDescriptor getProjectDescriptor() {
|
||||
return JAVA_20;
|
||||
}
|
||||
|
||||
@Override
|
||||
protected String getBasePath() {
|
||||
return JavaTestUtil.getRelativeJavaTestDataPath() + "/codeInsight/completion/smartType/";
|
||||
}
|
||||
|
||||
@Override
|
||||
protected void complete() {
|
||||
myItems = myFixture.complete(CompletionType.SMART);
|
||||
}
|
||||
|
||||
public void testSwitchPattern() { doTest(); }
|
||||
public void testSwitchPatternGeneric() { doTest(); }
|
||||
|
||||
private void doTest() {
|
||||
configureByFile("/" + getTestName(false) + ".java");
|
||||
if (myItems != null) {
|
||||
final Lookup lookup = getLookup();
|
||||
if (lookup != null) {
|
||||
selectItem(lookup.getCurrentItem(), Lookup.NORMAL_SELECT_CHAR);
|
||||
}
|
||||
}
|
||||
checkResultByFile("/" + getTestName(false) + "-out.java");
|
||||
}
|
||||
}
|
||||
Reference in New Issue
Block a user