[java-intentions] Create record from deconstruction pattern, if the identifier is unresolved: fixes after IJ-CR-96419

IDEA-303300

GitOrigin-RevId: 683cfefb998c2a1f3a16d7874c166740ff21ac2f
This commit is contained in:
Andrey Cherkasov
2022-10-25 17:01:19 +04:00
committed by intellij-monorepo-bot
parent 3d2c425834
commit 970dd8d1e7
8 changed files with 48 additions and 77 deletions

View File

@@ -1,18 +1,4 @@
/*
* Copyright 2000-2013 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.
*/
// Copyright 2000-2022 JetBrains s.r.o. and contributors. Use of this source code is governed by the Apache 2.0 license.
package com.intellij.codeInsight.daemon.impl.quickfix;
import com.intellij.codeInsight.ExpectedTypeInfo;
@@ -153,7 +139,7 @@ public abstract class CreateClassFromUsageBaseFix extends BaseIntentionAction {
return false;
}
final String refName = element.getReferenceName();
if (refName == null ||
if (refName == null ||
PsiTreeUtil.getParentOfType(element, PsiTypeElement.class, PsiReferenceList.class) == null && !checkClassName(refName)) return false;
PsiElement nameElement = element.getReferenceNameElement();
if (nameElement == null) return false;
@@ -215,7 +201,7 @@ public abstract class CreateClassFromUsageBaseFix extends BaseIntentionAction {
if (aClass != null) return aClass.getQualifiedName();
}
}
} else if (ggParent instanceof PsiExpressionList && parent instanceof PsiExpression &&
} else if (ggParent instanceof PsiExpressionList && parent instanceof PsiExpression &&
(myKind == CreateClassKind.ENUM || myKind == CreateClassKind.RECORD)) {
final ExpectedTypeInfo[] expectedTypes = ExpectedTypesProvider.getExpectedTypes((PsiExpression)parent, false);
if (expectedTypes.length == 1) {
@@ -230,4 +216,12 @@ public abstract class CreateClassFromUsageBaseFix extends BaseIntentionAction {
return superClassName;
}
protected static @Nullable PsiDeconstructionPattern getDeconstructionPattern(@NotNull PsiJavaCodeReferenceElement reference) {
if (reference.getParent() instanceof PsiTypeElement typeElement &&
typeElement.getParent() instanceof PsiDeconstructionPattern pattern) {
return pattern;
}
return null;
}
}

View File

@@ -1,4 +1,4 @@
// Copyright 2000-2020 JetBrains s.r.o. Use of this source code is governed by the Apache 2.0 license that can be found in the LICENSE file.
// Copyright 2000-2022 JetBrains s.r.o. and contributors. Use of this source code is governed by the Apache 2.0 license.
package com.intellij.codeInsight.daemon.impl.quickfix;
import com.intellij.codeInsight.FileModificationService;
@@ -37,7 +37,8 @@ public class CreateClassFromUsageFix extends CreateClassFromUsageBaseFix {
CreateFromUsageUtils.setupSuperClassReference(aClass, superClassName);
}
CreateFromUsageBaseFix.setupGenericParameters(aClass, element);
if (element.getParent() instanceof PsiTypeElement typeElement && typeElement.getParent() instanceof PsiDeconstructionPattern pattern) {
PsiDeconstructionPattern pattern = getDeconstructionPattern(element);
if (pattern != null) {
CreateInnerClassFromUsageFix.setupRecordFromDeconstructionPattern(aClass, pattern, getText());
}
CodeStyleManager.getInstance(project).reformat(aClass);
@@ -72,8 +73,8 @@ public class CreateClassFromUsageFix extends CreateClassFromUsageBaseFix {
IdeDocumentHistory.getInstance(project).includeCurrentPlaceAsChangePlace();
if (element.getParent() instanceof PsiTypeElement typeElement &&
typeElement.getParent() instanceof PsiDeconstructionPattern pattern) {
PsiDeconstructionPattern pattern = getDeconstructionPattern(element);
if (pattern != null) {
CreateInnerClassFromUsageFix.setupRecordFromDeconstructionPattern(aClass, pattern, getText());
}
else {

View File

@@ -1,18 +1,4 @@
/*
* Copyright 2000-2016 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.
*/
// Copyright 2000-2022 JetBrains s.r.o. and contributors. Use of this source code is governed by the Apache 2.0 license.
package com.intellij.codeInsight.daemon.impl.quickfix;
import com.intellij.codeInsight.CodeInsightUtil;
@@ -165,8 +151,8 @@ public class CreateInnerClassFromUsageFix extends CreateClassFromUsageBaseFix {
if (!aClass.isPhysical()) {
PsiClass add = (PsiClass)aClass.add(created);
if (ref.getParent() instanceof PsiTypeElement typeElement &&
typeElement.getParent() instanceof PsiDeconstructionPattern pattern) {
PsiDeconstructionPattern pattern = getDeconstructionPattern(ref);
if (pattern != null) {
setupRecordFromDeconstructionPattern(add, pattern, getText());
}
}
@@ -176,8 +162,8 @@ public class CreateInnerClassFromUsageFix extends CreateClassFromUsageBaseFix {
() -> {
PsiClass add = (PsiClass)aClass.add(created);
ref.bindToElement(add);
if (ref.getParent() instanceof PsiTypeElement typeElement &&
typeElement.getParent() instanceof PsiDeconstructionPattern pattern) {
PsiDeconstructionPattern pattern = getDeconstructionPattern(ref);
if (pattern != null) {
setupRecordFromDeconstructionPattern(add, pattern, getText());
}
},
@@ -217,7 +203,7 @@ public class CreateInnerClassFromUsageFix extends CreateClassFromUsageBaseFix {
private static @NotNull TemplateBuilderImpl createRecordHeaderTemplate(PsiClass aClass, PsiDeconstructionList list) {
TemplateBuilderImpl templateBuilder = new TemplateBuilderImpl(aClass);
PsiRecordHeader header = aClass.getRecordHeader();
CreateRecordFromNewFix.setupRecordComponents(header, templateBuilder, list, PsiSubstitutor.EMPTY);
CreateRecordFromNewFix.setupRecordComponentsFromPattern(header, templateBuilder, list);
return templateBuilder;
}
}

View File

@@ -1,4 +1,4 @@
// Copyright 2000-2019 JetBrains s.r.o. Use of this source code is governed by the Apache 2.0 license that can be found in the LICENSE file.
// Copyright 2000-2022 JetBrains s.r.o. and contributors. Use of this source code is governed by the Apache 2.0 license.
package com.intellij.codeInsight.daemon.impl.quickfix;
import com.intellij.codeInsight.ExpectedTypeInfo;
@@ -16,8 +16,8 @@ import com.intellij.psi.codeStyle.VariableKind;
import com.intellij.psi.search.GlobalSearchScope;
import com.intellij.psi.util.JavaPsiPatternUtil;
import com.intellij.psi.util.PsiTreeUtil;
import com.intellij.psi.util.TypeConversionUtil;
import com.intellij.util.CommonJavaRefactoringUtil;
import com.intellij.util.IncorrectOperationException;
import org.jetbrains.annotations.NonNls;
import org.jetbrains.annotations.NotNull;
import org.jetbrains.annotations.Nullable;
@@ -47,23 +47,23 @@ public class CreateRecordFromNewFix extends CreateClassFromNewFix {
return templateBuilder;
}
/**
* @param header header to set up record components
* @param builder builder to use
* @param list <ul>
* <li>{@code PsiExpressionList} if the record is created from a new expression</li>
* <li>{@code PsiDeconstructionList} if the record is created from a record pattern</li>
* </ul>
* @param substitutor substitutor to use
* @throws IncorrectOperationException if setting up of record components fails
*/
static void setupRecordComponents(@Nullable PsiRecordHeader header, @NotNull TemplateBuilder builder,
@NotNull PsiElement list, @NotNull PsiSubstitutor substitutor)
throws IncorrectOperationException {
if (header == null || !(list instanceof PsiExpressionList || list instanceof PsiDeconstructionList)) return;
PsiCaseLabelElement[] elements = list instanceof PsiExpressionList argumentList
? argumentList.getExpressions()
: ((PsiDeconstructionList)list).getDeconstructionComponents();
@NotNull PsiExpressionList list, @NotNull PsiSubstitutor substitutor) {
if (header == null) return;
setupRecordComponents(header, builder, substitutor, list.getExpressions());
}
static void setupRecordComponentsFromPattern(@Nullable PsiRecordHeader header,
@NotNull TemplateBuilder builder,
@NotNull PsiDeconstructionList list) {
if (header == null) return;
setupRecordComponents(header, builder, PsiSubstitutor.EMPTY, list.getDeconstructionComponents());
}
private static void setupRecordComponents(@NotNull PsiRecordHeader header,
@NotNull TemplateBuilder builder,
@NotNull PsiSubstitutor substitutor,
@NotNull PsiCaseLabelElement @NotNull [] elements) {
final PsiManager psiManager = header.getManager();
final Project project = psiManager.getProject();
@@ -111,9 +111,11 @@ public class CreateRecordFromNewFix extends CreateClassFromNewFix {
PsiRecordComponent component = recordComponents[i];
ComponentData data = components.get(i);
ExpectedTypeInfo info = ExpectedTypesProvider.createInfo(data.myType, ExpectedTypeInfo.TYPE_OR_SUPERTYPE, data.myType, TailType.NONE);
int kind =
TypeConversionUtil.isPrimitiveAndNotNull(data.myType) ? ExpectedTypeInfo.TYPE_STRICTLY : ExpectedTypeInfo.TYPE_OR_SUPERTYPE;
ExpectedTypeInfo info = ExpectedTypesProvider.createInfo(data.myType, kind, data.myType, TailType.NONE);
PsiElement context = PsiTreeUtil.getParentOfType(list, PsiClass.class, PsiMethod.class);
PsiElement context = PsiTreeUtil.getParentOfType(elements[i], PsiClass.class, PsiMethod.class);
guesser.setupTypeElement(Objects.requireNonNull(component.getTypeElement()), new ExpectedTypeInfo[]{info}, context, containingClass);
Expression expression = new CreateFromUsageUtils.ParameterNameExpression(data.myNames);

View File

@@ -1,10 +1,7 @@
// "Create record 'Point'" "true-preview"
class Test {
void foo(Object obj) {
switch (obj) {
case Point(double x, double y) -> {}
default -> {}
}
if (obj instanceof Point(double x, double y)) {}
}
}

View File

@@ -1,9 +1,6 @@
// "Create record 'Point'" "true-preview"
class Test {
void foo(Object obj) {
switch (obj) {
case Poi<caret>nt(double x, double y) -> {}
default -> {}
}
if (obj instanceof Poi<caret>nt(double x, double y)) {}
}
}

View File

@@ -1,10 +1,7 @@
// "Create inner record 'Point'" "true-preview"
class Test {
void foo(Object obj) {
switch (obj) {
case Point(double x, double y) -> {}
default -> {}
}
if (obj instanceof Point(double x, double y)) {}
}
private record Point(double x, double y) {

View File

@@ -1,9 +1,6 @@
// "Create inner record 'Point'" "true-preview"
class Test {
void foo(Object obj) {
switch (obj) {
case Poi<caret>nt(double x, double y) -> {}
default -> {}
}
if (obj instanceof Poi<caret>nt(double x, double y)) {}
}
}