mirror of
https://gitflic.ru/project/openide/openide.git
synced 2026-05-06 05:10:22 +07:00
[java-intentions] IDEA-299075 Better quick-fixes when generic method call has mismatched type
GitOrigin-RevId: 6fa73efcfb43cd7da05f95ef66c2cd40a3dc1a14
This commit is contained in:
committed by
intellij-monorepo-bot
parent
46c6cb94ad
commit
8a9959167b
@@ -616,4 +616,5 @@ inspection.redundant.requires.statement.message.module.unused=No usages of modul
|
||||
inspection.redundant.requires.statement.message.java.base.implicitly.required='java.base' is implicitly required.
|
||||
reassign.variable.display.name=Reassigned variable
|
||||
intention.family.name.remove.repeating.call=Remove repeating call
|
||||
intention.name.remove.repeating.call=Remove repeating call ''{0}()''
|
||||
intention.name.remove.repeating.call=Remove repeating call ''{0}()''
|
||||
intention.family.name.replace.with.expression=Replace with expression
|
||||
@@ -0,0 +1,199 @@
|
||||
// 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.analysis;
|
||||
|
||||
import com.intellij.codeInsight.daemon.impl.HighlightInfo;
|
||||
import com.intellij.codeInsight.daemon.impl.quickfix.QuickFixAction;
|
||||
import com.intellij.codeInsight.daemon.impl.quickfix.ReplaceExpressionAction;
|
||||
import com.intellij.codeInsight.daemon.impl.quickfix.WrapExpressionFix;
|
||||
import com.intellij.codeInsight.intention.QuickFixFactory;
|
||||
import com.intellij.psi.*;
|
||||
import com.intellij.psi.infos.MethodCandidateInfo;
|
||||
import com.intellij.psi.util.PsiTreeUtil;
|
||||
import com.intellij.psi.util.PsiTypesUtil;
|
||||
import com.intellij.psi.util.PsiUtil;
|
||||
import com.intellij.psi.util.TypeConversionUtil;
|
||||
import com.intellij.util.ArrayUtil;
|
||||
import com.intellij.util.containers.ContainerUtil;
|
||||
import com.siyeh.ig.psiutils.MethodCallUtils;
|
||||
import one.util.streamex.MoreCollectors;
|
||||
import one.util.streamex.StreamEx;
|
||||
import org.jetbrains.annotations.NotNull;
|
||||
import org.jetbrains.annotations.Nullable;
|
||||
|
||||
import java.util.Map;
|
||||
import java.util.Set;
|
||||
|
||||
import static com.intellij.util.ObjectUtils.tryCast;
|
||||
|
||||
/**
|
||||
* Utilities to register fixes for mismatching type
|
||||
*/
|
||||
class AdaptExpressionTypeFixUtil {
|
||||
private static final QuickFixFactory QUICK_FIX_FACTORY = QuickFixFactory.getInstance();
|
||||
private AdaptExpressionTypeFixUtil() {}
|
||||
|
||||
static void registerPatchParametersFixes(@NotNull HighlightInfo info,
|
||||
@NotNull PsiMethodCallExpression call,
|
||||
@NotNull PsiMethod method,
|
||||
@NotNull PsiType expectedTypeByParent) {
|
||||
JavaResolveResult result = call.resolveMethodGenerics();
|
||||
if (!(result instanceof MethodCandidateInfo)) return;
|
||||
PsiType methodType = method.getReturnType();
|
||||
PsiType actualType = ((MethodCandidateInfo)result).getSubstitutor(false).substitute(methodType);
|
||||
Map.Entry<PsiTypeParameter, PsiType> substitution = findDesiredSubstitution(expectedTypeByParent, actualType, methodType);
|
||||
if (substitution == null) return;
|
||||
PsiTypeParameter typeParameter = substitution.getKey();
|
||||
if (!PsiTreeUtil.isAncestor(method, typeParameter, true)) return;
|
||||
PsiType expectedTypeValue = substitution.getValue();
|
||||
|
||||
PsiParameter[] parameters = method.getParameterList().getParameters();
|
||||
Set<PsiTypeParameter> set = Set.of(typeParameter);
|
||||
PsiParameter parameter =
|
||||
StreamEx.of(parameters).collect(MoreCollectors.onlyOne(p -> PsiTypesUtil.mentionsTypeParameters(p.getType(), set))).orElse(null);
|
||||
if (parameter == null) return;
|
||||
PsiExpression arg = PsiUtil.skipParenthesizedExprDown(MethodCallUtils.getArgumentForParameter(call, parameter));
|
||||
if (arg == null) return;
|
||||
PsiClassType parameterType = tryCast(parameter.getType(), PsiClassType.class);
|
||||
if (parameterType == null) return;
|
||||
if (parameterType.rawType().equalsToText(CommonClassNames.JAVA_LANG_CLASS) && typeParameter == getSoleTypeParameter(parameterType)) {
|
||||
if (expectedTypeValue instanceof PsiClassType && JavaGenericsUtil.isReifiableType(expectedTypeValue)) {
|
||||
ReplaceExpressionAction fix = new ReplaceExpressionAction(
|
||||
arg, ((PsiClassType)expectedTypeValue).rawType().getCanonicalText() + ".class",
|
||||
((PsiClassType)expectedTypeValue).rawType().getPresentableText() + ".class");
|
||||
QuickFixAction.registerQuickFixAction(info, fix);
|
||||
}
|
||||
}
|
||||
PsiType expectedArgType = PsiSubstitutor.EMPTY.put(typeParameter, expectedTypeValue).substitute(parameterType);
|
||||
if (arg instanceof PsiLambdaExpression) {
|
||||
registerLambdaReturnFixes(info, (PsiLambdaExpression)arg, parameterType, expectedArgType, typeParameter);
|
||||
return;
|
||||
}
|
||||
registerExpectedTypeFixes(info, arg, expectedArgType);
|
||||
}
|
||||
|
||||
private static void registerLambdaReturnFixes(@NotNull HighlightInfo info,
|
||||
@NotNull PsiLambdaExpression arg,
|
||||
@NotNull PsiClassType parameterType,
|
||||
@Nullable PsiType expectedArgType,
|
||||
@NotNull PsiTypeParameter typeParameter) {
|
||||
if (!(expectedArgType instanceof PsiClassType)) return;
|
||||
PsiExpression lambdaBody = LambdaUtil.extractSingleExpressionFromBody(arg.getBody());
|
||||
if (lambdaBody == null) return;
|
||||
PsiClass fnInterface = parameterType.resolve();
|
||||
if (fnInterface == null) return;
|
||||
PsiType[] fnArgs = parameterType.getParameters();
|
||||
PsiTypeParameter[] fnParams = fnInterface.getTypeParameters();
|
||||
if (fnArgs.length != fnParams.length) return;
|
||||
PsiType fnTypeArgumentToChange = StreamEx.of(fnArgs)
|
||||
.collect(MoreCollectors.onlyOne(c -> PsiTypesUtil.mentionsTypeParameters(c, Set.of(typeParameter)))).orElse(null);
|
||||
if (fnTypeArgumentToChange == null) return;
|
||||
int index = ArrayUtil.indexOf(fnArgs, fnTypeArgumentToChange);
|
||||
if (index == -1) return;
|
||||
PsiTypeParameter fnParam = fnParams[index];
|
||||
PsiMethod sam = LambdaUtil.getFunctionalInterfaceMethod(fnInterface);
|
||||
if (sam == null) return;
|
||||
Set<PsiTypeParameter> fnParamSet = Set.of(fnParam);
|
||||
PsiType returnType = sam.getReturnType();
|
||||
if (!PsiTypesUtil.mentionsTypeParameters(returnType, fnParamSet) ||
|
||||
ContainerUtil.exists(sam.getParameterList().getParameters(), p -> PsiTypesUtil.mentionsTypeParameters(p.getType(), fnParamSet))) {
|
||||
return;
|
||||
}
|
||||
PsiType expectedFnReturnType = LambdaUtil.getFunctionalInterfaceReturnType(expectedArgType);
|
||||
if (expectedFnReturnType == null) return;
|
||||
registerExpectedTypeFixes(info, lambdaBody, expectedFnReturnType);
|
||||
}
|
||||
|
||||
static void registerExpectedTypeFixes(@NotNull HighlightInfo info, @NotNull PsiExpression arg, @Nullable PsiType expectedType) {
|
||||
if (expectedType == null) return;
|
||||
expectedType = GenericsUtil.getVariableTypeByExpressionType(expectedType);
|
||||
QuickFixAction.registerQuickFixAction(info, QUICK_FIX_FACTORY.createWrapWithAdapterFix(expectedType, arg));
|
||||
QuickFixAction.registerQuickFixAction(info, QUICK_FIX_FACTORY.createWrapWithOptionalFix(expectedType, arg));
|
||||
QuickFixAction.registerQuickFixAction(info, QUICK_FIX_FACTORY.createWrapExpressionFix(expectedType, arg));
|
||||
PsiType argType = arg.getType();
|
||||
if (arg instanceof PsiMethodCallExpression) {
|
||||
JavaResolveResult result = ((PsiMethodCallExpression)arg).resolveMethodGenerics();
|
||||
if (result instanceof MethodCandidateInfo) {
|
||||
argType = ((MethodCandidateInfo)result).getSubstitutor(false).substitute(argType);
|
||||
}
|
||||
}
|
||||
PsiType castToType = suggestCastTo(expectedType, argType);
|
||||
if (castToType != null) {
|
||||
QuickFixAction.registerQuickFixAction(info, QUICK_FIX_FACTORY.createAddTypeCastFix(castToType, arg));
|
||||
}
|
||||
if (arg instanceof PsiMethodCallExpression) {
|
||||
PsiMethod argMethod = ((PsiMethodCallExpression)arg).resolveMethod();
|
||||
if (argMethod != null) {
|
||||
registerPatchParametersFixes(info, (PsiMethodCallExpression)arg, argMethod, expectedType);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
private static @Nullable Map.Entry<PsiTypeParameter, PsiType> findDesiredSubstitution(@Nullable PsiType expected,
|
||||
@Nullable PsiType actual,
|
||||
@Nullable PsiType methodType) {
|
||||
if (expected == null || actual == null || methodType == null) return null;
|
||||
if (expected instanceof PsiArrayType && actual instanceof PsiArrayType && methodType instanceof PsiArrayType) {
|
||||
return findDesiredSubstitution(((PsiArrayType)expected).getComponentType(),
|
||||
((PsiArrayType)actual).getComponentType(),
|
||||
((PsiArrayType)methodType).getComponentType());
|
||||
}
|
||||
if (expected instanceof PsiWildcardType && ((PsiWildcardType)expected).isExtends()) {
|
||||
expected = ((PsiWildcardType)expected).getExtendsBound();
|
||||
}
|
||||
if (!(methodType instanceof PsiClassType) || !(expected instanceof PsiClassType) || !(actual instanceof PsiClassType)) return null;
|
||||
PsiClass methodClass = ((PsiClassType)methodType).resolve();
|
||||
PsiClass expectedClass = ((PsiClassType)expected).resolve();
|
||||
PsiClass actualClass = ((PsiClassType)actual).resolve();
|
||||
if (methodClass == null || expectedClass == null || actualClass == null) return null;
|
||||
if (methodClass instanceof PsiTypeParameter) {
|
||||
if (!expected.equals(actual)) {
|
||||
return Map.entry((PsiTypeParameter)methodClass, expected);
|
||||
}
|
||||
return null;
|
||||
}
|
||||
if (!expectedClass.isEquivalentTo(actualClass) || !expectedClass.isEquivalentTo(methodClass)) return null;
|
||||
PsiType[] methodTypeParameters = ((PsiClassType)methodType).getParameters();
|
||||
PsiType[] expectedTypeParameters = ((PsiClassType)expected).getParameters();
|
||||
PsiType[] actualTypeParameters = ((PsiClassType)actual).getParameters();
|
||||
if (methodTypeParameters.length != expectedTypeParameters.length || methodTypeParameters.length != actualTypeParameters.length) {
|
||||
return null;
|
||||
}
|
||||
Map.Entry<PsiTypeParameter, PsiType> existing = null;
|
||||
for (int i = 0; i < methodTypeParameters.length; i++) {
|
||||
Map.Entry<PsiTypeParameter, PsiType> substitution =
|
||||
findDesiredSubstitution(expectedTypeParameters[i], actualTypeParameters[i], methodTypeParameters[i]);
|
||||
if (existing == null) {
|
||||
existing = substitution;
|
||||
}
|
||||
else if (!existing.equals(substitution)) {
|
||||
return null;
|
||||
}
|
||||
}
|
||||
return existing;
|
||||
}
|
||||
|
||||
private static @Nullable PsiTypeParameter getSoleTypeParameter(@Nullable PsiType type) {
|
||||
if (!(type instanceof PsiClassType)) return null;
|
||||
PsiType[] parameters = ((PsiClassType)type).getParameters();
|
||||
if (parameters.length != 1) return null;
|
||||
PsiType parameter = parameters[0];
|
||||
if (parameter instanceof PsiWildcardType) {
|
||||
parameter = ((PsiWildcardType)parameter).getExtendsBound();
|
||||
}
|
||||
if (!(parameter instanceof PsiClassType)) return null;
|
||||
return tryCast(((PsiClassType)parameter).resolve(), PsiTypeParameter.class);
|
||||
}
|
||||
|
||||
static @Nullable PsiType suggestCastTo(@Nullable PsiType expectedTypeByParent, @Nullable PsiType actualType) {
|
||||
if (expectedTypeByParent == null || actualType == null) return null;
|
||||
if (TypeConversionUtil.isAssignable(expectedTypeByParent, actualType)) return null;
|
||||
if (TypeConversionUtil.areTypesConvertible(actualType, expectedTypeByParent)) return expectedTypeByParent;
|
||||
if (actualType instanceof PsiPrimitiveType) {
|
||||
PsiPrimitiveType unboxedType = PsiPrimitiveType.getUnboxedType(expectedTypeByParent);
|
||||
if (unboxedType != null && TypeConversionUtil.areTypesConvertible(actualType, unboxedType)) {
|
||||
return unboxedType;
|
||||
}
|
||||
}
|
||||
return null;
|
||||
}
|
||||
}
|
||||
@@ -325,13 +325,7 @@ public final class HighlightFixUtil {
|
||||
static void registerLambdaReturnTypeFixes(HighlightInfo info, PsiLambdaExpression lambda, PsiExpression expression) {
|
||||
PsiType type = LambdaUtil.getFunctionalInterfaceReturnType(lambda);
|
||||
if (type != null) {
|
||||
PsiType exprType = expression.getType();
|
||||
if (exprType != null && TypeConversionUtil.areTypesConvertible(exprType, type)) {
|
||||
QuickFixAction.registerQuickFixAction(info, QUICK_FIX_FACTORY.createAddTypeCastFix(type, expression));
|
||||
}
|
||||
QuickFixAction.registerQuickFixAction(info, QUICK_FIX_FACTORY.createWrapWithOptionalFix(type, expression));
|
||||
QuickFixAction.registerQuickFixAction(info, QUICK_FIX_FACTORY.createWrapExpressionFix(type, expression));
|
||||
QuickFixAction.registerQuickFixAction(info, QUICK_FIX_FACTORY.createWrapWithAdapterFix(type, expression));
|
||||
AdaptExpressionTypeFixUtil.registerExpectedTypeFixes(info, expression, type);
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
@@ -582,8 +582,7 @@ public final class HighlightMethodUtil {
|
||||
highlightInfo = HighlightUtil.createIncompatibleTypeHighlightInfo(
|
||||
expectedTypeByParent, actualType, fixRange, 0, XmlStringUtil.escapeString(errorMessage));
|
||||
if (methodCall instanceof PsiMethodCallExpression) {
|
||||
QuickFixAction.registerQuickFixAction(highlightInfo,
|
||||
QUICK_FIX_FACTORY.createWrapWithAdapterFix(expectedTypeByParent, (PsiExpression)methodCall));
|
||||
AdaptExpressionTypeFixUtil.registerExpectedTypeFixes(highlightInfo, (PsiMethodCallExpression)methodCall, expectedTypeByParent);
|
||||
}
|
||||
}
|
||||
else {
|
||||
@@ -946,16 +945,6 @@ public final class HighlightMethodUtil {
|
||||
QualifySuperArgumentFix.registerQuickFixAction((PsiSuperExpression)qualifierExpression, highlightInfo);
|
||||
}
|
||||
|
||||
PsiType expectedTypeByParent = PsiTypesUtil.getExpectedTypeByParent(methodCall);
|
||||
if (expectedTypeByParent != null) {
|
||||
PsiType methodCallType = methodCall.getType();
|
||||
if (methodCallType != null &&
|
||||
TypeConversionUtil.areTypesConvertible(methodCallType, expectedTypeByParent) &&
|
||||
!TypeConversionUtil.isAssignable(expectedTypeByParent, methodCallType)) {
|
||||
QuickFixAction.registerQuickFixAction(highlightInfo, fixRange, QUICK_FIX_FACTORY.createAddTypeCastFix(expectedTypeByParent, methodCall));
|
||||
}
|
||||
}
|
||||
|
||||
CandidateInfo[] methodCandidates = resolveHelper.getReferencedMethodCandidates(methodCall, false);
|
||||
QuickFixAction.registerQuickFixAction(highlightInfo, fixRange, QUICK_FIX_FACTORY.createSurroundWithArrayFix(methodCall, null));
|
||||
|
||||
|
||||
@@ -568,9 +568,7 @@ public final class HighlightUtil {
|
||||
QuickFixAction.registerQuickFixAction(highlightInfo, getFixFactory().createAddTypeCastFix(lType, expression));
|
||||
}
|
||||
if (expression != null) {
|
||||
QuickFixAction.registerQuickFixAction(highlightInfo, getFixFactory().createWrapWithOptionalFix(lType, expression));
|
||||
QuickFixAction.registerQuickFixAction(highlightInfo, getFixFactory().createWrapExpressionFix(lType, expression));
|
||||
QuickFixAction.registerQuickFixAction(highlightInfo, getFixFactory().createWrapWithAdapterFix(lType, expression));
|
||||
AdaptExpressionTypeFixUtil.registerExpectedTypeFixes(highlightInfo, expression, lType);
|
||||
HighlightFixUtil.registerCollectionToArrayFixAction(highlightInfo, rType, lType, expression);
|
||||
if (!(expression.getParent() instanceof PsiConditionalExpression && PsiType.VOID.equals(lType))) {
|
||||
HighlightFixUtil.registerChangeReturnTypeFix(highlightInfo, expression, lType);
|
||||
|
||||
@@ -0,0 +1,46 @@
|
||||
// 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.codeInspection.CommonQuickFixBundle;
|
||||
import com.intellij.codeInspection.LocalQuickFixAndIntentionActionOnPsiElement;
|
||||
import com.intellij.java.analysis.JavaAnalysisBundle;
|
||||
import com.intellij.openapi.editor.Editor;
|
||||
import com.intellij.openapi.project.Project;
|
||||
import com.intellij.psi.PsiElement;
|
||||
import com.intellij.psi.PsiExpression;
|
||||
import com.intellij.psi.PsiFile;
|
||||
import com.siyeh.ig.psiutils.CommentTracker;
|
||||
import org.jetbrains.annotations.NotNull;
|
||||
import org.jetbrains.annotations.Nullable;
|
||||
|
||||
public class ReplaceExpressionAction extends LocalQuickFixAndIntentionActionOnPsiElement {
|
||||
private final String myReplacement;
|
||||
private final String myPresentation;
|
||||
private final String myOrigText;
|
||||
|
||||
public ReplaceExpressionAction(@NotNull PsiExpression expression, @NotNull String replacement, @NotNull String presentation) {
|
||||
super(expression);
|
||||
myOrigText = expression.getText();
|
||||
myReplacement = replacement;
|
||||
myPresentation = presentation;
|
||||
}
|
||||
|
||||
@Override
|
||||
public void invoke(@NotNull Project project,
|
||||
@NotNull PsiFile file,
|
||||
@Nullable Editor editor,
|
||||
@NotNull PsiElement startElement,
|
||||
@NotNull PsiElement endElement) {
|
||||
new CommentTracker().replaceAndRestoreComments(startElement, myReplacement);
|
||||
}
|
||||
|
||||
@Override
|
||||
public @NotNull String getText() {
|
||||
return CommonQuickFixBundle.message("fix.replace.x.with.y", myOrigText, myPresentation);
|
||||
}
|
||||
|
||||
@Override
|
||||
public @NotNull String getFamilyName() {
|
||||
return JavaAnalysisBundle.message("intention.family.name.replace.with.expression");
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,9 @@
|
||||
// "Cast to 'java.util.List<java.lang.String>'" "false"
|
||||
import java.util.*;
|
||||
|
||||
class a {
|
||||
void test() {
|
||||
List<String> list = Collections.<caret>singletonList(123);
|
||||
}
|
||||
}
|
||||
|
||||
@@ -0,0 +1,8 @@
|
||||
// "Replace 'Double.class' with 'Integer.class'" "true-preview"
|
||||
class Demo {
|
||||
native static <T> T tryCast(Object obj, Class<T> clazz);
|
||||
|
||||
void test(Object obj) {
|
||||
Integer i = tryCast(obj, Integer.class);
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,10 @@
|
||||
// "Replace 'Integer.class' with 'String.class'" "true-preview"
|
||||
import java.util.*;
|
||||
|
||||
class Demo {
|
||||
native static <T> List<T> filterIsInstance(Collection<?> collection, Class<? extends T> aClass);
|
||||
|
||||
void test(List<?> list) {
|
||||
List<String> strings = filterIsInstance(list, String.class);
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,10 @@
|
||||
// "Replace 'Integer.class' with 'String.class'" "true-preview"
|
||||
import java.util.*;
|
||||
|
||||
class Demo {
|
||||
native static <T> List<T> filterIsInstance(Collection<?> collection, Class<? extends T> aClass);
|
||||
|
||||
void test(List<?> list) {
|
||||
List<String> stringsSync = Collections.synchronizedList(filterIsInstance(list, String.class));
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,8 @@
|
||||
// "Cast to 'long'" "true-preview"
|
||||
import java.util.function.*;
|
||||
|
||||
class Demo {
|
||||
void test(Function<String, String> input) {
|
||||
Function<String, Long> result = input.andThen(s -> (long) s.length());
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,8 @@
|
||||
// "Wrap using 'String.valueOf()'" "true-preview"
|
||||
import java.util.*;
|
||||
|
||||
class Demo {
|
||||
void test() {
|
||||
List<String> stringList = Collections.nCopies(10, String.valueOf(20));
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,8 @@
|
||||
// "Wrap using 'String.valueOf()'" "true-preview"
|
||||
import java.util.*;
|
||||
|
||||
class Demo {
|
||||
void test() {
|
||||
List<Set<String>> nCopiesNested = Collections.nCopies(10, Set.of(String.valueOf(20)));
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,9 @@
|
||||
// "Adapt using 'new File()'" "true-preview"
|
||||
import java.util.*;
|
||||
import java.io.File;
|
||||
|
||||
class Demo {
|
||||
void test(int value) {
|
||||
Set<File> file = Set.of(new File("/etc/passwd"));
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,8 @@
|
||||
// "Cast to 'long'" "true-preview"
|
||||
import java.util.*;
|
||||
|
||||
class Demo {
|
||||
void test() {
|
||||
Optional<Long> opt = Optional.of(123L);
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,8 @@
|
||||
// "Wrap using 'String.valueOf()'" "true-preview"
|
||||
import java.util.*;
|
||||
|
||||
class Demo {
|
||||
void test(int value) {
|
||||
Optional<String> optStr = Optional.of(String.valueOf(value));
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,8 @@
|
||||
// "Wrap using 'String.valueOf()'" "true-preview"
|
||||
import java.util.stream.*;
|
||||
|
||||
class Demo {
|
||||
void test() {
|
||||
Stream<String> stream = Stream.generate(() -> String.valueOf(Math.random()));
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,8 @@
|
||||
// "Adapt using 'Math.toIntExact()'" "true-preview"
|
||||
import java.util.*;
|
||||
|
||||
class Demo {
|
||||
void test(List<?> list) {
|
||||
List<Integer> intList = Collections.singletonList(Math.toIntExact(123L));
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,8 @@
|
||||
// "Adapt using 'Math.toIntExact()'" "true-preview"
|
||||
import java.util.*;
|
||||
|
||||
class Demo {
|
||||
void test(List<?> list) {
|
||||
List<Integer> intList2 = Collections.unmodifiableList(Collections.singletonList(Math.toIntExact(123L)));
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,8 @@
|
||||
// "Replace 'Double.class' with 'Integer.class'" "true-preview"
|
||||
class Demo {
|
||||
native static <T> T tryCast(Object obj, Class<T> clazz);
|
||||
|
||||
void test(Object obj) {
|
||||
Integer i = <caret>tryCast(obj, Double.class);
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,10 @@
|
||||
// "Replace 'Integer.class' with 'String.class'" "true-preview"
|
||||
import java.util.*;
|
||||
|
||||
class Demo {
|
||||
native static <T> List<T> filterIsInstance(Collection<?> collection, Class<? extends T> aClass);
|
||||
|
||||
void test(List<?> list) {
|
||||
List<String> strings = <caret>filterIsInstance(list, Integer.class);
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,10 @@
|
||||
// "Replace 'Integer.class' with 'String.class'" "true-preview"
|
||||
import java.util.*;
|
||||
|
||||
class Demo {
|
||||
native static <T> List<T> filterIsInstance(Collection<?> collection, Class<? extends T> aClass);
|
||||
|
||||
void test(List<?> list) {
|
||||
List<String> stringsSync = <caret>Collections.synchronizedList(filterIsInstance(list, Integer.class));
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,8 @@
|
||||
// "Cast to 'long'" "true-preview"
|
||||
import java.util.function.*;
|
||||
|
||||
class Demo {
|
||||
void test(Function<String, String> input) {
|
||||
Function<String, Long> result = input.andThen(s -> <caret>s.length());
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,8 @@
|
||||
// "Wrap using 'String.valueOf()'" "true-preview"
|
||||
import java.util.*;
|
||||
|
||||
class Demo {
|
||||
void test() {
|
||||
List<String> stringList = Collections.<caret>nCopies(10, 20);
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,8 @@
|
||||
// "Wrap using 'String.valueOf()'" "true-preview"
|
||||
import java.util.*;
|
||||
|
||||
class Demo {
|
||||
void test() {
|
||||
List<Set<String>> nCopiesNested = Collections.<caret>nCopies(10, Set.of(20));
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,9 @@
|
||||
// "Adapt using 'new File()'" "true-preview"
|
||||
import java.util.*;
|
||||
import java.io.File;
|
||||
|
||||
class Demo {
|
||||
void test(int value) {
|
||||
Set<File> file = Set.of("/etc/<caret>passwd");
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,8 @@
|
||||
// "Cast to 'long'" "true-preview"
|
||||
import java.util.*;
|
||||
|
||||
class Demo {
|
||||
void test() {
|
||||
Optional<Long> opt = <caret>Optional.of(123);
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,8 @@
|
||||
// "Wrap using 'String.valueOf()'" "true-preview"
|
||||
import java.util.*;
|
||||
|
||||
class Demo {
|
||||
void test(int value) {
|
||||
Optional<String> optStr = <caret>Optional.of(value);
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,8 @@
|
||||
// "Wrap using 'String.valueOf()'" "true-preview"
|
||||
import java.util.stream.*;
|
||||
|
||||
class Demo {
|
||||
void test() {
|
||||
Stream<String> stream = Stream.generate(() -> <caret>Math.random());
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,8 @@
|
||||
// "Adapt using 'Math.toIntExact()'" "true-preview"
|
||||
import java.util.*;
|
||||
|
||||
class Demo {
|
||||
void test(List<?> list) {
|
||||
List<Integer> intList = <caret>Collections.singletonList(123L);
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,8 @@
|
||||
// "Adapt using 'Math.toIntExact()'" "true-preview"
|
||||
import java.util.*;
|
||||
|
||||
class Demo {
|
||||
void test(List<?> list) {
|
||||
List<Integer> intList2 = <caret>Collections.unmodifiableList(Collections.singletonList(123L));
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,34 @@
|
||||
/*
|
||||
* 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.daemon.quickFix;
|
||||
|
||||
import com.intellij.codeInsight.daemon.quickFix.LightQuickFixParameterizedTestCase;
|
||||
import com.intellij.testFramework.LightProjectDescriptor;
|
||||
import org.jetbrains.annotations.NotNull;
|
||||
|
||||
import static com.intellij.testFramework.fixtures.LightJavaCodeInsightFixtureTestCase.JAVA_11;
|
||||
|
||||
public class PatchMethodParametersTest extends LightQuickFixParameterizedTestCase {
|
||||
@Override
|
||||
protected String getBasePath() {
|
||||
return "/codeInsight/daemonCodeAnalyzer/quickFix/patchMethodParams";
|
||||
}
|
||||
|
||||
@Override
|
||||
protected @NotNull LightProjectDescriptor getProjectDescriptor() {
|
||||
return JAVA_11;
|
||||
}
|
||||
}
|
||||
@@ -499,6 +499,23 @@ public final class MethodCallUtils {
|
||||
return -1;
|
||||
}
|
||||
|
||||
/**
|
||||
* @param call method call
|
||||
* @param parameter parameter of called method
|
||||
* @return an expression in the call argument list that corresponds to a given parameter; null if there's no correspondence
|
||||
*/
|
||||
public static @Nullable PsiExpression getArgumentForParameter(@NotNull PsiCall call, @NotNull PsiParameter parameter) {
|
||||
PsiMethod scope = tryCast(parameter.getDeclarationScope(), PsiMethod.class);
|
||||
if (scope == null) return null;
|
||||
int index = scope.getParameterList().getParameterIndex(parameter);
|
||||
PsiExpressionList argList = call.getArgumentList();
|
||||
if (argList == null) return null;
|
||||
PsiExpression[] args = argList.getExpressions();
|
||||
if (index >= args.length) return null;
|
||||
if (parameter.isVarArgs() && !isVarArgCall(call)) return null;
|
||||
return args[index];
|
||||
}
|
||||
|
||||
private static class SuperCallVisitor extends JavaRecursiveElementWalkingVisitor {
|
||||
|
||||
private final PsiMethod myMethod;
|
||||
|
||||
Reference in New Issue
Block a user