From d45ae0f45cb974cc5251df66507451911f00b795 Mon Sep 17 00:00:00 2001 From: "Vladimir.Orlov" Date: Tue, 27 Jun 2017 12:52:36 +0300 Subject: [PATCH 1/5] build scripts: temporary solution - using 8u112b736.21 for building os x artifacts for 172 builds. https://youtrack.jetbrains.com/issue/JRE-401 --- .../intellij/build/IdeaCommunityProperties.groovy | 1 + .../jetbrains/intellij/build/ProductProperties.groovy | 7 +++++++ .../intellij/build/impl/MacDmgBuilder.groovy | 11 +++++++++-- 3 files changed, 17 insertions(+), 2 deletions(-) diff --git a/build/groovy/org/jetbrains/intellij/build/IdeaCommunityProperties.groovy b/build/groovy/org/jetbrains/intellij/build/IdeaCommunityProperties.groovy index 8b495f85c6fd..27822ca90bb9 100644 --- a/build/groovy/org/jetbrains/intellij/build/IdeaCommunityProperties.groovy +++ b/build/groovy/org/jetbrains/intellij/build/IdeaCommunityProperties.groovy @@ -31,6 +31,7 @@ class IdeaCommunityProperties extends BaseIdeaProperties { additionalIDEPropertiesFilePaths = ["$home/build/conf/ideaCE.properties".toString()] toolsJarRequired = true buildCrossPlatformDistribution = true + customJreFileName = "jbrex8u112b736.21_x64.tar.gz" productLayout.platformApiModules = CommunityRepositoryModules.PLATFORM_API_MODULES + JAVA_API_MODULES productLayout.platformImplementationModules = CommunityRepositoryModules.PLATFORM_IMPLEMENTATION_MODULES + JAVA_IMPLEMENTATION_MODULES + diff --git a/platform/build-scripts/groovy/org/jetbrains/intellij/build/ProductProperties.groovy b/platform/build-scripts/groovy/org/jetbrains/intellij/build/ProductProperties.groovy index 561de01b418c..53f37b0e764d 100644 --- a/platform/build-scripts/groovy/org/jetbrains/intellij/build/ProductProperties.groovy +++ b/platform/build-scripts/groovy/org/jetbrains/intellij/build/ProductProperties.groovy @@ -70,6 +70,13 @@ abstract class ProductProperties { */ String customJvmMemoryOptionsX64 = null + /** + * Include jre for OS X from 171.3 release. + * https://youtrack.jetbrains.com/issue/JRE-401 + * As soon as the issue will be fixed the change should be reverted. + */ + String customJreFileName = "jbre8u112b736.21_x64.tar.gz" + /** * An identifier which will be used to form names for directories where configuration and caches will be stored, usually a product name * without spaces with added version ('IntelliJIdea2016.1' for IntelliJ IDEA 2016.1) diff --git a/platform/build-scripts/groovy/org/jetbrains/intellij/build/impl/MacDmgBuilder.groovy b/platform/build-scripts/groovy/org/jetbrains/intellij/build/impl/MacDmgBuilder.groovy index 9c96ef02212e..e3ff0526fc45 100644 --- a/platform/build-scripts/groovy/org/jetbrains/intellij/build/impl/MacDmgBuilder.groovy +++ b/platform/build-scripts/groovy/org/jetbrains/intellij/build/impl/MacDmgBuilder.groovy @@ -51,9 +51,16 @@ class MacDmgBuilder { static void signAndBuildDmg(BuildContext buildContext, MacDistributionCustomizer customizer, MacHostProperties macHostProperties, String macZipPath) { MacDmgBuilder dmgBuilder = createInstance(buildContext, customizer, macHostProperties) - def jreArchivePath = buildContext.bundledJreManager.findMacJreArchive() + def jreDir = new File(buildContext.paths.projectHome, 'build/jdk') + def jreArchivePath = new File(jreDir, buildContext.productProperties.customJreFileName) + if (!jreArchivePath.exists()) { + buildContext.bundledJreManager.findMacJreArchive() + } + if (jreArchivePath != null) { - dmgBuilder.doSignAndBuildDmg(macZipPath, jreArchivePath) + String jreArchive = jreArchivePath.absolutePath + buildContext.messages.info("jreArchive: $jreArchive") + dmgBuilder.doSignAndBuildDmg(macZipPath, jreArchive) } else { buildContext.messages.info("Skipping building Mac OS distribution with bundled JRE because JRE archive is missing") From 5c68a35fa192c2a6690c927a4f03f3f3d9936ad9 Mon Sep 17 00:00:00 2001 From: Bas Leijdekkers Date: Tue, 27 Jun 2017 12:03:45 +0200 Subject: [PATCH 2/5] IPP: intention to replace simple String.format() call with concatenation (IDEA-175016) --- .../siyeh/ig/psiutils/MethodCallUtils.java | 2 +- .../src/META-INF/IntentionPowerPack.xml | 5 + .../siyeh/IntentionPowerPackBundle.properties | 2 + ...ormatStringWithConcatenationIntention.java | 137 ++++++++++++++++++ .../after.java.template | 6 + .../before.java.template | 6 + .../description.html | 5 + ...tStringWithConcatenationIntentionTest.java | 62 ++++++++ 8 files changed, 224 insertions(+), 1 deletion(-) create mode 100644 plugins/IntentionPowerPak/src/com/siyeh/ipp/concatenation/ReplaceFormatStringWithConcatenationIntention.java create mode 100644 plugins/IntentionPowerPak/src/intentionDescriptions/ReplaceFormatStringWithConcatenationIntention/after.java.template create mode 100644 plugins/IntentionPowerPak/src/intentionDescriptions/ReplaceFormatStringWithConcatenationIntention/before.java.template create mode 100644 plugins/IntentionPowerPak/src/intentionDescriptions/ReplaceFormatStringWithConcatenationIntention/description.html create mode 100644 plugins/IntentionPowerPak/testSrc/com/siyeh/ipp/concatenation/ReplaceFormatStringWithConcatenationIntentionTest.java diff --git a/plugins/InspectionGadgets/InspectionGadgetsAnalysis/src/com/siyeh/ig/psiutils/MethodCallUtils.java b/plugins/InspectionGadgets/InspectionGadgetsAnalysis/src/com/siyeh/ig/psiutils/MethodCallUtils.java index be11f23f6220..7688be1e53a4 100644 --- a/plugins/InspectionGadgets/InspectionGadgetsAnalysis/src/com/siyeh/ig/psiutils/MethodCallUtils.java +++ b/plugins/InspectionGadgets/InspectionGadgetsAnalysis/src/com/siyeh/ig/psiutils/MethodCallUtils.java @@ -168,8 +168,8 @@ public class MethodCallUtils { public static boolean isCallToMethod(@NotNull PsiMethodCallExpression expression, @NonNls @Nullable String calledOnClassName, @Nullable PsiType returnType, @NonNls @Nullable String methodName, @Nullable PsiType... parameterTypes) { - final PsiReferenceExpression methodExpression = expression.getMethodExpression(); if (methodName != null) { + final PsiReferenceExpression methodExpression = expression.getMethodExpression(); final String referenceName = methodExpression.getReferenceName(); if (!methodName.equals(referenceName)) { return false; diff --git a/plugins/IntentionPowerPak/src/META-INF/IntentionPowerPack.xml b/plugins/IntentionPowerPak/src/META-INF/IntentionPowerPack.xml index ef1df657424b..cdc27ddbb679 100644 --- a/plugins/IntentionPowerPak/src/META-INF/IntentionPowerPack.xml +++ b/plugins/IntentionPowerPak/src/META-INF/IntentionPowerPack.xml @@ -367,6 +367,11 @@ com.siyeh.IntentionPowerPackBundle intention.category.strings + + com.siyeh.ipp.concatenation.ReplaceFormatStringWithConcatenationIntention + com.siyeh.IntentionPowerPackBundle + intention.category.strings + com.siyeh.ipp.concatenation.CopyConcatenatedStringToClipboardIntention com.siyeh.IntentionPowerPackBundle diff --git a/plugins/IntentionPowerPak/src/com/siyeh/IntentionPowerPackBundle.properties b/plugins/IntentionPowerPak/src/com/siyeh/IntentionPowerPackBundle.properties index caaf914b8cfe..2bbc06f742b4 100644 --- a/plugins/IntentionPowerPak/src/com/siyeh/IntentionPowerPackBundle.properties +++ b/plugins/IntentionPowerPak/src/com/siyeh/IntentionPowerPackBundle.properties @@ -117,6 +117,8 @@ extract.while.loop.condition.to.if.statement.intention.name=Extract condition to extract.while.loop.condition.to.if.statement.intention.family.name=Extract While Loop Condition to Internal If Statement replace.concatenation.with.format.string.intention.name=Replace '+' with 'String.format()' replace.concatenation.with.format.string.intention.family.name=Replace String Concatenation with String.format() +replace.format.string.with.concatenation.intention.name=Replace 'String.format()' with concatenation +replace.format.string.with.concatenation.intention.family.name=Replace String.format() with Concatenation copy.concatenated.string.to.clipboard.intention.name=Copy String concatenation text to the clipboard copy.concatenated.string.to.clipboard.intention.family.name=Copy String Concatenation Text to the Clipboard flip.expression.intention.family.name=Flip Binary Expression diff --git a/plugins/IntentionPowerPak/src/com/siyeh/ipp/concatenation/ReplaceFormatStringWithConcatenationIntention.java b/plugins/IntentionPowerPak/src/com/siyeh/ipp/concatenation/ReplaceFormatStringWithConcatenationIntention.java new file mode 100644 index 000000000000..1b9ee8707c9e --- /dev/null +++ b/plugins/IntentionPowerPak/src/com/siyeh/ipp/concatenation/ReplaceFormatStringWithConcatenationIntention.java @@ -0,0 +1,137 @@ +/* + * 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.siyeh.ipp.concatenation; + +import com.intellij.psi.*; +import com.siyeh.ig.PsiReplacementUtil; +import com.siyeh.ig.psiutils.ExpressionUtils; +import com.siyeh.ig.psiutils.MethodCallUtils; +import com.siyeh.ig.psiutils.ParenthesesUtils; +import com.siyeh.ig.psiutils.TypeUtils; +import com.siyeh.ipp.base.Intention; +import com.siyeh.ipp.base.PsiElementPredicate; +import org.jetbrains.annotations.NotNull; + +/** + * @author Bas Leijdekkers + */ +public class ReplaceFormatStringWithConcatenationIntention extends Intention { + + @NotNull + @Override + protected PsiElementPredicate getElementPredicate() { + return element -> { + if (!(element instanceof PsiMethodCallExpression)) { + return false; + } + final PsiMethodCallExpression methodCallExpression = (PsiMethodCallExpression)element; + if (!MethodCallUtils.isCallToMethod(methodCallExpression, CommonClassNames.JAVA_LANG_STRING, TypeUtils.getStringType(element), + "format", (PsiType[])null)) { + return false; + } + final PsiExpressionList argumentList = methodCallExpression.getArgumentList(); + final PsiExpression[] arguments = argumentList.getExpressions(); + + return arguments.length > 1 && getPercentSCount(arguments[0]) == arguments.length - 1 || + arguments.length > 2 && getPercentSCount(arguments[1]) == arguments.length - 2; + }; + } + + static int getPercentSCount(PsiExpression expression) { + expression = ParenthesesUtils.stripParentheses(expression); + if (!(expression instanceof PsiLiteralExpression || expression instanceof PsiPolyadicExpression) + || !ExpressionUtils.hasStringType(expression)) { + return -1; + } + final Object value = ExpressionUtils.computeConstantExpression(expression); + if (!(value instanceof String)) { + return -1; + } + final String string = (String)value; + int index = string.indexOf('%'); + final int length = string.length(); + int count = 0; + while (index >= 0) { + final char c = string.charAt(index + 1); + if (length > index + 1) { + if (c == 's') { + count++; + } + else if (c != '%') { + return -1; + } + } + index = string.indexOf('%', index + 1); + } + if (count == 0) { + return -1; + } + return count; + } + + @Override + protected void processIntention(@NotNull PsiElement element) { + if (!(element instanceof PsiMethodCallExpression)) { + return; + } + final PsiMethodCallExpression methodCallExpression = (PsiMethodCallExpression)element; + final PsiExpressionList argumentList = methodCallExpression.getArgumentList(); + final PsiExpression[] arguments = argumentList.getExpressions(); + final String replacementExpression; + if (ExpressionUtils.hasStringType(arguments[0])) { + replacementExpression = buildReplacementExpression(arguments, 0); + } + else { + replacementExpression = buildReplacementExpression(arguments, 1); + } + PsiReplacementUtil.replaceExpression(methodCallExpression, replacementExpression); + } + + public String buildReplacementExpression(PsiExpression[] arguments, int indexOfFormatString) { + final StringBuilder builder = new StringBuilder(); + String value = (String)ExpressionUtils.computeConstantExpression(arguments[indexOfFormatString]); + assert value != null; + value = value.replace("%%", "%"); + int start = 0; + int end = value.indexOf("%s"); + int count = 0; + while (end >= 0) { + if (end > start) { + if (builder.length() > 0) { + builder.append('+'); + } + builder.append('"').append(value.substring(start, end)).append("\"+"); + } + count++; + final PsiExpression argument = arguments[indexOfFormatString + count]; + if (builder.length() == 0 && !ExpressionUtils.hasStringType(argument)) { + builder.append("String.valueOf(").append(argument.getText()).append(')'); + } + else { + builder.append(argument.getText()); + } + start = end + 2; + end = value.indexOf("%s", start); + } + if (start < value.length() - 1) { + if (builder.length() > 0) { + builder.append('+'); + } + builder.append('"').append(value.substring(start)).append('"'); + } + return builder.toString(); + } +} diff --git a/plugins/IntentionPowerPak/src/intentionDescriptions/ReplaceFormatStringWithConcatenationIntention/after.java.template b/plugins/IntentionPowerPak/src/intentionDescriptions/ReplaceFormatStringWithConcatenationIntention/after.java.template new file mode 100644 index 000000000000..1be439a65e47 --- /dev/null +++ b/plugins/IntentionPowerPak/src/intentionDescriptions/ReplaceFormatStringWithConcatenationIntention/after.java.template @@ -0,0 +1,6 @@ +class X { + + public String message(String actual, String expected) { + return "Expected to get a '" + expected + "', got a '" + actual + "' instead"; + } +} \ No newline at end of file diff --git a/plugins/IntentionPowerPak/src/intentionDescriptions/ReplaceFormatStringWithConcatenationIntention/before.java.template b/plugins/IntentionPowerPak/src/intentionDescriptions/ReplaceFormatStringWithConcatenationIntention/before.java.template new file mode 100644 index 000000000000..e2ee93f399ca --- /dev/null +++ b/plugins/IntentionPowerPak/src/intentionDescriptions/ReplaceFormatStringWithConcatenationIntention/before.java.template @@ -0,0 +1,6 @@ +class X { + + public String message(String actual, String expected) { + return String.format("Expected to get a '%s', got a '%s' instead", expected, actual); + } +} \ No newline at end of file diff --git a/plugins/IntentionPowerPak/src/intentionDescriptions/ReplaceFormatStringWithConcatenationIntention/description.html b/plugins/IntentionPowerPak/src/intentionDescriptions/ReplaceFormatStringWithConcatenationIntention/description.html new file mode 100644 index 000000000000..89623c8ef5a5 --- /dev/null +++ b/plugins/IntentionPowerPak/src/intentionDescriptions/ReplaceFormatStringWithConcatenationIntention/description.html @@ -0,0 +1,5 @@ + + +

