From c1cf67610fa3cd7c432b90179f51db34b82f5f04 Mon Sep 17 00:00:00 2001 From: Dmitry Batkovich Date: Mon, 24 Jul 2017 15:37:04 +0300 Subject: [PATCH] guava type migration: support a case when migration chain is an argument of read-only method IDEA-176444 --- .../rules/guava/FluentIterableConversionUtil.java | 10 +++++----- .../guava/GuavaFluentIterableConversionRule.java | 10 +++++----- .../rules/guava/GuavaOptionalConversionRule.java | 6 +++--- .../rules/guava/GuavaTypeConversionDescriptor.java | 13 ++++++++++--- .../rules/guava/IterableStreamConversionRule.java | 4 ++-- .../inspections/GuavaInspectionTest.java | 4 ++++ .../convertFluentIterableAsIterableParameter2.java | 11 +++++++++++ ...ertFluentIterableAsIterableParameter2_after.java | 11 +++++++++++ 8 files changed, 51 insertions(+), 18 deletions(-) create mode 100644 java/typeMigration/testData/inspections/guava/convertFluentIterableAsIterableParameter2.java create mode 100644 java/typeMigration/testData/inspections/guava/convertFluentIterableAsIterableParameter2_after.java diff --git a/java/typeMigration/src/com/intellij/refactoring/typeMigration/rules/guava/FluentIterableConversionUtil.java b/java/typeMigration/src/com/intellij/refactoring/typeMigration/rules/guava/FluentIterableConversionUtil.java index 2cc9126a2bb5..6bf575166335 100644 --- a/java/typeMigration/src/com/intellij/refactoring/typeMigration/rules/guava/FluentIterableConversionUtil.java +++ b/java/typeMigration/src/com/intellij/refactoring/typeMigration/rules/guava/FluentIterableConversionUtil.java @@ -1,5 +1,5 @@ /* - * Copyright 2000-2015 JetBrains s.r.o. + * 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. @@ -140,7 +140,7 @@ public class FluentIterableConversionUtil { return new GuavaFilterInstanceOfConversionDescriptor(filterClassName); } else if (GuavaLambda.PREDICATE.getClassQName().equals(resolvedClass.getQualifiedName())) { - return new GuavaTypeConversionDescriptor("$it$.filter($p$)", "$it$." + StreamApiConstants.FILTER + "($p$)"); + return new GuavaTypeConversionDescriptor("$it$.filter($p$)", "$it$." + StreamApiConstants.FILTER + "($p$)", context); } return null; } @@ -157,8 +157,8 @@ public class FluentIterableConversionUtil { } static class TransformAndConcatConversionRule extends GuavaTypeConversionDescriptor { - public TransformAndConcatConversionRule() { - super("$q$.transformAndConcat($params$)", "$q$.flatMap($params$)"); + public TransformAndConcatConversionRule(PsiExpression context) { + super("$q$.transformAndConcat($params$)", "$q$.flatMap($params$)", context); } @Override @@ -272,7 +272,7 @@ public class FluentIterableConversionUtil { final String returnType; if ("toMap".equals(methodName) || "uniqueIndex".equals(methodName)) { final GuavaTypeConversionDescriptor descriptor = new GuavaTypeConversionDescriptor("$it$.$methodName$($f$)", - "$it$.collect(java.util.stream.Collectors.toMap(java.util.function.Function.identity(), $f$))"); + "$it$.collect(java.util.stream.Collectors.toMap(java.util.function.Function.identity(), $f$))", context); return descriptor.withConversionType(GuavaConversionUtil.addTypeParameters(CommonClassNames.JAVA_UTIL_MAP, context.getType(), context)); } else if ("toList".equals(methodName)) { diff --git a/java/typeMigration/src/com/intellij/refactoring/typeMigration/rules/guava/GuavaFluentIterableConversionRule.java b/java/typeMigration/src/com/intellij/refactoring/typeMigration/rules/guava/GuavaFluentIterableConversionRule.java index 9f3345158f0e..b35e5742ca9e 100644 --- a/java/typeMigration/src/com/intellij/refactoring/typeMigration/rules/guava/GuavaFluentIterableConversionRule.java +++ b/java/typeMigration/src/com/intellij/refactoring/typeMigration/rules/guava/GuavaFluentIterableConversionRule.java @@ -1,5 +1,5 @@ /* - * Copyright 2000-2015 JetBrains s.r.o. + * 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. @@ -78,8 +78,8 @@ public class GuavaFluentIterableConversionRule extends BaseGuavaTypeConversionRu myFluentIterableReturnType = fluentIterableReturnType; } - public TypeConversionDescriptor create() { - GuavaTypeConversionDescriptor descriptor = new GuavaTypeConversionDescriptor(myStringToReplace, myReplaceByString); + public TypeConversionDescriptor create(PsiExpression context) { + GuavaTypeConversionDescriptor descriptor = new GuavaTypeConversionDescriptor(myStringToReplace, myReplaceByString, context); if (!myWithLambdaParameter) { descriptor = descriptor.setConvertParameterAsLambda(false); } @@ -176,7 +176,7 @@ public class GuavaFluentIterableConversionRule extends BaseGuavaTypeConversionRu needSpecifyType = false; } else if (methodName.equals("transformAndConcat")) { - descriptorBase = new FluentIterableConversionUtil.TransformAndConcatConversionRule(); + descriptorBase = new FluentIterableConversionUtil.TransformAndConcatConversionRule(context); } else if (methodName.equals("toArray")) { descriptorBase = FluentIterableConversionUtil.getToArrayDescriptor(from, context); needSpecifyType = false; @@ -250,7 +250,7 @@ public class GuavaFluentIterableConversionRule extends BaseGuavaTypeConversionRu else { final TypeConversionDescriptorFactory base = DESCRIPTORS_MAP.get(methodName); if (base != null) { - final TypeConversionDescriptor descriptor = base.create(); + final TypeConversionDescriptor descriptor = base.create(context); needSpecifyType = base.isChainedMethod(); if (needSpecifyType && !base.isFluentIterableReturnType()) { conversionType = GuavaConversionUtil.addTypeParameters(GuavaOptionalConversionRule.JAVA_OPTIONAL, context.getType(), context); diff --git a/java/typeMigration/src/com/intellij/refactoring/typeMigration/rules/guava/GuavaOptionalConversionRule.java b/java/typeMigration/src/com/intellij/refactoring/typeMigration/rules/guava/GuavaOptionalConversionRule.java index e6ccc20cf915..8aaac548d251 100644 --- a/java/typeMigration/src/com/intellij/refactoring/typeMigration/rules/guava/GuavaOptionalConversionRule.java +++ b/java/typeMigration/src/com/intellij/refactoring/typeMigration/rules/guava/GuavaOptionalConversionRule.java @@ -1,5 +1,5 @@ /* - * Copyright 2000-2015 JetBrains s.r.o. + * 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. @@ -74,7 +74,7 @@ public class GuavaOptionalConversionRule extends BaseGuavaTypeConversionRule { return descriptor; } return GuavaLambda.SUPPLIER.getClassQName().equals(qName) - ? new GuavaTypeConversionDescriptor("$val$.or($other$)", "$val$.orElseGet($other$)") + ? new GuavaTypeConversionDescriptor("$val$.or($other$)", "$val$.orElseGet($other$)", context) : new TypeConversionDescriptor("$val$.or($other$)", "$val$.orElse($other$)"); } return null; @@ -86,7 +86,7 @@ public class GuavaOptionalConversionRule extends BaseGuavaTypeConversionRule { return null; } final PsiExpression functionArgument = arguments[0]; - final TypeConversionDescriptor descriptor = new GuavaTypeConversionDescriptor("$val$.transform($fun$)", "$val$.map($fun$)"); + final TypeConversionDescriptor descriptor = new GuavaTypeConversionDescriptor("$val$.transform($fun$)", "$val$.map($fun$)", context); final PsiType typeParameter = GuavaConversionUtil.getFunctionReturnType(functionArgument); if (typeParameter == null) { return descriptor; diff --git a/java/typeMigration/src/com/intellij/refactoring/typeMigration/rules/guava/GuavaTypeConversionDescriptor.java b/java/typeMigration/src/com/intellij/refactoring/typeMigration/rules/guava/GuavaTypeConversionDescriptor.java index 7c82412c193c..e4c33e5189fc 100644 --- a/java/typeMigration/src/com/intellij/refactoring/typeMigration/rules/guava/GuavaTypeConversionDescriptor.java +++ b/java/typeMigration/src/com/intellij/refactoring/typeMigration/rules/guava/GuavaTypeConversionDescriptor.java @@ -1,5 +1,5 @@ /* - * Copyright 2000-2016 JetBrains s.r.o. + * 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. @@ -32,11 +32,15 @@ import org.jetbrains.annotations.Nullable; public class GuavaTypeConversionDescriptor extends TypeConversionDescriptor { private static final Logger LOG = Logger.getInstance(GuavaTypeConversionDescriptor.class); private final String myReplaceByStringSource; + private final boolean myIterable; private boolean myConvertParameterAsLambda = true; - GuavaTypeConversionDescriptor(@NonNls String stringToReplace, @NonNls String replaceByString) { + GuavaTypeConversionDescriptor(@NonNls String stringToReplace, + @NonNls String replaceByString, + @NotNull PsiExpression expression) { super(stringToReplace, replaceByString); myReplaceByStringSource = replaceByString; + myIterable = isIterable(expression); } public GuavaTypeConversionDescriptor setConvertParameterAsLambda(boolean convertParameterAsLambda) { @@ -46,7 +50,7 @@ public class GuavaTypeConversionDescriptor extends TypeConversionDescriptor { @Override public PsiExpression replace(PsiExpression expression, @NotNull TypeEvaluator evaluator) throws IncorrectOperationException { - setReplaceByString(myReplaceByStringSource + (isIterable(expression) ? ".collect(java.util.stream.Collectors.toList())" : "")); + setReplaceByString(myReplaceByStringSource + (myIterable ? ".collect(java.util.stream.Collectors.toList())" : "")); if (myConvertParameterAsLambda) { LOG.assertTrue(expression instanceof PsiMethodCallExpression); final PsiExpression[] arguments = ((PsiMethodCallExpression)expression).getArgumentList().getExpressions(); @@ -82,6 +86,9 @@ public class GuavaTypeConversionDescriptor extends TypeConversionDescriptor { } } } + else if (parent instanceof PsiMethodCallExpression) { + return isIterable((PsiExpression)parent); + } return false; } diff --git a/java/typeMigration/src/com/intellij/refactoring/typeMigration/rules/guava/IterableStreamConversionRule.java b/java/typeMigration/src/com/intellij/refactoring/typeMigration/rules/guava/IterableStreamConversionRule.java index c87402aa14ac..c4875b31f6f0 100644 --- a/java/typeMigration/src/com/intellij/refactoring/typeMigration/rules/guava/IterableStreamConversionRule.java +++ b/java/typeMigration/src/com/intellij/refactoring/typeMigration/rules/guava/IterableStreamConversionRule.java @@ -1,5 +1,5 @@ /* - * Copyright 2000-2015 JetBrains s.r.o. + * 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. @@ -37,7 +37,7 @@ public class IterableStreamConversionRule extends TypeConversionRule { to, CommonClassNames.JAVA_LANG_ITERABLE, StreamApiConstants.JAVA_UTIL_STREAM_STREAM)) { - return new GuavaTypeConversionDescriptor("$it$", "$it$").setConvertParameterAsLambda(false); + return new GuavaTypeConversionDescriptor("$it$", "$it$", context).setConvertParameterAsLambda(false); } return null; } diff --git a/java/typeMigration/test/com/intellij/codeInsight/inspections/GuavaInspectionTest.java b/java/typeMigration/test/com/intellij/codeInsight/inspections/GuavaInspectionTest.java index addc796dbd3e..f83021ba9d4f 100644 --- a/java/typeMigration/test/com/intellij/codeInsight/inspections/GuavaInspectionTest.java +++ b/java/typeMigration/test/com/intellij/codeInsight/inspections/GuavaInspectionTest.java @@ -178,6 +178,10 @@ public class GuavaInspectionTest extends JavaCodeInsightFixtureTestCase { doTest(); } + public void testConvertFluentIterableAsIterableParameter2() { + doTest(); + } + public void testConvertFunctionAsParameter() { doTest(); } diff --git a/java/typeMigration/testData/inspections/guava/convertFluentIterableAsIterableParameter2.java b/java/typeMigration/testData/inspections/guava/convertFluentIterableAsIterableParameter2.java new file mode 100644 index 000000000000..dfb72fc42c01 --- /dev/null +++ b/java/typeMigration/testData/inspections/guava/convertFluentIterableAsIterableParameter2.java @@ -0,0 +1,11 @@ +import com.google.common.collect.FluentIterable; +import com.google.common.collect.Iterables; + +import java.util.ArrayList; + +public class Main16 { + void m() { + //read-only method with Iterable parameter + Iterables.cycle(FluentIterable.from(new ArrayList()).transform(s -> s)); + } +} diff --git a/java/typeMigration/testData/inspections/guava/convertFluentIterableAsIterableParameter2_after.java b/java/typeMigration/testData/inspections/guava/convertFluentIterableAsIterableParameter2_after.java new file mode 100644 index 000000000000..3acb9c34a713 --- /dev/null +++ b/java/typeMigration/testData/inspections/guava/convertFluentIterableAsIterableParameter2_after.java @@ -0,0 +1,11 @@ +import com.google.common.collect.Iterables; + +import java.util.ArrayList; +import java.util.stream.Collectors; + +public class Main16 { + void m() { + //read-only method with Iterable parameter + Iterables.cycle(new ArrayList().stream().map(s -> s).collect(Collectors.toList())); + } +}