Replaces a simple call to String.format() with a String concatenation.

+ + \ No newline at end of file diff --git a/plugins/IntentionPowerPak/testSrc/com/siyeh/ipp/concatenation/ReplaceFormatStringWithConcatenationIntentionTest.java b/plugins/IntentionPowerPak/testSrc/com/siyeh/ipp/concatenation/ReplaceFormatStringWithConcatenationIntentionTest.java new file mode 100644 index 000000000000..10ddba4defff --- /dev/null +++ b/plugins/IntentionPowerPak/testSrc/com/siyeh/ipp/concatenation/ReplaceFormatStringWithConcatenationIntentionTest.java @@ -0,0 +1,62 @@ +/* + * 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.siyeh.ipp.concatenation; + +import com.siyeh.ipp.IPPTestCase; +import junit.framework.TestCase; + +/** + * @author Bas Leijdekkers + */ +public class ReplaceFormatStringWithConcatenationIntentionTest extends IPPTestCase { + + public void testNotSupported() { + doTestIntentionNotAvailable("class C {" + + " String m() {" + + " return /*_Replace 'String.format()' with concatenation*/String.format(\"%d\", 1);" + + " }" + + "}"); + } + + public void testSimple() { + doTest("class C {" + + " String m() {" + + " return /*_Replace 'String.format()' with concatenation*/String.format(\"%s\", 1);" + + " }" + + "}", + + "class C {" + + " String m() {" + + " return String.valueOf(1);" + + " }" + + "}"); + } + + public void testMultiple() { + doTest("class C {" + + " String m(String expected, String actual) {" + + " return String./*_Replace 'String.format()' with concatenation*/format(\"Expected to get a '%s', got a '%s' instead\", expected, actual);" + + " }" + + "}", + + "class C {" + + " String m(String expected, String actual) {" + + " return \"Expected to get a '\" + expected + \"', got a '\" + actual + \"' instead\";" + + " }" + + "}"); + } + +} \ No newline at end of file From f52e3077445635c8ad7a7620a3f818cb9f70ace8 Mon Sep 17 00:00:00 2001 From: Roman Shevchenko Date: Tue, 27 Jun 2017 13:17:08 +0300 Subject: [PATCH 3/5] [tests] annotates property-based tests for exclusion --- .../java/propertyBased/ApplyRandomIntentionsTest.java | 4 +++- .../java/propertyBased/CompletionConsistencyTest.java | 10 ++++++---- 2 files changed, 9 insertions(+), 5 deletions(-) diff --git a/java/java-tests/testSrc/com/intellij/java/propertyBased/ApplyRandomIntentionsTest.java b/java/java-tests/testSrc/com/intellij/java/propertyBased/ApplyRandomIntentionsTest.java index a4e646a1106b..4015167a4576 100644 --- a/java/java-tests/testSrc/com/intellij/java/propertyBased/ApplyRandomIntentionsTest.java +++ b/java/java-tests/testSrc/com/intellij/java/propertyBased/ApplyRandomIntentionsTest.java @@ -19,6 +19,7 @@ import com.intellij.openapi.command.WriteCommandAction; import com.intellij.psi.*; import com.intellij.psi.util.PsiModificationTracker; import com.intellij.psi.util.PsiTreeUtil; +import com.intellij.testFramework.SkipSlowTestLocally; import com.intellij.util.SystemProperties; import org.jetbrains.annotations.Nullable; import slowCheck.*; @@ -27,6 +28,7 @@ import java.util.Objects; import java.util.concurrent.atomic.AtomicLong; import java.util.function.Consumer; +@SkipSlowTestLocally public class ApplyRandomIntentionsTest extends AbstractApplyAndRevertTestCase { @Override @@ -134,7 +136,7 @@ public class ApplyRandomIntentionsTest extends AbstractApplyAndRevertTestCase { CheckerSettings settings = CheckerSettings.DEFAULT_SETTINGS.withIterationCount(30); Generator genIntention = Generator.from(data -> InvokeIntention.generate(psiManager.findFile(javaFiles().generateValue(data)), data)); - + PropertyChecker.forAll(settings, Generator.listsOf(genIntention.noShrink()), list -> { long startModCount = tracker.getModificationCount(); if (rebuildStamp.getAndSet(startModCount) != startModCount) { diff --git a/java/java-tests/testSrc/com/intellij/java/propertyBased/CompletionConsistencyTest.java b/java/java-tests/testSrc/com/intellij/java/propertyBased/CompletionConsistencyTest.java index bef9a8a25e14..a0569589ae06 100644 --- a/java/java-tests/testSrc/com/intellij/java/propertyBased/CompletionConsistencyTest.java +++ b/java/java-tests/testSrc/com/intellij/java/propertyBased/CompletionConsistencyTest.java @@ -30,6 +30,7 @@ import com.intellij.openapi.util.text.StringUtil; import com.intellij.psi.*; import com.intellij.psi.util.PsiTreeUtil; import com.intellij.testFramework.PsiTestUtil; +import com.intellij.testFramework.SkipSlowTestLocally; import com.intellij.util.SystemProperties; import com.intellij.util.containers.ContainerUtil; import com.intellij.util.ui.UIUtil; @@ -41,8 +42,9 @@ import java.util.List; /** * @author peter */ +@SkipSlowTestLocally public class CompletionConsistencyTest extends AbstractApplyAndRevertTestCase { - + static class CompletionInvocation extends ActionOnRange { final int itemIndexRaw; LookupElement selectedItem; @@ -91,7 +93,7 @@ public class CompletionConsistencyTest extends AbstractApplyAndRevertTestCase { if (offset < 0) continue; editor.getCaretModel().moveToOffset(offset); - + PsiElement leaf = psiFile.findElementAt(offset); try { @@ -138,8 +140,8 @@ public class CompletionConsistencyTest extends AbstractApplyAndRevertTestCase { private static boolean isInnermostReferenceQualifier(PsiElement leaf) { PsiElement parent = leaf.getParent(); - return parent instanceof PsiJavaCodeReferenceElement && - !((PsiJavaCodeReferenceElement)parent).isQualified() && + return parent instanceof PsiJavaCodeReferenceElement && + !((PsiJavaCodeReferenceElement)parent).isQualified() && parent.getParent() instanceof PsiJavaCodeReferenceElement; } From 6cb35eac1d7ba7187b43f993c1da924a404064ff Mon Sep 17 00:00:00 2001 From: Anna Kozlova Date: Tue, 27 Jun 2017 12:22:09 +0300 Subject: [PATCH 4/5] inline superclass: hide javadoc settings when no found anyway (IDEA-175025) --- .../InlineSuperClassRefactoringDialog.java | 12 +++++++++++- .../InlineSuperClassRefactoringProcessor.java | 17 ++++++++++------- 2 files changed, 21 insertions(+), 8 deletions(-) diff --git a/java/java-impl/src/com/intellij/refactoring/inlineSuperClass/InlineSuperClassRefactoringDialog.java b/java/java-impl/src/com/intellij/refactoring/inlineSuperClass/InlineSuperClassRefactoringDialog.java index 49047e8b8c33..1acf2976f963 100644 --- a/java/java-impl/src/com/intellij/refactoring/inlineSuperClass/InlineSuperClassRefactoringDialog.java +++ b/java/java-impl/src/com/intellij/refactoring/inlineSuperClass/InlineSuperClassRefactoringDialog.java @@ -18,6 +18,8 @@ package com.intellij.refactoring.inlineSuperClass; import com.intellij.openapi.project.Project; import com.intellij.psi.PsiClass; +import com.intellij.psi.PsiDocCommentOwner; +import com.intellij.psi.PsiMember; import com.intellij.refactoring.JavaRefactoringSettings; import com.intellij.refactoring.RefactoringBundle; import com.intellij.refactoring.inline.InlineOptionsDialog; @@ -70,8 +72,16 @@ public class InlineSuperClassRefactoringDialog extends InlineOptionsDialog { final GridBagConstraints gc = new GridBagConstraints(0, GridBagConstraints.RELATIVE, 1, 1, 1, 0, GridBagConstraints.NORTHWEST, GridBagConstraints.HORIZONTAL, JBUI.emptyInsets(), 0, 0); - panel.add(myDocPanel, gc); panel.add(super.createCenterPanel(), gc); + panel.add(myDocPanel, gc); + if (mySuperClass.getDocComment() == null) { + boolean hasJavadoc = + InlineSuperClassRefactoringProcessor.getClassMembersToPush(mySuperClass).stream().anyMatch(memberInfo -> { + PsiMember member = memberInfo.getMember(); + return member instanceof PsiDocCommentOwner && ((PsiDocCommentOwner)member).getDocComment() != null; + }); + myDocPanel.setVisible(hasJavadoc); + } gc.weighty = 1; gc.fill = GridBagConstraints.BOTH; panel.add(Box.createVerticalGlue(), gc); diff --git a/java/java-impl/src/com/intellij/refactoring/inlineSuperClass/InlineSuperClassRefactoringProcessor.java b/java/java-impl/src/com/intellij/refactoring/inlineSuperClass/InlineSuperClassRefactoringProcessor.java index 694519705370..e45dd2e6e61a 100644 --- a/java/java-impl/src/com/intellij/refactoring/inlineSuperClass/InlineSuperClassRefactoringProcessor.java +++ b/java/java-impl/src/com/intellij/refactoring/inlineSuperClass/InlineSuperClassRefactoringProcessor.java @@ -40,7 +40,6 @@ import com.intellij.usageView.UsageInfo; import com.intellij.usageView.UsageViewDescriptor; import com.intellij.util.ArrayUtilRt; import com.intellij.util.IncorrectOperationException; -import com.intellij.util.Processor; import com.intellij.util.containers.ContainerUtil; import com.intellij.util.containers.HashMap; import com.intellij.util.containers.MultiMap; @@ -63,18 +62,22 @@ public class InlineSuperClassRefactoringProcessor extends FixableUsagesRefactori myCurrentInheritor = currentInheritor; mySuperClass = superClass; myPolicy = policy; - MemberInfoStorage memberInfoStorage = new MemberInfoStorage(mySuperClass, new MemberInfo.Filter() { - public boolean includeMember(PsiMember element) { - return !(element instanceof PsiClass) || PsiTreeUtil.isAncestor(mySuperClass, element, true); - } - }); - List members = memberInfoStorage.getClassMemberInfos(mySuperClass); + List members = getClassMembersToPush(mySuperClass); for (MemberInfo member : members) { member.setChecked(true); } myMemberInfos = members.toArray(new MemberInfo[members.size()]); } + public static List getClassMembersToPush(PsiClass superClass) { + MemberInfoStorage memberInfoStorage = new MemberInfoStorage(superClass, new MemberInfo.Filter() { + public boolean includeMember(PsiMember element) { + return !(element instanceof PsiClass) || PsiTreeUtil.isAncestor(superClass, element, true); + } + }); + return memberInfoStorage.getClassMemberInfos(superClass); + } + @NotNull protected UsageViewDescriptor createUsageViewDescriptor(@NotNull final UsageInfo[] usages) { return new InlineSuperClassUsageViewDescriptor(mySuperClass); From 0314bd07e8c0a8db0b9e81f7ed981b69f4af7a66 Mon Sep 17 00:00:00 2001 From: Anna Kozlova Date: Tue, 27 Jun 2017 13:18:27 +0300 Subject: [PATCH 5/5] qualify unresolved refs with static accessor fixes (IDEA-168929) --- .../intention/QuickFixFactory.java | 1 + .../impl/analysis/HighlightMethodUtil.java | 3 + .../intention/EmptyQuickFixFactory.java | 6 ++ .../quickfix/DefaultQuickFixProvider.java | 1 + .../quickfix/QualifyStaticConstantFix.java | 59 +++++++++++++++++ .../quickfix/QualifyStaticMethodCallFix.java | 65 +++++++++++++++++++ .../quickfix/StaticImportConstantFix.java | 2 +- .../impl/quickfix/StaticImportMethodFix.java | 2 +- .../StaticImportMethodQuestionAction.java | 2 +- .../impl/config/QuickFixFactoryImpl.java | 6 ++ 10 files changed, 144 insertions(+), 3 deletions(-) create mode 100644 java/java-impl/src/com/intellij/codeInsight/daemon/impl/quickfix/QualifyStaticConstantFix.java create mode 100644 java/java-impl/src/com/intellij/codeInsight/daemon/impl/quickfix/QualifyStaticMethodCallFix.java diff --git a/java/java-analysis-api/src/com/intellij/codeInsight/intention/QuickFixFactory.java b/java/java-analysis-api/src/com/intellij/codeInsight/intention/QuickFixFactory.java index b5400e54950d..2ffcac8fbfe4 100644 --- a/java/java-analysis-api/src/com/intellij/codeInsight/intention/QuickFixFactory.java +++ b/java/java-analysis-api/src/com/intellij/codeInsight/intention/QuickFixFactory.java @@ -203,6 +203,7 @@ public abstract class QuickFixFactory { @NotNull public abstract IntentionAction createCreateGetterSetterPropertyFromUsageFix(@NotNull PsiMethodCallExpression call); @NotNull public abstract IntentionAction createStaticImportMethodFix(@NotNull PsiMethodCallExpression call); + @NotNull public abstract IntentionAction createQualifyStaticMethodCallFix(@NotNull PsiMethodCallExpression call); @NotNull public abstract IntentionAction createReplaceAddAllArrayToCollectionFix(@NotNull PsiMethodCallExpression call); diff --git a/java/java-analysis-impl/src/com/intellij/codeInsight/daemon/impl/analysis/HighlightMethodUtil.java b/java/java-analysis-impl/src/com/intellij/codeInsight/daemon/impl/analysis/HighlightMethodUtil.java index 6c7d4c364dec..16221f829c46 100644 --- a/java/java-analysis-impl/src/com/intellij/codeInsight/daemon/impl/analysis/HighlightMethodUtil.java +++ b/java/java-analysis-impl/src/com/intellij/codeInsight/daemon/impl/analysis/HighlightMethodUtil.java @@ -461,6 +461,8 @@ public class HighlightMethodUtil { QuickFixAction.registerQuickFixAction(highlightInfo, range, QUICK_FIX_FACTORY.createCreateAbstractMethodFromUsageFix(methodCall)); QuickFixAction.registerQuickFixAction(highlightInfo, range, QUICK_FIX_FACTORY.createCreatePropertyFromUsageFix(methodCall)); QuickFixAction.registerQuickFixAction(highlightInfo, range, QUICK_FIX_FACTORY.createStaticImportMethodFix(methodCall)); + QuickFixAction.registerQuickFixAction(highlightInfo, range, QUICK_FIX_FACTORY.createQualifyStaticMethodCallFix(methodCall)); + QuickFixAction.registerQuickFixAction(highlightInfo, range, QUICK_FIX_FACTORY.addMethodQualifierFix(methodCall)); if (resolved instanceof PsiVariable && languageLevel.isAtLeast(LanguageLevel.JDK_1_8)) { PsiMethod method = LambdaUtil.getFunctionalInterfaceMethod(((PsiVariable)resolved).getType()); if (method != null) { @@ -854,6 +856,7 @@ public class HighlightMethodUtil { registerChangeParameterClassFix(methodCall, list, highlightInfo); if (methodCandidates.length == 0) { QuickFixAction.registerQuickFixAction(highlightInfo, fixRange, QUICK_FIX_FACTORY.createStaticImportMethodFix(methodCall)); + QuickFixAction.registerQuickFixAction(highlightInfo, fixRange, QUICK_FIX_FACTORY.createQualifyStaticMethodCallFix(methodCall)); QuickFixAction.registerQuickFixAction(highlightInfo, fixRange, QUICK_FIX_FACTORY.addMethodQualifierFix(methodCall)); } for (IntentionAction action : QUICK_FIX_FACTORY.getVariableTypeFromCallFixes(methodCall, list)) { diff --git a/java/java-analysis-impl/src/com/intellij/codeInsight/intention/EmptyQuickFixFactory.java b/java/java-analysis-impl/src/com/intellij/codeInsight/intention/EmptyQuickFixFactory.java index 549751caa5cd..7276d30e12af 100644 --- a/java/java-analysis-impl/src/com/intellij/codeInsight/intention/EmptyQuickFixFactory.java +++ b/java/java-analysis-impl/src/com/intellij/codeInsight/intention/EmptyQuickFixFactory.java @@ -455,6 +455,12 @@ public class EmptyQuickFixFactory extends QuickFixFactory { return QuickFixes.EMPTY_FIX; } + @NotNull + @Override + public IntentionAction createQualifyStaticMethodCallFix(@NotNull PsiMethodCallExpression call) { + return QuickFixes.EMPTY_FIX; + } + @NotNull @Override public IntentionAction createReplaceAddAllArrayToCollectionFix(@NotNull PsiMethodCallExpression psiMethodCallExpression) { diff --git a/java/java-impl/src/com/intellij/codeInsight/daemon/impl/quickfix/DefaultQuickFixProvider.java b/java/java-impl/src/com/intellij/codeInsight/daemon/impl/quickfix/DefaultQuickFixProvider.java index 05a794b01ae0..31354e2475e6 100644 --- a/java/java-impl/src/com/intellij/codeInsight/daemon/impl/quickfix/DefaultQuickFixProvider.java +++ b/java/java-impl/src/com/intellij/codeInsight/daemon/impl/quickfix/DefaultQuickFixProvider.java @@ -44,6 +44,7 @@ public class DefaultQuickFixProvider extends UnresolvedReferenceQuickFixProvider registrar.register(new ImportClassFix(ref)); registrar.register(new StaticImportConstantFix(ref)); + registrar.register(new QualifyStaticConstantFix(ref)); registrar.register(QuickFixFactory.getInstance().createSetupJDKFix()); OrderEntryFix.registerFixes(registrar, ref); diff --git a/java/java-impl/src/com/intellij/codeInsight/daemon/impl/quickfix/QualifyStaticConstantFix.java b/java/java-impl/src/com/intellij/codeInsight/daemon/impl/quickfix/QualifyStaticConstantFix.java new file mode 100644 index 000000000000..7eac4ed2b49d --- /dev/null +++ b/java/java-impl/src/com/intellij/codeInsight/daemon/impl/quickfix/QualifyStaticConstantFix.java @@ -0,0 +1,59 @@ +/* + * 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.codeInsight.daemon.impl.quickfix; + +import com.intellij.codeInsight.daemon.QuickFixBundle; +import com.intellij.openapi.editor.Editor; +import com.intellij.openapi.project.Project; +import com.intellij.psi.PsiField; +import com.intellij.psi.PsiJavaCodeReferenceElement; +import com.intellij.psi.PsiReferenceExpression; +import org.jetbrains.annotations.NotNull; + +import java.util.List; + +public class QualifyStaticConstantFix extends StaticImportConstantFix { + public QualifyStaticConstantFix(@NotNull PsiJavaCodeReferenceElement referenceElement) { + super(referenceElement); + } + + @NotNull + @Override + protected String getBaseText() { + return "Qualify static constant access"; + } + + @NotNull + @Override + protected StaticImportMethodQuestionAction createQuestionAction(List fieldsToImport, + @NotNull Project project, + Editor editor) { + return new StaticImportMethodQuestionAction(project, editor, fieldsToImport, myRef) { + @NotNull + @Override + protected String getPopupTitle() { + return QuickFixBundle.message("field.to.import.chooser.title"); + } + + @Override + protected void doImport(PsiField toImport) { + PsiJavaCodeReferenceElement element = myRef.getElement(); + if (!(element instanceof PsiReferenceExpression)) return; + QualifyStaticMethodCallFix.qualifyStatically(toImport, project, (PsiReferenceExpression)element); + } + }; + } +} diff --git a/java/java-impl/src/com/intellij/codeInsight/daemon/impl/quickfix/QualifyStaticMethodCallFix.java b/java/java-impl/src/com/intellij/codeInsight/daemon/impl/quickfix/QualifyStaticMethodCallFix.java new file mode 100644 index 000000000000..f0f91745729b --- /dev/null +++ b/java/java-impl/src/com/intellij/codeInsight/daemon/impl/quickfix/QualifyStaticMethodCallFix.java @@ -0,0 +1,65 @@ +/* + * 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.codeInsight.daemon.impl.quickfix; + +import com.intellij.openapi.command.WriteCommandAction; +import com.intellij.openapi.editor.Editor; +import com.intellij.openapi.project.Project; +import com.intellij.psi.*; +import com.intellij.psi.codeStyle.JavaCodeStyleManager; +import org.jetbrains.annotations.NotNull; + +import java.util.List; + +public class QualifyStaticMethodCallFix extends StaticImportMethodFix { + public QualifyStaticMethodCallFix(@NotNull PsiMethodCallExpression methodCallExpression) { + super(methodCallExpression); + } + + @NotNull + @Override + protected String getBaseText() { + return "Qualify static call"; + } + + @NotNull + @Override + protected StaticImportMethodQuestionAction createQuestionAction(List methodsToImport, + @NotNull Project project, + Editor editor) { + return new StaticImportMethodQuestionAction(project, editor, methodsToImport, myMethodCall) { + @Override + protected void doImport(PsiMethod toImport) { + PsiMethodCallExpression element = myMethodCall.getElement(); + if (element == null) return; + qualifyStatically(toImport, project, element.getMethodExpression()); + } + }; + } + + public static void qualifyStatically(PsiMember toImport, + Project project, + PsiReferenceExpression qualifiedExpression) { + PsiClass containingClass = toImport.getContainingClass(); + if (containingClass == null) return; + PsiReferenceExpression qualifier = JavaPsiFacade.getElementFactory(project).createReferenceExpression(containingClass); + WriteCommandAction.runWriteCommandAction(project, "Qualify Static Access", null, () -> { + qualifiedExpression.setQualifierExpression(qualifier); + JavaCodeStyleManager.getInstance(project).shortenClassReferences(qualifiedExpression); + } + ); + } +} diff --git a/java/java-impl/src/com/intellij/codeInsight/daemon/impl/quickfix/StaticImportConstantFix.java b/java/java-impl/src/com/intellij/codeInsight/daemon/impl/quickfix/StaticImportConstantFix.java index 06ffe94bdfb9..9719f79367b0 100644 --- a/java/java-impl/src/com/intellij/codeInsight/daemon/impl/quickfix/StaticImportConstantFix.java +++ b/java/java-impl/src/com/intellij/codeInsight/daemon/impl/quickfix/StaticImportConstantFix.java @@ -31,7 +31,7 @@ import java.util.Collections; import java.util.List; public class StaticImportConstantFix extends StaticImportMemberFix { - private final SmartPsiElementPointer myRef; + protected final SmartPsiElementPointer myRef; public StaticImportConstantFix(@NotNull PsiJavaCodeReferenceElement referenceElement) { myRef = SmartPointerManager.getInstance(referenceElement.getProject()).createSmartPsiElementPointer(referenceElement); diff --git a/java/java-impl/src/com/intellij/codeInsight/daemon/impl/quickfix/StaticImportMethodFix.java b/java/java-impl/src/com/intellij/codeInsight/daemon/impl/quickfix/StaticImportMethodFix.java index bab43bb73f66..786db0e6d0d6 100644 --- a/java/java-impl/src/com/intellij/codeInsight/daemon/impl/quickfix/StaticImportMethodFix.java +++ b/java/java-impl/src/com/intellij/codeInsight/daemon/impl/quickfix/StaticImportMethodFix.java @@ -32,7 +32,7 @@ import java.util.Collections; import java.util.List; public class StaticImportMethodFix extends StaticImportMemberFix { - private final SmartPsiElementPointer myMethodCall; + protected final SmartPsiElementPointer myMethodCall; public StaticImportMethodFix(@NotNull PsiMethodCallExpression methodCallExpression) { myMethodCall = SmartPointerManager.getInstance(methodCallExpression.getProject()).createSmartPsiElementPointer(methodCallExpression); diff --git a/java/java-impl/src/com/intellij/codeInsight/daemon/impl/quickfix/StaticImportMethodQuestionAction.java b/java/java-impl/src/com/intellij/codeInsight/daemon/impl/quickfix/StaticImportMethodQuestionAction.java index 70123159619e..16823f6096cb 100644 --- a/java/java-impl/src/com/intellij/codeInsight/daemon/impl/quickfix/StaticImportMethodQuestionAction.java +++ b/java/java-impl/src/com/intellij/codeInsight/daemon/impl/quickfix/StaticImportMethodQuestionAction.java @@ -87,7 +87,7 @@ public class StaticImportMethodQuestionAction implements Qu return true; } - private void doImport(final T toImport) { + protected void doImport(final T toImport) { final Project project = toImport.getProject(); final PsiElement element = myRef.getElement(); if (element == null) return; diff --git a/java/java-impl/src/com/intellij/codeInsight/intention/impl/config/QuickFixFactoryImpl.java b/java/java-impl/src/com/intellij/codeInsight/intention/impl/config/QuickFixFactoryImpl.java index c1d685a2f06c..aac472a44051 100644 --- a/java/java-impl/src/com/intellij/codeInsight/intention/impl/config/QuickFixFactoryImpl.java +++ b/java/java-impl/src/com/intellij/codeInsight/intention/impl/config/QuickFixFactoryImpl.java @@ -535,6 +535,12 @@ public class QuickFixFactoryImpl extends QuickFixFactory { return new StaticImportMethodFix(call); } + @NotNull + @Override + public IntentionAction createQualifyStaticMethodCallFix(@NotNull PsiMethodCallExpression call) { + return new QualifyStaticMethodCallFix(call); + } + @NotNull @Override public IntentionAction createReplaceAddAllArrayToCollectionFix(@NotNull PsiMethodCallExpression call) {