diff --git a/.idea/libraries/jna.xml b/.idea/libraries/jna.xml index 7a9e4319d055..d9fed3852d8f 100644 --- a/.idea/libraries/jna.xml +++ b/.idea/libraries/jna.xml @@ -3,7 +3,6 @@ - diff --git a/java/debugger/impl/src/com/intellij/debugger/impl/ReloadClassesWorker.java b/java/debugger/impl/src/com/intellij/debugger/impl/ReloadClassesWorker.java index 9ff1b2bec9fd..d8d8dd469c43 100644 --- a/java/debugger/impl/src/com/intellij/debugger/impl/ReloadClassesWorker.java +++ b/java/debugger/impl/src/com/intellij/debugger/impl/ReloadClassesWorker.java @@ -1,5 +1,5 @@ /* - * Copyright 2000-2013 JetBrains s.r.o. + * Copyright 2000-2009 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. @@ -130,13 +130,8 @@ class ReloadClassesWorker { continue; } redefineProcessor.processClass(qualifiedName, content); - if (myProgress.isCancelled()) { - break; - } - } - if (!myProgress.isCancelled()) { - redefineProcessor.processPending(); } + redefineProcessor.processPending(); myProgress.setFraction(1); final int partiallyRedefinedClassesCount = redefineProcessor.getPartiallyRedefinedClassesCount(); diff --git a/java/java-analysis-impl/src/com/intellij/codeInsight/daemon/impl/analysis/HighlightUtil.java b/java/java-analysis-impl/src/com/intellij/codeInsight/daemon/impl/analysis/HighlightUtil.java index 12af14a61b5c..15bb4fe3bd4c 100644 --- a/java/java-analysis-impl/src/com/intellij/codeInsight/daemon/impl/analysis/HighlightUtil.java +++ b/java/java-analysis-impl/src/com/intellij/codeInsight/daemon/impl/analysis/HighlightUtil.java @@ -288,9 +288,48 @@ public class HighlightUtil extends HighlightUtilBase { } + @Nullable + static HighlightInfo checkIntersectionInTypeCast(@NotNull PsiTypeCastExpression expression) { + final PsiTypeElement castTypeElement = expression.getCastType(); + if (castTypeElement == null) return null; + PsiType castType = castTypeElement.getType(); + if (isIntersection(castTypeElement, castType)) { + if (PsiUtil.isLanguageLevel8OrHigher(expression)) { + final PsiTypeElement[] conjuncts = PsiTreeUtil.getChildrenOfType(castTypeElement, PsiTypeElement.class); + if (conjuncts != null) { + final List conjList = new ArrayList(Arrays.asList(conjuncts)); + for (int i = 1; i < conjuncts.length; i++) { + final PsiTypeElement conjunct = conjuncts[i]; + final PsiType conjType = conjunct.getType(); + if (conjType instanceof PsiClassType) { + final PsiClass aClass = ((PsiClassType)conjType).resolve(); + if (aClass != null && !aClass.isInterface()) { + final HighlightInfo errorResult = HighlightInfo.newHighlightInfo(HighlightInfoType.ERROR) + .range(conjunct) + .descriptionAndTooltip(JavaErrorMessages.message("interface.expected")).create(); + QuickFixAction.registerQuickFixAction(errorResult, new FlipIntersectionSidesFix(aClass.getName(), conjList, conjunct, castTypeElement), null); + return errorResult; + } + } + } + } + } else { + return HighlightInfo.newHighlightInfo(HighlightInfoType.ERROR) + .range(expression) + .descriptionAndTooltip("Intersection types in cast are not supported at this language level").create(); + } + } + return null; + } + + static boolean isIntersection(PsiTypeElement castTypeElement, PsiType castType) { + if (castType instanceof PsiIntersectionType) return true; + return PsiTreeUtil.getChildrenOfType(castTypeElement, PsiTypeElement.class) != null; + } + @Nullable static HighlightInfo checkInconvertibleTypeCast(@NotNull PsiTypeCastExpression expression) { - PsiTypeElement castTypeElement = expression.getCastType(); + final PsiTypeElement castTypeElement = expression.getCastType(); if (castTypeElement == null) return null; PsiType castType = castTypeElement.getType(); @@ -306,6 +345,7 @@ public class HighlightUtil extends HighlightUtilBase { return HighlightInfo.newHighlightInfo(HighlightInfoType.ERROR).range(expression).descriptionAndTooltip(message).create(); } + return null; } diff --git a/java/java-analysis-impl/src/com/intellij/codeInsight/daemon/impl/analysis/HighlightVisitorImpl.java b/java/java-analysis-impl/src/com/intellij/codeInsight/daemon/impl/analysis/HighlightVisitorImpl.java index d24c311e4a53..f552a66c25ab 100644 --- a/java/java-analysis-impl/src/com/intellij/codeInsight/daemon/impl/analysis/HighlightVisitorImpl.java +++ b/java/java-analysis-impl/src/com/intellij/codeInsight/daemon/impl/analysis/HighlightVisitorImpl.java @@ -1336,6 +1336,7 @@ public class HighlightVisitorImpl extends JavaElementVisitor implements Highligh public void visitTypeCastExpression(PsiTypeCastExpression typeCast) { super.visitTypeCastExpression(typeCast); try { + if (!myHolder.hasErrorResults()) myHolder.add(HighlightUtil.checkIntersectionInTypeCast(typeCast)); if (!myHolder.hasErrorResults()) myHolder.add(HighlightUtil.checkInconvertibleTypeCast(typeCast)); } catch (IndexNotReadyException ignore) { diff --git a/java/java-analysis-impl/src/com/intellij/codeInsight/daemon/impl/quickfix/FlipIntersectionSidesFix.java b/java/java-analysis-impl/src/com/intellij/codeInsight/daemon/impl/quickfix/FlipIntersectionSidesFix.java new file mode 100644 index 000000000000..8eed99632fda --- /dev/null +++ b/java/java-analysis-impl/src/com/intellij/codeInsight/daemon/impl/quickfix/FlipIntersectionSidesFix.java @@ -0,0 +1,100 @@ +/* + * 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. + */ +package com.intellij.codeInsight.daemon.impl.quickfix; + +import com.intellij.codeInsight.FileModificationService; +import com.intellij.codeInsight.intention.IntentionAction; +import com.intellij.openapi.diagnostic.Logger; +import com.intellij.openapi.editor.Editor; +import com.intellij.openapi.project.Project; +import com.intellij.openapi.util.Comparing; +import com.intellij.openapi.util.text.StringUtil; +import com.intellij.psi.*; +import com.intellij.psi.codeStyle.CodeStyleManager; +import com.intellij.util.Function; +import com.intellij.util.IncorrectOperationException; +import org.jetbrains.annotations.NotNull; + +import java.util.List; + +/** +* User: anna +* Date: 10/31/13 +*/ +public class FlipIntersectionSidesFix implements IntentionAction { + private static final Logger LOG = Logger.getInstance("#" + FlipIntersectionSidesFix.class.getName()); + private final String myClassName; + private final List myConjuncts; + private final PsiTypeElement myConjunct; + private final PsiTypeElement myCastTypeElement; + + public FlipIntersectionSidesFix(String className, + @NotNull List conjList, + PsiTypeElement conjunct, + PsiTypeElement castTypeElement) { + myClassName = className; + myConjuncts = conjList; + LOG.assertTrue(!conjList.isEmpty()); + myConjunct = conjunct; + myCastTypeElement = castTypeElement; + } + + @NotNull + @Override + public String getText() { + return "Move '" + myClassName + "' to the beginning"; + } + + @NotNull + @Override + public String getFamilyName() { + return "Move to front"; + } + + @Override + public boolean isAvailable(@NotNull Project project, Editor editor, PsiFile file) { + for (PsiTypeElement typeElement : myConjuncts) { + if (!typeElement.isValid()) return false; + } + return !Comparing.strEqual(myConjunct.getText(), myConjuncts.get(0).getText()); + } + + @Override + public void invoke(@NotNull Project project, Editor editor, PsiFile file) throws IncorrectOperationException { + if (!FileModificationService.getInstance().prepareFileForWrite(file)) return; + myConjuncts.remove(myConjunct); + myConjuncts.add(0, myConjunct); + + final String intersectionTypeText = StringUtil.join(myConjuncts, new Function() { + @Override + public String fun(PsiTypeElement element) { + return element.getText(); + } + }, " & "); + final PsiElementFactory elementFactory = JavaPsiFacade.getElementFactory(project); + final PsiTypeCastExpression fixedCast = + (PsiTypeCastExpression)elementFactory.createExpressionFromText("(" + intersectionTypeText + ") a", myCastTypeElement); + final PsiTypeElement fixedCastCastType = fixedCast.getCastType(); + LOG.assertTrue(fixedCastCastType != null); + final PsiElement flippedTypeElement = myCastTypeElement.replace(fixedCastCastType); + CodeStyleManager.getInstance(project).reformat(flippedTypeElement); + } + + @Override + public boolean startInWriteAction() { + return true; + } +} diff --git a/java/java-analysis-impl/src/com/intellij/codeInsight/daemon/impl/analysis/QualifyWithThisFix.java b/java/java-analysis-impl/src/com/intellij/codeInsight/daemon/impl/quickfix/QualifyWithThisFix.java similarity index 88% rename from java/java-analysis-impl/src/com/intellij/codeInsight/daemon/impl/analysis/QualifyWithThisFix.java rename to java/java-analysis-impl/src/com/intellij/codeInsight/daemon/impl/quickfix/QualifyWithThisFix.java index cebb50c019ea..beb210744589 100644 --- a/java/java-analysis-impl/src/com/intellij/codeInsight/daemon/impl/analysis/QualifyWithThisFix.java +++ b/java/java-analysis-impl/src/com/intellij/codeInsight/daemon/impl/quickfix/QualifyWithThisFix.java @@ -13,8 +13,9 @@ * See the License for the specific language governing permissions and * limitations under the License. */ -package com.intellij.codeInsight.daemon.impl.analysis; +package com.intellij.codeInsight.daemon.impl.quickfix; +import com.intellij.codeInsight.FileModificationService; import com.intellij.codeInsight.intention.IntentionAction; import com.intellij.openapi.editor.Editor; import com.intellij.openapi.project.Project; @@ -26,7 +27,7 @@ import org.jetbrains.annotations.NotNull; /** * User: anna */ -class QualifyWithThisFix implements IntentionAction { +public class QualifyWithThisFix implements IntentionAction { private final PsiClass myContainingClass; private final PsiElement myExpression; @@ -54,6 +55,7 @@ class QualifyWithThisFix implements IntentionAction { @Override public void invoke(@NotNull Project project, Editor editor, PsiFile file) throws IncorrectOperationException { + if (!FileModificationService.getInstance().prepareFileForWrite(file)) return; final PsiThisExpression thisExpression = RefactoringChangeUtil.createThisExpression(PsiManager.getInstance(project), myContainingClass); ((PsiReferenceExpression)myExpression).setQualifierExpression(thisExpression); diff --git a/java/java-psi-api/src/com/intellij/psi/util/TypeConversionUtil.java b/java/java-psi-api/src/com/intellij/psi/util/TypeConversionUtil.java index 51e2fdf0341f..115b646768c8 100644 --- a/java/java-psi-api/src/com/intellij/psi/util/TypeConversionUtil.java +++ b/java/java-psi-api/src/com/intellij/psi/util/TypeConversionUtil.java @@ -179,7 +179,15 @@ public class TypeConversionUtil { } return false; } - else if (toType instanceof PsiIntersectionType) return false; + else if (toType instanceof PsiIntersectionType) { + if (fromType instanceof PsiClassType && ((PsiClassType)fromType).getLanguageLevel().isAtLeast(LanguageLevel.JDK_1_8)) { + for (PsiType conjunct : ((PsiIntersectionType)toType).getConjuncts()) { + if (!isNarrowingReferenceConversionAllowed(fromType, conjunct)) return false; + } + return true; + } + return false; + } if (fromType instanceof PsiDisjunctionType) { return isNarrowingReferenceConversionAllowed(((PsiDisjunctionType)fromType).getLeastUpperBound(), toType); diff --git a/java/java-psi-impl/src/com/intellij/psi/impl/source/resolve/graphInference/InferenceSession.java b/java/java-psi-impl/src/com/intellij/psi/impl/source/resolve/graphInference/InferenceSession.java index 50df51eaa7a4..de5d470e8e69 100644 --- a/java/java-psi-impl/src/com/intellij/psi/impl/source/resolve/graphInference/InferenceSession.java +++ b/java/java-psi-impl/src/com/intellij/psi/impl/source/resolve/graphInference/InferenceSession.java @@ -445,14 +445,18 @@ public class InferenceSession { } else if (acceptObject || upperBounds.size() > 1 || !upperBounds.get(0).equalsToText(CommonClassNames.JAVA_LANG_OBJECT)) { PsiType glb = null; - for (PsiType upperBound : upperBounds) { - upperBound = acceptBoundsWithRecursiveDependencies(typeParameter, upperBound, substitutor); - if (isProperType(upperBound, false)) { - if (glb == null) { - glb = upperBound; - } - else { - glb = GenericsUtil.getGreatestLowerBound(glb, upperBound); + if (isThrowable(upperBounds)) { + glb = PsiType.getJavaLangRuntimeException(myManager, GlobalSearchScope.allScope(myManager.getProject())); + } else { + for (PsiType upperBound : upperBounds) { + upperBound = acceptBoundsWithRecursiveDependencies(typeParameter, upperBound, substitutor); + if (isProperType(upperBound, false)) { + if (glb == null) { + glb = upperBound; + } + else { + glb = GenericsUtil.getGreatestLowerBound(glb, upperBound); + } } } } @@ -473,6 +477,20 @@ public class InferenceSession { return substitutor; } + private static boolean isThrowable(List upperBounds) { + boolean commonThrowable = false; + for (PsiType upperBound : upperBounds) { + if (upperBound.equalsToText(CommonClassNames.JAVA_LANG_OBJECT)) continue; + if (upperBound.equalsToText(CommonClassNames.JAVA_LANG_EXCEPTION) || + upperBound.equalsToText(CommonClassNames.JAVA_LANG_THROWABLE)) { + commonThrowable = true; + } else { + return false; + } + } + return commonThrowable; + } + private PsiType acceptBoundsWithRecursiveDependencies(PsiTypeParameter typeParameter, PsiType bound, PsiSubstitutor substitutor) { if (!isProperType(bound)) { final PsiSubstitutor subst = PsiUtil.resolveClassInType(bound) != typeParameter ? substitutor.put(typeParameter, null) : substitutor; diff --git a/java/java-tests/testData/codeInsight/daemonCodeAnalyzer/genericsHighlighting8/CastToIntersection.java b/java/java-tests/testData/codeInsight/daemonCodeAnalyzer/genericsHighlighting8/CastToIntersection.java new file mode 100644 index 000000000000..66affa9cde79 --- /dev/null +++ b/java/java-tests/testData/codeInsight/daemonCodeAnalyzer/genericsHighlighting8/CastToIntersection.java @@ -0,0 +1,11 @@ +import java.io.Serializable; + +public class FooBar1 { + { + Object x = null; + Object y = (CharSequence & Serializable) x; + Object y2 = (CharSequence & Integer) x; + Object y3 = (Integer & CharSequence) x; + int y1 = (CharSequence & Serializable) x; + } +} diff --git a/java/java-tests/testData/codeInsight/daemonCodeAnalyzer/quickFix/flipIntersection/after1.java b/java/java-tests/testData/codeInsight/daemonCodeAnalyzer/quickFix/flipIntersection/after1.java new file mode 100644 index 000000000000..f07cf3847bda --- /dev/null +++ b/java/java-tests/testData/codeInsight/daemonCodeAnalyzer/quickFix/flipIntersection/after1.java @@ -0,0 +1,7 @@ +// "Move 'Number' to the beginning" "true" +class C { + { + Object x = null; + Object y2 = (Number & CharSequence) x; + } +} diff --git a/java/java-tests/testData/codeInsight/daemonCodeAnalyzer/quickFix/flipIntersection/before1.java b/java/java-tests/testData/codeInsight/daemonCodeAnalyzer/quickFix/flipIntersection/before1.java new file mode 100644 index 000000000000..38380bc0c315 --- /dev/null +++ b/java/java-tests/testData/codeInsight/daemonCodeAnalyzer/quickFix/flipIntersection/before1.java @@ -0,0 +1,7 @@ +// "Move 'Number' to the beginning" "true" +class C { + { + Object x = null; + Object y2 = (CharSequence & Number) x; + } +} diff --git a/java/java-tests/testData/codeInsight/daemonCodeAnalyzer/quickFix/flipIntersection/before2.java b/java/java-tests/testData/codeInsight/daemonCodeAnalyzer/quickFix/flipIntersection/before2.java new file mode 100644 index 000000000000..34f28f2733f3 --- /dev/null +++ b/java/java-tests/testData/codeInsight/daemonCodeAnalyzer/quickFix/flipIntersection/before2.java @@ -0,0 +1,7 @@ +// "Move 'Number' to the beginning" "false" +class C { + { + Object x = null; + Object y2 = (Number & Number) x; + } +} diff --git a/plugins/groovy/src/org/jetbrains/plugins/groovy/refactoring/introduce/constant/GrInplaceIntroduceConstantPanel.java b/java/java-tests/testSrc/com/intellij/codeInsight/daemon/quickFix/FlipIntersectionTypesTest.java similarity index 56% rename from plugins/groovy/src/org/jetbrains/plugins/groovy/refactoring/introduce/constant/GrInplaceIntroduceConstantPanel.java rename to java/java-tests/testSrc/com/intellij/codeInsight/daemon/quickFix/FlipIntersectionTypesTest.java index 5bd7e5bf48df..ddd8ce49bc9a 100644 --- a/plugins/groovy/src/org/jetbrains/plugins/groovy/refactoring/introduce/constant/GrInplaceIntroduceConstantPanel.java +++ b/java/java-tests/testSrc/com/intellij/codeInsight/daemon/quickFix/FlipIntersectionTypesTest.java @@ -13,24 +13,16 @@ * See the License for the specific language governing permissions and * limitations under the License. */ -package org.jetbrains.plugins.groovy.refactoring.introduce.constant; +package com.intellij.codeInsight.daemon.quickFix; -import com.intellij.ui.components.JBCheckBox; - -import javax.swing.*; - -/** - * Created by Max Medvedev on 8/29/13 - */ -public class GrInplaceIntroduceConstantPanel { - private JBCheckBox myMoveToAnotherClassJBCheckBox; - private JPanel myRootPane; - - public boolean isMoveToAnotherClass() { - return myMoveToAnotherClassJBCheckBox.isSelected(); +public class FlipIntersectionTypesTest extends LightQuickFixTestCase { + public void test() throws Exception { + doAllTests(); } - public JComponent getRootPane() { - return myRootPane; + @Override + protected String getBasePath() { + return "/codeInsight/daemonCodeAnalyzer/quickFix/flipIntersection"; } } + diff --git a/lib/jna-platform.jar b/lib/jna-platform.jar deleted file mode 100644 index 4b3d567c6209..000000000000 Binary files a/lib/jna-platform.jar and /dev/null differ diff --git a/lib/required_for_dist.txt b/lib/required_for_dist.txt index f7e7e48ef0b0..5f749bcff7f8 100644 --- a/lib/required_for_dist.txt +++ b/lib/required_for_dist.txt @@ -21,7 +21,6 @@ jgoodies-forms.jar jgoodies-looks-2.4.2.jar jh.jar jna-utils.jar -jna-platform.jar jna.jar jsch-0.1.50.jar jsr166e.jar diff --git a/platform/analysis-impl/src/com/intellij/psi/impl/source/resolve/reference/impl/providers/FileReference.java b/platform/analysis-impl/src/com/intellij/psi/impl/source/resolve/reference/impl/providers/FileReference.java index 69c2b0cdf326..207b819fff23 100644 --- a/platform/analysis-impl/src/com/intellij/psi/impl/source/resolve/reference/impl/providers/FileReference.java +++ b/platform/analysis-impl/src/com/intellij/psi/impl/source/resolve/reference/impl/providers/FileReference.java @@ -163,40 +163,39 @@ public class FileReference implements PsiFileReference, FileReferenceOwner, PsiP } else { final String decoded = decode(text); - if (decoded != null) { - if (context instanceof PackagePrefixFileSystemItem) { - context = ((PackagePrefixFileSystemItem)context).getDirectory(); + if (context instanceof PackagePrefixFileSystemItem) { + context = ((PackagePrefixFileSystemItem)context).getDirectory(); + } + + if (context instanceof PsiDirectory && caseSensitivityApplies((PsiDirectory)context, caseSensitive)) { + // optimization: do not load all children into VFS + PsiDirectory directory = (PsiDirectory)context; + PsiFileSystemItem child = directory.findFile(decoded); + if (child == null) child = directory.findSubdirectory(decoded); + if (child != null) { + result.add(new PsiElementResolveResult(getOriginalFile(child))); } - - if (context instanceof PsiDirectory && caseSensitivityApplies((PsiDirectory)context, caseSensitive)) { - // optimization: do not load all children into VFS - PsiDirectory directory = (PsiDirectory)context; - PsiFileSystemItem child = directory.findFile(decoded); - if (child == null) child = directory.findSubdirectory(decoded); - if (child != null) { - result.add(new PsiElementResolveResult(getOriginalFile(child))); + } + else { + processVariants(context, new PsiFileSystemItemProcessor() { + @Override + public boolean acceptItem(String name, boolean isDirectory) { + return caseSensitive ? decoded.equals(name) : decoded.compareToIgnoreCase(name) == 0; } - } - else { - processVariants(context, new PsiFileSystemItemProcessor() { - @Override - public boolean acceptItem(String name, boolean isDirectory) { - return caseSensitive ? decoded.equals(name) : decoded.compareToIgnoreCase(name) == 0; - } - @Override - public boolean execute(@NotNull PsiFileSystemItem element) { - result.add(new PsiElementResolveResult(getOriginalFile(element))); - return true; - } - }); - } + @Override + public boolean execute(@NotNull PsiFileSystemItem element) { + result.add(new PsiElementResolveResult(getOriginalFile(element))); + return true; + } + }); } } } } + @NotNull public String getFileNameToCreate() { return decode(getCanonicalText()); } @@ -218,8 +217,8 @@ public class FileReference implements PsiFileReference, FileReferenceOwner, PsiP !myFileReferenceSet.isEndingSlashNotAllowed() && myIndex > 0); } - @Nullable - public String decode(final String text) { + @NotNull + public String decode(@NotNull final String text) { // strip http get parameters String _text = text; if (text.indexOf('?') >= 0) { @@ -228,7 +227,7 @@ public class FileReference implements PsiFileReference, FileReferenceOwner, PsiP if (myFileReferenceSet.isUrlEncoded()) { try { - return new URI(_text).getPath(); + return StringUtil.notNullize(new URI(_text).getPath(), text); } catch (Exception e) { return text; @@ -504,7 +503,7 @@ public class FileReference implements PsiFileReference, FileReferenceOwner, PsiP public String getUnresolvedMessagePattern() { return LangBundle.message("error.cannot.resolve") + " " + (isLast() ? LangBundle.message("terms.file") : LangBundle.message("terms.directory")) - + " '" + StringUtil.escapePattern(StringUtil.notNullize(decode(getCanonicalText()))) + "'"; + + " '" + StringUtil.escapePattern(decode(getCanonicalText())) + "'"; } public final boolean isLast() { diff --git a/platform/lang-impl/src/com/intellij/refactoring/introduce/inplace/OccurrencesChooser.java b/platform/lang-impl/src/com/intellij/refactoring/introduce/inplace/OccurrencesChooser.java index 04a67b29b829..444bc492aa81 100644 --- a/platform/lang-impl/src/com/intellij/refactoring/introduce/inplace/OccurrencesChooser.java +++ b/platform/lang-impl/src/com/intellij/refactoring/introduce/inplace/OccurrencesChooser.java @@ -1,5 +1,5 @@ /* - * Copyright 2000-2010 JetBrains s.r.o. + * 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. @@ -44,7 +44,7 @@ import java.util.List; // This prevents languages with polyadic expressions or sequences // from reusing it, use simpleChooser instead. public abstract class OccurrencesChooser { - public static enum ReplaceChoice { + public enum ReplaceChoice { NO("Replace this occurrence only"), NO_WRITE("Replace all occurrences but write"), ALL("Replace all {0} occurrences"); private final String myDescription; diff --git a/platform/lang-impl/src/com/intellij/refactoring/rename/inplace/InplaceRefactoring.java b/platform/lang-impl/src/com/intellij/refactoring/rename/inplace/InplaceRefactoring.java index 33f23494b341..fc7335595a10 100644 --- a/platform/lang-impl/src/com/intellij/refactoring/rename/inplace/InplaceRefactoring.java +++ b/platform/lang-impl/src/com/intellij/refactoring/rename/inplace/InplaceRefactoring.java @@ -1,5 +1,5 @@ /* - * Copyright 2000-2012 JetBrains s.r.o. + * 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. @@ -30,6 +30,7 @@ import com.intellij.lang.refactoring.NamesValidator; import com.intellij.openapi.Disposable; import com.intellij.openapi.actionSystem.Shortcut; import com.intellij.openapi.application.ApplicationManager; +import com.intellij.openapi.application.Result; import com.intellij.openapi.command.CommandProcessor; import com.intellij.openapi.command.WriteCommandAction; import com.intellij.openapi.command.impl.FinishMarkAction; @@ -327,7 +328,7 @@ public abstract class InplaceRefactoring { new WriteCommandAction(myProject, getCommandName()) { @Override - protected void run(com.intellij.openapi.application.Result result) throws Throwable { + protected void run(Result result) throws Throwable { startTemplate(builder); } }.execute(); diff --git a/platform/util/src/com/intellij/openapi/application/PathManager.java b/platform/util/src/com/intellij/openapi/application/PathManager.java index 501fd0457aaf..2f2418b2ca35 100644 --- a/platform/util/src/com/intellij/openapi/application/PathManager.java +++ b/platform/util/src/com/intellij/openapi/application/PathManager.java @@ -416,9 +416,7 @@ public class PathManager { // helpers private static String getAbsolutePath(String path) { - if (path.startsWith("~/") || path.startsWith("~\\")) { - path = getUserHome() + path.substring(1); - } + path = FileUtil.expandUserHome(path); return new File(path).getAbsolutePath(); } diff --git a/platform/util/src/com/intellij/openapi/util/io/FileUtil.java b/platform/util/src/com/intellij/openapi/util/io/FileUtil.java index cd3668c73250..677587c19876 100644 --- a/platform/util/src/com/intellij/openapi/util/io/FileUtil.java +++ b/platform/util/src/com/intellij/openapi/util/io/FileUtil.java @@ -1213,6 +1213,13 @@ public class FileUtil extends FileUtilRt { return path; } + public static String expandUserHome(String path) { + if (path.startsWith("~/") || path.startsWith("~\\")) { + path = SystemProperties.getUserHome() + path.substring(1); + } + return path; + } + @NotNull public static File[] notNullize(@Nullable File[] files) { return notNullize(files, ArrayUtil.EMPTY_FILE_ARRAY); diff --git a/platform/vcs-log/api/src/com/intellij/vcs/log/ContentRevisionFactory.java b/platform/vcs-log/api/src/com/intellij/vcs/log/ContentRevisionFactory.java new file mode 100644 index 000000000000..dcf81e7b18c6 --- /dev/null +++ b/platform/vcs-log/api/src/com/intellij/vcs/log/ContentRevisionFactory.java @@ -0,0 +1,35 @@ +/* + * 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. + */ +package com.intellij.vcs.log; + +import com.intellij.openapi.vcs.changes.ContentRevision; +import com.intellij.openapi.vfs.VirtualFile; +import org.jetbrains.annotations.NotNull; + +/** + *

This factory is used to create a particular {@link ContentRevision} instance which corresponds to the file and the commit hash.

+ *

Different VCS plugins may use different {@link ContentRevision} implementation, therefore we need to be able + * to retrieve a correct instance for a commit.

+ */ +public abstract class ContentRevisionFactory { + + @NotNull + public abstract ContentRevision createRevision(@NotNull VirtualFile file, @NotNull Hash hash); + + @NotNull + public abstract ContentRevision createRevision(@NotNull VirtualFile root, @NotNull String path, @NotNull Hash hash); + +} diff --git a/platform/vcs-log/api/src/com/intellij/vcs/log/VcsFullCommitDetails.java b/platform/vcs-log/api/src/com/intellij/vcs/log/VcsFullCommitDetails.java index 06a117c6db6e..8c3d87f808ef 100644 --- a/platform/vcs-log/api/src/com/intellij/vcs/log/VcsFullCommitDetails.java +++ b/platform/vcs-log/api/src/com/intellij/vcs/log/VcsFullCommitDetails.java @@ -11,8 +11,8 @@ import java.util.List; *

Full details of a commit: all metadata (commit message, author, committer, etc.) and the changes.

*

These details will be shown in dedicated panels displayed near the log.

*

An instance of this object can be obtained via - * {@link VcsLogObjectsFactory#createFullDetails( - * Hash, List, long, VirtualFile, String, String, String, String, String, String, long, List) VcsLogObjectsFactory#createFullDetails}

+ * {@link VcsLogObjectsFactory#createFullDetails(Hash, List, long, VirtualFile, String, String, String, String, String, String, long, + * List, ContentRevisionFactory) VcsLogObjectsFactory#createFullDetails}

* * @author Kirill Likhodedov */ diff --git a/platform/vcs-log/api/src/com/intellij/vcs/log/VcsLogObjectsFactory.java b/platform/vcs-log/api/src/com/intellij/vcs/log/VcsLogObjectsFactory.java index d4ebe28d2dc8..debb813d261d 100644 --- a/platform/vcs-log/api/src/com/intellij/vcs/log/VcsLogObjectsFactory.java +++ b/platform/vcs-log/api/src/com/intellij/vcs/log/VcsLogObjectsFactory.java @@ -31,7 +31,8 @@ public interface VcsLogObjectsFactory { @NotNull String subject, @NotNull String authorName, @NotNull String authorEmail, @NotNull String message, @NotNull String committerName, - @NotNull String committerEmail, long commitTime, @NotNull List changes); + @NotNull String committerEmail, long commitTime, @NotNull List changes, + @NotNull ContentRevisionFactory contentRevisionFactory); @NotNull VcsUser createUser(@NotNull String name); diff --git a/platform/vcs-log/impl/src/com/intellij/vcs/log/data/LoadingDetails.java b/platform/vcs-log/impl/src/com/intellij/vcs/log/data/LoadingDetails.java index 11db6c8db62b..14f558cfce84 100644 --- a/platform/vcs-log/impl/src/com/intellij/vcs/log/data/LoadingDetails.java +++ b/platform/vcs-log/impl/src/com/intellij/vcs/log/data/LoadingDetails.java @@ -1,11 +1,16 @@ package com.intellij.vcs.log.data; +import com.intellij.openapi.vcs.FilePathImpl; import com.intellij.openapi.vcs.changes.Change; +import com.intellij.openapi.vcs.changes.ContentRevision; +import com.intellij.openapi.vcs.changes.SimpleContentRevision; import com.intellij.openapi.vfs.VirtualFile; +import com.intellij.vcs.log.ContentRevisionFactory; import com.intellij.vcs.log.Hash; import com.intellij.vcs.log.impl.VcsFullCommitDetailsImpl; import org.jetbrains.annotations.NotNull; +import java.io.File; import java.util.Collections; /** @@ -19,7 +24,20 @@ public class LoadingDetails extends VcsFullCommitDetailsImpl { private final long myLoadingTaskIndex; public LoadingDetails(@NotNull Hash hash, long loadingTaskIndex, @NotNull VirtualFile root) { - super(hash, Collections.emptyList(), -1, root, "Loading...", "", "", "", "", "", -1, Collections.emptyList()); + super(hash, Collections.emptyList(), -1, root, "Loading...", "", "", "", "", "", -1, Collections.emptyList(), + new ContentRevisionFactory() { + @NotNull + @Override + public ContentRevision createRevision(@NotNull VirtualFile file, @NotNull Hash hash) { + return new SimpleContentRevision("", new FilePathImpl(file), hash.asString()); + } + + @NotNull + @Override + public ContentRevision createRevision(@NotNull VirtualFile root, @NotNull String path, @NotNull Hash hash) { + return new SimpleContentRevision("", new FilePathImpl(new File(path), false), hash.asString()); + } + }); myLoadingTaskIndex = loadingTaskIndex; } diff --git a/platform/vcs-log/impl/src/com/intellij/vcs/log/impl/VcsFullCommitDetailsImpl.java b/platform/vcs-log/impl/src/com/intellij/vcs/log/impl/VcsFullCommitDetailsImpl.java index daab05f66f42..30c5c374c66f 100644 --- a/platform/vcs-log/impl/src/com/intellij/vcs/log/impl/VcsFullCommitDetailsImpl.java +++ b/platform/vcs-log/impl/src/com/intellij/vcs/log/impl/VcsFullCommitDetailsImpl.java @@ -1,7 +1,12 @@ package com.intellij.vcs.log.impl; +import com.intellij.openapi.vcs.FilePath; import com.intellij.openapi.vcs.changes.Change; +import com.intellij.openapi.vcs.changes.ContentRevision; import com.intellij.openapi.vfs.VirtualFile; +import com.intellij.util.Function; +import com.intellij.util.containers.ContainerUtil; +import com.intellij.vcs.log.ContentRevisionFactory; import com.intellij.vcs.log.Hash; import com.intellij.vcs.log.VcsFullCommitDetails; import org.jetbrains.annotations.NotNull; @@ -21,19 +26,24 @@ public class VcsFullCommitDetailsImpl extends VcsShortCommitDetailsImpl implemen @NotNull private final String myCommitterEmail; private final long myCommitTime; - @NotNull private final Collection myChanges; + @NotNull private final Collection myChanges; public VcsFullCommitDetailsImpl(@NotNull Hash hash, @NotNull List parents, long authorTime, @NotNull VirtualFile root, @NotNull String subject, @NotNull String authorName, @NotNull String authorEmail, @NotNull String message, @NotNull String committerName, @NotNull String committerEmail, long commitTime, - @NotNull List changes) { + @NotNull List changes, @NotNull final ContentRevisionFactory contentRevisionFactory) { super(hash, parents, authorTime, root, subject, authorName); myAuthorEmail = authorEmail; myCommitterName = committerName; myCommitterEmail = committerEmail; myCommitTime = commitTime; myFullMessage = message; - myChanges = changes; + myChanges = ContainerUtil.map(changes, new Function() { + @Override + public LightChange fun(Change change) { + return LightChange.create(contentRevisionFactory, VcsFullCommitDetailsImpl.this, change); + } + }); } @Override @@ -45,7 +55,12 @@ public class VcsFullCommitDetailsImpl extends VcsShortCommitDetailsImpl implemen @Override @NotNull public final Collection getChanges() { - return myChanges; + return ContainerUtil.map(myChanges, new Function() { + @Override + public Change fun(LightChange change) { + return change.toChange(); + } + }); } @Override @@ -70,4 +85,79 @@ public class VcsFullCommitDetailsImpl extends VcsShortCommitDetailsImpl implemen public long getCommitTime() { return myCommitTime; } + + private static class LightChange { + + private ContentRevisionFactory myContentRevisionFactory; + private VcsFullCommitDetails myDetails; + private boolean myModification; + private VirtualFile myBeforeFile; + private VirtualFile myAfterFile; + private String myBeforePath; + private String myAfterPath; + + private static LightChange create(ContentRevisionFactory contentRevisionFactory, VcsFullCommitDetails details, Change change) { + LightChange lc = new LightChange(); + Change.Type type = change.getType(); + lc.myModification = type == Change.Type.MODIFICATION; + lc.myContentRevisionFactory = contentRevisionFactory; + + ContentRevision before = change.getBeforeRevision(); + if (before != null && !lc.myModification) { // don't store the same path twice (for modification store only after path) + FilePath filePath = before.getFile(); + if (filePath.getVirtualFile() == null) { + lc.myBeforePath = filePath.getIOFile().getPath(); + } + else { + lc.myBeforeFile = filePath.getVirtualFile(); + } + } + + ContentRevision after = change.getAfterRevision(); + if (after != null) { + FilePath filePath = after.getFile(); + if (filePath.getVirtualFile() == null) { + lc.myAfterPath = filePath.getIOFile().getPath(); + } + else { + lc.myAfterFile = filePath.getVirtualFile(); + } + } + + lc.myDetails = details; + return lc; + } + + Change toChange() { + List parents = myDetails.getParents(); + Hash parentHash = parents.isEmpty() ? null : parents.get(0); // no parents for the initial commit + + ContentRevision before = null; + if (parentHash != null) { + if (myBeforeFile != null) { + before = myContentRevisionFactory.createRevision(myBeforeFile, parentHash); + } + else if (myBeforePath != null) { + before = myContentRevisionFactory.createRevision(myDetails.getRoot(), myBeforePath, parentHash); + } + } + + ContentRevision after = null; + if (myAfterFile != null) { + after = myContentRevisionFactory.createRevision(myAfterFile, myDetails.getHash()); + if (myModification && parentHash != null) { // we didn't store myBeforeFile/Path to avoid duplicate path + before = myContentRevisionFactory.createRevision(myAfterFile, parentHash); + } + } + else if (myAfterPath != null) { + after = myContentRevisionFactory.createRevision(myDetails.getRoot(), myAfterPath, myDetails.getHash()); + if (myModification && parentHash != null) { + before = myContentRevisionFactory.createRevision(myDetails.getRoot(), myAfterPath, parentHash); + } + } + + return new Change(before, after); + } + + } } diff --git a/platform/vcs-log/impl/src/com/intellij/vcs/log/impl/VcsLogObjectsFactoryImpl.java b/platform/vcs-log/impl/src/com/intellij/vcs/log/impl/VcsLogObjectsFactoryImpl.java index 8b710784a124..6ea9810a3bf0 100644 --- a/platform/vcs-log/impl/src/com/intellij/vcs/log/impl/VcsLogObjectsFactoryImpl.java +++ b/platform/vcs-log/impl/src/com/intellij/vcs/log/impl/VcsLogObjectsFactoryImpl.java @@ -42,9 +42,10 @@ public class VcsLogObjectsFactoryImpl implements VcsLogObjectsFactory { public VcsFullCommitDetails createFullDetails(@NotNull Hash hash, @NotNull List parents, long authorTime, @NotNull VirtualFile root, @NotNull String subject, @NotNull String authorName, @NotNull String authorEmail, @NotNull String message, @NotNull String committerName, - @NotNull String committerEmail, long commitTime, @NotNull List changes) { + @NotNull String committerEmail, long commitTime, @NotNull List changes, + @NotNull ContentRevisionFactory contentRevisionFactory) { return new VcsFullCommitDetailsImpl(hash, parents, authorTime, root, subject, authorName, authorEmail, message, committerName, - committerEmail, commitTime, changes); + committerEmail, commitTime, changes, contentRevisionFactory); } @NotNull diff --git a/plugins/InspectionGadgets/InspectionGadgetsAnalysis/src/com/siyeh/ig/psiutils/ParenthesesUtils.java b/plugins/InspectionGadgets/InspectionGadgetsAnalysis/src/com/siyeh/ig/psiutils/ParenthesesUtils.java index f93f13bcb9a4..bc44d6d44b79 100644 --- a/plugins/InspectionGadgets/InspectionGadgetsAnalysis/src/com/siyeh/ig/psiutils/ParenthesesUtils.java +++ b/plugins/InspectionGadgets/InspectionGadgetsAnalysis/src/com/siyeh/ig/psiutils/ParenthesesUtils.java @@ -518,6 +518,11 @@ public class ParenthesesUtils { } } } + else if (parentExpression instanceof PsiConditionalExpression && expression instanceof PsiConditionalExpression) { + final PsiConditionalExpression conditionalExpression = (PsiConditionalExpression)parentExpression; + final PsiExpression condition = conditionalExpression.getCondition(); + return PsiTreeUtil.isAncestor(condition, expression, true); + } return parentPrecedence < childPrecedence; } } diff --git a/plugins/InspectionGadgets/test/com/siyeh/igtest/style/clarifying_parentheses/UnnecessaryParentheses.java b/plugins/InspectionGadgets/test/com/siyeh/igtest/style/clarifying_parentheses/UnnecessaryParentheses.java index 2f7a798fe0bc..baf32bb6fcbb 100644 --- a/plugins/InspectionGadgets/test/com/siyeh/igtest/style/clarifying_parentheses/UnnecessaryParentheses.java +++ b/plugins/InspectionGadgets/test/com/siyeh/igtest/style/clarifying_parentheses/UnnecessaryParentheses.java @@ -11,4 +11,17 @@ class UnnecessaryParentheses { } return true; } +} +class ConditionalCondition { + + String s; + String t; + + public boolean equals(Object other) { + if (!(other instanceof ConditionalCondition)) return false; + final ConditionalCondition condition = (ConditionalCondition)other; + + + return (s != null ? !s.equals(condition.s) : condition.s != null) ? false : t.equals(condition.t); + } } \ No newline at end of file diff --git a/plugins/IntentionPowerPak/src/com/siyeh/ipp/trivialif/ReplaceIfWithConditionalIntention.java b/plugins/IntentionPowerPak/src/com/siyeh/ipp/trivialif/ReplaceIfWithConditionalIntention.java index b7f95f7bafbe..c30df47d6c35 100644 --- a/plugins/IntentionPowerPak/src/com/siyeh/ipp/trivialif/ReplaceIfWithConditionalIntention.java +++ b/plugins/IntentionPowerPak/src/com/siyeh/ipp/trivialif/ReplaceIfWithConditionalIntention.java @@ -18,7 +18,6 @@ package com.siyeh.ipp.trivialif; import com.intellij.psi.*; import com.intellij.psi.impl.PsiDiamondTypeUtil; import com.intellij.psi.util.PsiTreeUtil; -import com.intellij.util.IncorrectOperationException; import com.siyeh.ig.psiutils.EquivalenceChecker; import com.siyeh.ig.psiutils.ParenthesesUtils; import com.siyeh.ipp.base.Intention; @@ -36,8 +35,7 @@ public class ReplaceIfWithConditionalIntention extends Intention { } @Override - public void processIntention(@NotNull PsiElement element) - throws IncorrectOperationException { + public void processIntention(@NotNull PsiElement element) { final PsiIfStatement ifStatement = (PsiIfStatement)element.getParent(); if (ifStatement == null) { return; @@ -183,9 +181,8 @@ public class ReplaceIfWithConditionalIntention extends Intention { return null; } @NonNls final StringBuilder conditional = new StringBuilder(); - final String conditionText = getExpressionText(condition); - conditional.append(conditionText); - conditional.append('?'); + final String conditionText = getExpressionText(condition, true); + conditional.append(conditionText).append('?'); final PsiType thenType = thenValue.getType(); final PsiType elseType = elseValue.getType(); if (thenType instanceof PsiPrimitiveType && @@ -195,28 +192,24 @@ public class ReplaceIfWithConditionalIntention extends Intention { // prevent unboxing of boxed value to preserve semantics (IDEADEV-36008) final PsiPrimitiveType primitiveType = (PsiPrimitiveType)thenType; conditional.append(primitiveType.getBoxedTypeName()); - conditional.append(".valueOf("); - conditional.append(thenValue.getText()); - conditional.append("):"); - conditional.append(getExpressionText(elseValue)); + conditional.append(".valueOf(").append(thenValue.getText()).append("):"); + conditional.append(getExpressionText(elseValue, false)); } else if (elseType instanceof PsiPrimitiveType && !PsiType.NULL.equals(elseType) && !(thenType instanceof PsiPrimitiveType) && !(requiredType instanceof PsiPrimitiveType)) { // prevent unboxing of boxed value to preserve semantics (IDEADEV-36008) - conditional.append(getExpressionText(thenValue)); + conditional.append(getExpressionText(thenValue, false)); conditional.append(':'); final PsiPrimitiveType primitiveType = (PsiPrimitiveType)elseType; conditional.append(primitiveType.getBoxedTypeName()); - conditional.append(".valueOf("); - conditional.append(elseValue.getText()); - conditional.append(')'); + conditional.append(".valueOf(").append(elseValue.getText()).append(')'); } else { - conditional.append(getExpressionText(thenValue)); + conditional.append(getExpressionText(thenValue, false)); conditional.append(':'); - conditional.append(getExpressionText(elseValue)); + conditional.append(getExpressionText(elseValue, false)); } return conditional.toString(); } @@ -230,9 +223,12 @@ public class ReplaceIfWithConditionalIntention extends Intention { return thenValue; } - private static String getExpressionText(PsiExpression expression) { - if (ParenthesesUtils.getPrecedence(expression) <= - ParenthesesUtils.CONDITIONAL_PRECEDENCE) { + private static String getExpressionText(PsiExpression expression, boolean isCondition) { + final int precedence = ParenthesesUtils.getPrecedence(expression); + if (precedence <= ParenthesesUtils.CONDITIONAL_PRECEDENCE) { + if (isCondition && precedence == ParenthesesUtils.CONDITIONAL_PRECEDENCE) { + return '(' + expression.getText() + ')'; + } return expression.getText(); } else { diff --git a/plugins/IntentionPowerPak/test/com/siyeh/ipp/trivialif/replaceIfWithConditional/ConditionalCondition.java b/plugins/IntentionPowerPak/test/com/siyeh/ipp/trivialif/replaceIfWithConditional/ConditionalCondition.java new file mode 100644 index 000000000000..a1e3377c76bf --- /dev/null +++ b/plugins/IntentionPowerPak/test/com/siyeh/ipp/trivialif/replaceIfWithConditional/ConditionalCondition.java @@ -0,0 +1,16 @@ +package com.siyeh.ipp.trivialif.replaceIfWithConditional; + +class ConditionalCondition { + + String s; + String t; + + public boolean equals(Object other) { + if (!(other instanceof ConditionalCondition)) return false; + final ConditionalCondition condition = (ConditionalCondition)other; + + + if (s != null ? !s.equals(condition.s) : condition.s != null) return false; + return t.equals(condition.t); + } +} \ No newline at end of file diff --git a/plugins/IntentionPowerPak/test/com/siyeh/ipp/trivialif/replaceIfWithConditional/ConditionalCondition_after.java b/plugins/IntentionPowerPak/test/com/siyeh/ipp/trivialif/replaceIfWithConditional/ConditionalCondition_after.java new file mode 100644 index 000000000000..753f032bb9c3 --- /dev/null +++ b/plugins/IntentionPowerPak/test/com/siyeh/ipp/trivialif/replaceIfWithConditional/ConditionalCondition_after.java @@ -0,0 +1,15 @@ +package com.siyeh.ipp.trivialif.replaceIfWithConditional; + +class ConditionalCondition { + + String s; + String t; + + public boolean equals(Object other) { + if (!(other instanceof ConditionalCondition)) return false; + final ConditionalCondition condition = (ConditionalCondition)other; + + + return (s != null ? !s.equals(condition.s) : condition.s != null) ? false : t.equals(condition.t); + } +} \ No newline at end of file diff --git a/plugins/IntentionPowerPak/testSrc/com/siyeh/ipp/trivialif/ReplaceIfWithConditionalIntentionTest.java b/plugins/IntentionPowerPak/testSrc/com/siyeh/ipp/trivialif/ReplaceIfWithConditionalIntentionTest.java index 9cbfe40f0d35..d39fe0f02832 100644 --- a/plugins/IntentionPowerPak/testSrc/com/siyeh/ipp/trivialif/ReplaceIfWithConditionalIntentionTest.java +++ b/plugins/IntentionPowerPak/testSrc/com/siyeh/ipp/trivialif/ReplaceIfWithConditionalIntentionTest.java @@ -1,5 +1,5 @@ /* - * Copyright 2000-2011 JetBrains s.r.o. + * 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. @@ -18,19 +18,15 @@ package com.siyeh.ipp.trivialif; import com.siyeh.IntentionPowerPackBundle; import com.siyeh.ipp.IPPTestCase; +/** + * @see com.siyeh.ipp.trivialif.ReplaceIfWithConditionalIntention + */ public class ReplaceIfWithConditionalIntentionTest extends IPPTestCase { - public void testReturnValueWithDiamonds() { - doTest(); - } - - public void testReplaceableAssignmentsWithDiamonds() { - doTest(); - } - - public void testReplaceableAssignmentsWithDiamondsLeave() { - doTest(); - } + public void testReturnValueWithDiamonds() { doTest(); } + public void testReplaceableAssignmentsWithDiamonds() { doTest(); } + public void testReplaceableAssignmentsWithDiamondsLeave() { doTest(); } + public void testConditionalCondition() { doTest(); } @Override protected String getIntentionName() { diff --git a/plugins/git4idea/src/META-INF/plugin.xml b/plugins/git4idea/src/META-INF/plugin.xml index 430bb42af494..ad09f73663a6 100644 --- a/plugins/git4idea/src/META-INF/plugin.xml +++ b/plugins/git4idea/src/META-INF/plugin.xml @@ -148,6 +148,8 @@ + + parents, long authorTime, @NotNull VirtualFile root, @NotNull String subject, + public GitCommit(final Project project, @NotNull Hash hash, @NotNull List parents, long authorTime, @NotNull VirtualFile root, + @NotNull String subject, @NotNull String authorName, @NotNull String authorEmail, @NotNull String message, @NotNull String committerName, @NotNull String committerEmail, long commitTime, @NotNull List changes) { - super(hash, parents, authorTime, root, subject, authorName, authorEmail, message, committerName, committerEmail, commitTime, changes); + super(hash, parents, authorTime, root, subject, authorName, authorEmail, message, committerName, committerEmail, commitTime, changes, + GitContentRevisionFactory.getInstance(project)); + } } diff --git a/plugins/git4idea/src/git4idea/GitContentRevision.java b/plugins/git4idea/src/git4idea/GitContentRevision.java index 5ce16c9ea1fb..c440b2606d79 100644 --- a/plugins/git4idea/src/git4idea/GitContentRevision.java +++ b/plugins/git4idea/src/git4idea/GitContentRevision.java @@ -199,12 +199,12 @@ public class GitContentRevision implements ContentRevision { } public static ContentRevision createRevision(@NotNull final VirtualFile file, @Nullable final VcsRevisionNumber revisionNumber, - @NotNull final Project project) throws VcsException { + @NotNull final Project project) { return createRevision(file, revisionNumber, project, null); } public static ContentRevision createRevision(@NotNull final VirtualFile file, @Nullable final VcsRevisionNumber revisionNumber, - @NotNull final Project project, @Nullable final Charset charset) throws VcsException { + @NotNull final Project project, @Nullable final Charset charset) { final FilePathImpl filePath = new FilePathImpl(file); return createRevision(filePath, revisionNumber, project, charset); } diff --git a/plugins/git4idea/src/git4idea/cherrypick/GitCherryPickAction.java b/plugins/git4idea/src/git4idea/cherrypick/GitCherryPickAction.java index 3d938889da1c..ffa399e93299 100644 --- a/plugins/git4idea/src/git4idea/cherrypick/GitCherryPickAction.java +++ b/plugins/git4idea/src/git4idea/cherrypick/GitCherryPickAction.java @@ -39,6 +39,7 @@ import git4idea.config.GitVcsSettings; import git4idea.history.browser.GitHeavyCommit; import git4idea.history.wholeTree.AbstractHash; import git4idea.history.wholeTree.GitCommitDetailsProvider; +import git4idea.log.GitContentRevisionFactory; import git4idea.repo.GitRepository; import icons.Git4ideaIcons; import org.jetbrains.annotations.NotNull; @@ -166,14 +167,14 @@ public class GitCherryPickAction extends DumbAwareAction { // TODO remove after removing the old Vcs Log implementation @Nullable private List getSelectedCommits(AnActionEvent e) { - List commits = e.getData(GitVcs.SELECTED_COMMITS); - if (commits != null) { - return convertHeavyCommitToFullDetails(commits); - } final Project project = e.getProject(); if (project == null) { return null; } + List commits = e.getData(GitVcs.SELECTED_COMMITS); + if (commits != null) { + return convertHeavyCommitToFullDetails(commits, project); + } final VcsLog log = getVcsLog(project); if (log == null) { return null; @@ -197,7 +198,7 @@ public class GitCherryPickAction extends DumbAwareAction { return selectedDetails; } - private static List convertHeavyCommitToFullDetails(List commits) { + private static List convertHeavyCommitToFullDetails(List commits, final Project project) { return ContainerUtil.map(commits, new Function() { @Override public VcsFullCommitDetails fun(GitHeavyCommit commit) { @@ -211,7 +212,7 @@ public class GitCherryPickAction extends DumbAwareAction { return factory.createFullDetails( factory.createHash(commit.getHash().getValue()), parents, commit.getAuthorTime(), commit.getRoot(), commit.getSubject(), commit.getAuthor(), commit.getAuthorEmail(), commit.getDescription(), commit.getCommitter(), commit.getCommitterEmail(), - commit.getDate().getTime(), commit.getChanges() + commit.getDate().getTime(), commit.getChanges(), GitContentRevisionFactory.getInstance(project) ); } }); diff --git a/plugins/git4idea/src/git4idea/commands/GitHandler.java b/plugins/git4idea/src/git4idea/commands/GitHandler.java index 0816bb93db0e..adbb64de75da 100644 --- a/plugins/git4idea/src/git4idea/commands/GitHandler.java +++ b/plugins/git4idea/src/git4idea/commands/GitHandler.java @@ -458,6 +458,7 @@ public abstract class GitHandler { startHandlingStreams(); } catch (Throwable t) { + LOG.error(t); cleanupEnv(); myListeners.getMulticaster().startFailed(t); } diff --git a/plugins/git4idea/src/git4idea/history/GitHistoryUtils.java b/plugins/git4idea/src/git4idea/history/GitHistoryUtils.java index f7b4ec8ca3f8..79f7223bc1ea 100644 --- a/plugins/git4idea/src/git4idea/history/GitHistoryUtils.java +++ b/plugins/git4idea/src/git4idea/history/GitHistoryUtils.java @@ -711,7 +711,7 @@ public class GitHistoryUtils { return HashImpl.build(hash); } }); - return new GitCommit(HashImpl.build(record.getHash()), parents, record.getAuthorTimeStamp(), root, record.getSubject(), + return new GitCommit(project, HashImpl.build(record.getHash()), parents, record.getAuthorTimeStamp(), root, record.getSubject(), record.getAuthorName(), record.getAuthorEmail(), record.getFullMessage(), record.getCommitterName(), record.getCommitterEmail(), record.getLongTimeStamp(), record.parseChanges(project, root)); diff --git a/plugins/git4idea/src/git4idea/log/GitContentRevisionFactory.java b/plugins/git4idea/src/git4idea/log/GitContentRevisionFactory.java new file mode 100644 index 000000000000..054f3987e809 --- /dev/null +++ b/plugins/git4idea/src/git4idea/log/GitContentRevisionFactory.java @@ -0,0 +1,57 @@ +/* + * 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. + */ +package git4idea.log; + +import com.intellij.openapi.components.ServiceManager; +import com.intellij.openapi.project.Project; +import com.intellij.openapi.vcs.FilePathImpl; +import com.intellij.openapi.vcs.changes.ContentRevision; +import com.intellij.openapi.vfs.VirtualFile; +import com.intellij.vcs.log.ContentRevisionFactory; +import com.intellij.vcs.log.Hash; +import git4idea.GitContentRevision; +import git4idea.GitRevisionNumber; +import org.jetbrains.annotations.NotNull; + +import java.io.File; + +public class GitContentRevisionFactory extends ContentRevisionFactory { + + @NotNull private final Project myProject; + + @SuppressWarnings("UnusedDeclaration") + private GitContentRevisionFactory(@NotNull Project project) { + myProject = project; + } + + public static ContentRevisionFactory getInstance(Project project) { + return ServiceManager.getService(project, GitContentRevisionFactory.class); + } + + @NotNull + @Override + public ContentRevision createRevision(@NotNull VirtualFile file, @NotNull Hash hash) { + return GitContentRevision.createRevision(file, new GitRevisionNumber(hash.asString()), myProject); + } + + @NotNull + @Override + public ContentRevision createRevision(@NotNull VirtualFile root, @NotNull String path, @NotNull Hash hash) { + return GitContentRevision.createRevision(new FilePathImpl(new File(path), false), + new GitRevisionNumber(hash.asString()), myProject, null); + } + +} diff --git a/plugins/git4idea/test-stepdefs/git4idea/GitCherryPickStepdefs.java b/plugins/git4idea/test-stepdefs/git4idea/GitCherryPickStepdefs.java index e062a67ee4d6..5aa6c58a9aee 100644 --- a/plugins/git4idea/test-stepdefs/git4idea/GitCherryPickStepdefs.java +++ b/plugins/git4idea/test-stepdefs/git4idea/GitCherryPickStepdefs.java @@ -39,6 +39,7 @@ import cucumber.annotation.en.Then; import cucumber.annotation.en.When; import git4idea.cherrypick.GitCherryPicker; import git4idea.config.GitVersionSpecialty; +import git4idea.log.GitContentRevisionFactory; import java.util.*; @@ -263,7 +264,7 @@ public class GitCherryPickStepdefs { changes.add(new Change(null, new MockContentRevision(new FilePathImpl(new MockVirtualFile("name")), VcsRevisionNumber.NULL))); return ServiceManager.getService(VcsLogObjectsFactory.class).createFullDetails( HashImpl.build(hash), Collections.emptyList(), 0, NullVirtualFile.INSTANCE, message, "John Smith", "john@mail.com", message, - "John Smith", "john@mail.com", 0, changes); + "John Smith", "john@mail.com", 0, changes, GitContentRevisionFactory.getInstance(myProject)); } } \ No newline at end of file diff --git a/plugins/gradle/src/org/jetbrains/plugins/gradle/integrations/maven/ImportMavenRepositoriesTask.java b/plugins/gradle/src/org/jetbrains/plugins/gradle/integrations/maven/ImportMavenRepositoriesTask.java index 25c4faa5e170..031914507419 100644 --- a/plugins/gradle/src/org/jetbrains/plugins/gradle/integrations/maven/ImportMavenRepositoriesTask.java +++ b/plugins/gradle/src/org/jetbrains/plugins/gradle/integrations/maven/ImportMavenRepositoriesTask.java @@ -204,7 +204,7 @@ public class ImportMavenRepositoriesTask implements Runnable { if (uri.getScheme() != null && StringUtil.startsWith(uri.getScheme(), "http")) return uri; } } - catch (URISyntaxException e) { + catch (URISyntaxException ignored) { // ignore it } @@ -219,7 +219,7 @@ public class ImportMavenRepositoriesTask implements Runnable { if (uri.getScheme() != null && StringUtil.startsWith("http", uri.getScheme())) return uri; } } - catch (URISyntaxException e) { + catch (URISyntaxException ignored) { // ignore it } diff --git a/plugins/gradle/src/org/jetbrains/plugins/gradle/integrations/maven/codeInsight/actions/AddGradleDslDependencyActionHandler.java b/plugins/gradle/src/org/jetbrains/plugins/gradle/integrations/maven/codeInsight/actions/AddGradleDslDependencyActionHandler.java index 02dae6b24ac8..09e96cc39be4 100644 --- a/plugins/gradle/src/org/jetbrains/plugins/gradle/integrations/maven/codeInsight/actions/AddGradleDslDependencyActionHandler.java +++ b/plugins/gradle/src/org/jetbrains/plugins/gradle/integrations/maven/codeInsight/actions/AddGradleDslDependencyActionHandler.java @@ -19,11 +19,9 @@ import com.intellij.codeInsight.CodeInsightActionHandler; import com.intellij.codeInsight.CodeInsightUtilBase; import com.intellij.openapi.application.ApplicationManager; import com.intellij.openapi.command.WriteCommandAction; -import com.intellij.openapi.editor.Document; import com.intellij.openapi.editor.Editor; import com.intellij.openapi.project.Project; import com.intellij.openapi.util.Condition; -import com.intellij.psi.PsiDocumentManager; import com.intellij.psi.PsiFile; import com.intellij.psi.util.PsiTreeUtil; import com.intellij.util.ArrayUtil; @@ -91,12 +89,6 @@ class AddGradleDslDependencyActionHandler implements CodeInsightActionHandler { } } } - - PsiDocumentManager documentManager = PsiDocumentManager.getInstance(project); - Document document = documentManager.getDocument(file); - if (document != null) { - documentManager.commitDocument(document); - } } }.execute(); } diff --git a/plugins/groovy/src/org/jetbrains/plugins/groovy/refactoring/introduce/GrAbstractInplaceIntroducer.java b/plugins/groovy/src/org/jetbrains/plugins/groovy/refactoring/introduce/GrAbstractInplaceIntroducer.java new file mode 100644 index 000000000000..32004067b0ca --- /dev/null +++ b/plugins/groovy/src/org/jetbrains/plugins/groovy/refactoring/introduce/GrAbstractInplaceIntroducer.java @@ -0,0 +1,277 @@ +/* + * 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. + */ +package org.jetbrains.plugins.groovy.refactoring.introduce; + +import com.intellij.openapi.application.ApplicationManager; +import com.intellij.openapi.editor.Editor; +import com.intellij.openapi.editor.RangeMarker; +import com.intellij.openapi.project.Project; +import com.intellij.openapi.util.Comparing; +import com.intellij.openapi.util.Computable; +import com.intellij.psi.*; +import com.intellij.psi.util.PsiTreeUtil; +import com.intellij.psi.util.PsiUtilCore; +import com.intellij.refactoring.introduce.inplace.AbstractInplaceIntroducer; +import com.intellij.refactoring.introduce.inplace.OccurrencesChooser; +import com.intellij.util.Function; +import com.intellij.util.IncorrectOperationException; +import com.intellij.util.containers.ContainerUtil; +import org.jetbrains.annotations.NotNull; +import org.jetbrains.annotations.Nullable; +import org.jetbrains.plugins.groovy.GroovyFileType; +import org.jetbrains.plugins.groovy.lang.lexer.GroovyTokenTypes; +import org.jetbrains.plugins.groovy.lang.psi.GroovyPsiElementFactory; +import org.jetbrains.plugins.groovy.lang.psi.api.statements.GrVariable; +import org.jetbrains.plugins.groovy.lang.psi.api.statements.expressions.GrExpression; +import org.jetbrains.plugins.groovy.lang.psi.api.statements.expressions.GrMethodCall; +import org.jetbrains.plugins.groovy.lang.psi.api.statements.expressions.GrNewExpression; +import org.jetbrains.plugins.groovy.lang.psi.api.statements.expressions.GrReferenceExpression; +import org.jetbrains.plugins.groovy.lang.psi.api.statements.expressions.path.GrMethodCallExpression; +import org.jetbrains.plugins.groovy.refactoring.GroovyRefactoringUtil; + +import java.util.List; + + +/** + * Created by Max Medvedev on 10/28/13 + */ +public abstract class GrAbstractInplaceIntroducer extends AbstractInplaceIntroducer { + + private SmartTypePointer myTypePointer; + private OccurrencesChooser.ReplaceChoice myReplaceChoice; + + private RangeMarker myVarMarker; + private final PsiFile myFile; + + private final GrIntroduceContext myContext; + + public GrAbstractInplaceIntroducer(String title, + OccurrencesChooser.ReplaceChoice replaceChoice, + GrIntroduceContext context) { + super(context.getProject(), context.getEditor(), context.getExpression(), context.getVar(), context.getOccurrences(), title, GroovyFileType.GROOVY_FILE_TYPE); + myReplaceChoice = replaceChoice; + myContext = context; + myFile = context.getPlace().getContainingFile(); + } + + public GrIntroduceContext getContext() { + return myContext; + } + + @Override + public void setReplaceAllOccurrences(boolean allOccurrences) { + throw new IncorrectOperationException("don't invoke this method"); + } + + @Override + public GrExpression restoreExpression(PsiFile containingFile, GrVariable variable, RangeMarker marker, String exprText) { + if (exprText == null) return null; + if (variable == null || !variable.isValid()) return null; + final PsiElement refVariableElement = containingFile.findElementAt(marker.getStartOffset()); + final PsiElement refVariableElementParent = refVariableElement != null ? refVariableElement.getParent() : null; + GrExpression expression = + refVariableElementParent instanceof GrNewExpression && refVariableElement.getNode().getElementType() == GroovyTokenTypes.kNEW + ? (GrNewExpression)refVariableElementParent + : PsiTreeUtil.getParentOfType(refVariableElement, GrReferenceExpression.class); + if (expression instanceof GrReferenceExpression && !(expression.getParent() instanceof GrMethodCall)) { + final String referenceName = ((GrReferenceExpression)expression).getReferenceName(); + if (((GrReferenceExpression)expression).resolve() == variable || + Comparing.strEqual(variable.getName(), referenceName) || + Comparing.strEqual(exprText, referenceName)) { + return (GrExpression)expression + .replace(GroovyPsiElementFactory.getInstance(myProject).createExpressionFromText(exprText, variable)); + } + } + if (expression == null) { + expression = PsiTreeUtil.getParentOfType(refVariableElement, GrExpression.class); + } + while (expression instanceof GrReferenceExpression) { + final PsiElement parent = expression.getParent(); + if (parent instanceof GrMethodCallExpression) { + if (parent.getText().equals(exprText)) return (GrExpression)parent; + } + if (parent instanceof GrExpression) { + expression = (GrExpression)parent; + if (expression.getText().equals(exprText)) { + return expression; + } + } + else { + return null; + } + } + if (expression != null && expression.isValid() && expression.getText().equals(exprText)) { + return expression; + } + + if (refVariableElementParent instanceof GrExpression && refVariableElementParent.getText().equals(exprText)) { + return (GrExpression)refVariableElementParent; + } + + return null; + } + + @Override + protected void updateTitle(@Nullable GrVariable variable, String value) { + if (variable == null) { + super.updateTitle(variable, value); + } + else { + final String variableText = variable.getParent().getText(); + final PsiElement identifier = variable.getNameIdentifierGroovy(); + final int startOffsetInParent = identifier.getStartOffsetInParent() + variable.getStartOffsetInParent(); + setPreviewText( + variableText.substring(0, startOffsetInParent) + value + variableText.substring(startOffsetInParent + identifier.getTextLength())); + revalidate(); + } + } + + @Override + protected void updateTitle(@Nullable GrVariable variable) { + if (variable == null) return; + setPreviewText(variable.getParent().getText()); + revalidate(); + } + + @Nullable + @Override + protected PsiElement getNameIdentifier() { + return ((GrVariable)myElementToRename).getNameIdentifierGroovy(); + } + + @Override + protected GrVariable getVariable() { + if (myVarMarker == null) return null; + + int offset = myVarMarker.getStartOffset(); + PsiElement at = myFile.findElementAt(offset); + GrVariable var = PsiTreeUtil.getParentOfType(at, GrVariable.class); + return var; + } + + @Override + protected void performIntroduce() { + final List markers = getOccurrenceMarkers(); + GrIntroduceContext context = new GrIntroduceContext() { + @NotNull + @Override + public Project getProject() { + return myProject; + } + + @Override + public Editor getEditor() { + return myEditor; + } + + @Nullable + @Override + public GrExpression getExpression() { + return (GrExpression)getExpr(); + } + + @Nullable + @Override + public GrVariable getVar() { + return getLocalVariable(); + } + + @Nullable + @Override + public StringPartInfo getStringPart() { + return null; + } + + @NotNull + @Override + public PsiElement[] getOccurrences() { + List result = ContainerUtil.map(markers, new Function() { + @Override + public PsiElement fun(RangeMarker marker) { + return GroovyRefactoringUtil.findElementInRange(myFile, marker.getStartOffset(), marker.getEndOffset(), GrExpression.class); + } + }); + return PsiUtilCore.toPsiElementArray(result); + } + + @Override + public PsiElement getScope() { + return myScope; + } + + @NotNull + @Override + public PsiElement getPlace() { + GrExpression expression = getExpression(); + return expression != null ? expression : getLocalVariable(); + } + }; + runRefactoring(context, getSettings(), true); + } + + @Nullable + @Override + protected GrVariable createFieldToStartTemplateOn(boolean replaceAll, String[] names) { + + final Settings settings = getInitialSettingsForInplace(myContext, myReplaceChoice, names); + if (settings == null) return null; + + SmartPsiElementPointer pointer = ApplicationManager.getApplication().runWriteAction(new Computable>() { + @Override + public SmartPsiElementPointer compute() { + GrVariable var = runRefactoring(myContext, settings, false); + return var != null ? SmartPointerManager.getInstance(myProject).createSmartPsiElementPointer(var) : null; + } + }); + + if (pointer != null) { + GrVariable var = pointer.getElement(); + if (var != null) { + myVarMarker = myContext.getEditor().getDocument().createRangeMarker(var.getTextRange()); + } + return var; + } + else { + return null; + } + } + + protected abstract GrVariable runRefactoring(GrIntroduceContext context, Settings settings, boolean processUsages); + + @Nullable + protected abstract Settings getInitialSettingsForInplace(@NotNull GrIntroduceContext context, + @NotNull OccurrencesChooser.ReplaceChoice choice, + String[] names); + + @Override + public boolean isReplaceAllOccurrences() { + return myReplaceChoice != OccurrencesChooser.ReplaceChoice.NO || myContext.getOccurrences().length == 1; + } + + protected abstract Settings getSettings(); + + @Override + protected void restoreState(GrVariable psiField) { + PsiType declaredType = psiField.getDeclaredType(); + myTypePointer = declaredType != null ? SmartTypePointerManager.getInstance(myProject).createSmartTypePointer(declaredType) : null; + super.restoreState(psiField); + } + + @Nullable + protected PsiType getSelectedType() { + return myTypePointer != null ? myTypePointer.getType() : null; + } +} diff --git a/plugins/groovy/src/org/jetbrains/plugins/groovy/refactoring/introduce/GrIntroduceHandlerBase.java b/plugins/groovy/src/org/jetbrains/plugins/groovy/refactoring/introduce/GrIntroduceHandlerBase.java index ec3aefa1c717..6e147414b669 100644 --- a/plugins/groovy/src/org/jetbrains/plugins/groovy/refactoring/introduce/GrIntroduceHandlerBase.java +++ b/plugins/groovy/src/org/jetbrains/plugins/groovy/refactoring/introduce/GrIntroduceHandlerBase.java @@ -21,7 +21,6 @@ import com.intellij.lang.LanguageRefactoringSupport; import com.intellij.lang.refactoring.RefactoringSupportProvider; import com.intellij.openapi.actionSystem.DataContext; import com.intellij.openapi.application.ApplicationManager; -import com.intellij.openapi.command.CommandProcessor; import com.intellij.openapi.diagnostic.Logger; import com.intellij.openapi.editor.Document; import com.intellij.openapi.editor.Editor; @@ -32,7 +31,6 @@ import com.intellij.openapi.editor.colors.EditorColorsManager; import com.intellij.openapi.editor.markup.RangeHighlighter; import com.intellij.openapi.editor.markup.TextAttributes; import com.intellij.openapi.project.Project; -import com.intellij.openapi.util.Computable; import com.intellij.openapi.util.Pass; import com.intellij.openapi.util.TextRange; import com.intellij.openapi.wm.WindowManager; @@ -77,7 +75,7 @@ import java.util.*; import static org.jetbrains.plugins.groovy.lang.psi.util.PsiUtil.skipParentheses; /** - * @author Maxim.Medvedev + * Created by Max Medvedev on 10/29/13 */ public abstract class GrIntroduceHandlerBase implements RefactoringActionHandler { private static final Logger LOG = Logger.getInstance(GrIntroduceHandlerBase.class); @@ -144,15 +142,8 @@ public abstract class GrIntroduceHandlerBase occurrenceMarkers, - RangeMarker varRangeMarker, - @Nullable RangeMarker expressionRangeMarker, - @Nullable RangeMarker stringPartRangeMarker); - - protected abstract Settings getSettingsForInplace(GrIntroduceContext context, OccurrencesChooser.ReplaceChoice choice); + protected abstract GrAbstractInplaceIntroducer getIntroducer(@NotNull GrIntroduceContext context, + OccurrencesChooser.ReplaceChoice choice); public static Map> fillChoice(GrIntroduceContext context) { HashMap> map = ContainerUtil.newLinkedHashMap(); @@ -296,7 +287,8 @@ public abstract class GrIntroduceHandlerBase callback, Editor editor); public GrIntroduceContext getContext(@NotNull Project project, - @NotNull Editor editor, - @Nullable GrExpression expression, - @Nullable GrVariable variable, - @Nullable StringPartInfo stringPart, - @NotNull PsiElement scope) { + @NotNull Editor editor, + @Nullable GrExpression expression, + @Nullable GrVariable variable, + @Nullable StringPartInfo stringPart, + @NotNull PsiElement scope) { if (variable != null) { final List list = Collections.synchronizedList(new ArrayList()); ReferencesSearch.search(variable, new LocalSearchScope(scope)).forEach(new Processor() { @@ -348,48 +340,6 @@ public abstract class GrIntroduceHandlerBase callback = new Pass() { - @Override - public void pass(final OccurrencesChooser.ReplaceChoice choice) { - - final Settings settings = isInplace ? getSettingsForInplace(context, choice) : showDialog(context); - if (settings == null) return; - - CommandProcessor.getInstance().executeCommand(project, new Runnable() { - public void run() { - List occurrences = ContainerUtil.newArrayList(); - Document document = editor.getDocument(); - for (PsiElement element : context.getOccurrences()) { - occurrences.add(createRange(document, element)); - } - RangeMarker expressionRangeMarker = createRange(document, context.getExpression()); - RangeMarker stringPartRangeMarker = createRange(document, context.getStringPart()); - RangeMarker varRangeMarker = createRange(document, context.getVar()); - - SmartPsiElementPointer pointer = - ApplicationManager.getApplication().runWriteAction(new Computable>() { - @Override - public SmartPsiElementPointer compute() { - GrVariable var = runRefactoring(context, settings); - return var != null - ? SmartPointerManager.getInstance(context.getProject()).createSmartPsiElementPointer(var) - : null; - } - }); - GrVariable var = pointer != null ? pointer.getElement() : null; - - if (isInplace && var != null) { - GrInplaceIntroducer introducer = getIntroducer(var, context, settings, occurrences, varRangeMarker, expressionRangeMarker, stringPartRangeMarker); - LinkedHashSet suggestions = introducer.suggestNames(context); - PsiDocumentManager.getInstance(project).doPostponedOperationsAndUnblockDocument(editor.getDocument()); - introducer.performInplaceRefactoring(suggestions); - } - } - }, getRefactoringName(), getRefactoringName()); - } - }; - if (isInplace(context.getEditor(), context.getPlace())) { Map> occurrencesMap = fillChoice(context); new OccurrencesChooser(editor) { @@ -405,17 +355,28 @@ public abstract class GrIntroduceHandlerBase() { + @Override + public void pass(final OccurrencesChooser.ReplaceChoice choice) { + getIntroducer(context, choice).startInplaceIntroduceTemplate(); + } + }, occurrencesMap); } else { - callback.pass(null); + final Settings settings = showDialog(context); + if (settings == null) return false; + ApplicationManager.getApplication().runWriteAction(new Runnable() { + @Override + public void run() { + runRefactoring(context, settings); + } + }); } return true; } catch (GrRefactoringError e) { - CommonRefactoringUtil - .showErrorHint(project, editor, RefactoringBundle.getCannotRefactorMessage(e.getMessage()), getRefactoringName(), getHelpID()); + CommonRefactoringUtil.showErrorHint(project, editor, RefactoringBundle.getCannotRefactorMessage(e.getMessage()), getRefactoringName(), getHelpID()); return false; } } diff --git a/plugins/groovy/src/org/jetbrains/plugins/groovy/refactoring/introduce/constant/GrInplaceConstantIntroducer.java b/plugins/groovy/src/org/jetbrains/plugins/groovy/refactoring/introduce/constant/GrInplaceConstantIntroducer.java index ff5a264036fb..df6623b42a88 100644 --- a/plugins/groovy/src/org/jetbrains/plugins/groovy/refactoring/introduce/constant/GrInplaceConstantIntroducer.java +++ b/plugins/groovy/src/org/jetbrains/plugins/groovy/refactoring/introduce/constant/GrInplaceConstantIntroducer.java @@ -15,127 +15,118 @@ */ package org.jetbrains.plugins.groovy.refactoring.introduce.constant; -import com.intellij.openapi.editor.RangeMarker; import com.intellij.psi.*; -import com.intellij.psi.util.PsiTreeUtil; -import com.intellij.psi.util.PsiUtilCore; -import com.intellij.util.containers.ContainerUtil; +import com.intellij.refactoring.introduce.inplace.OccurrencesChooser; +import com.intellij.refactoring.introduceField.IntroduceConstantHandler; +import com.intellij.ui.components.JBCheckBox; import org.jetbrains.annotations.NotNull; import org.jetbrains.annotations.Nullable; +import org.jetbrains.plugins.groovy.lang.psi.GroovyFileBase; import org.jetbrains.plugins.groovy.lang.psi.api.statements.GrVariable; -import org.jetbrains.plugins.groovy.lang.psi.api.statements.GrVariableDeclaration; -import org.jetbrains.plugins.groovy.lang.psi.api.statements.expressions.GrBinaryExpression; import org.jetbrains.plugins.groovy.lang.psi.api.statements.expressions.GrExpression; -import org.jetbrains.plugins.groovy.lang.psi.api.statements.expressions.GrReferenceExpression; import org.jetbrains.plugins.groovy.refactoring.GroovyNameSuggestionUtil; -import org.jetbrains.plugins.groovy.refactoring.introduce.GrInplaceIntroducer; +import org.jetbrains.plugins.groovy.refactoring.introduce.GrAbstractInplaceIntroducer; import org.jetbrains.plugins.groovy.refactoring.introduce.GrIntroduceContext; -import org.jetbrains.plugins.groovy.refactoring.introduce.GrIntroduceContextImpl; +import org.jetbrains.plugins.groovy.refactoring.introduce.StringPartInfo; import org.jetbrains.plugins.groovy.refactoring.introduce.field.GroovyInplaceFieldValidator; import javax.swing.*; -import java.util.LinkedHashSet; -import java.util.List; /** * Created by Max Medvedev on 8/29/13 */ -public class GrInplaceConstantIntroducer extends GrInplaceIntroducer { +public class GrInplaceConstantIntroducer extends GrAbstractInplaceIntroducer { private final GrInplaceIntroduceConstantPanel myPanel; private final GrIntroduceContext myContext; - private final RangeMarker myExpressionRangeMarker; - private final RangeMarker myStringPartRangeMarker; - private final boolean myReplaceAll; + private String[] mySuggestedNames; - public GrInplaceConstantIntroducer(GrVariable var, - GrIntroduceContext context, - List occurrences, - boolean replaceAllOccurrences, - RangeMarker expressionRangeMarker, - RangeMarker stringPartRangeMarker) { - super(var, context.getEditor(), context.getProject(), GrIntroduceConstantHandler.REFACTORING_NAME, occurrences, context.getPlace()); + public GrInplaceConstantIntroducer(GrIntroduceContext context, OccurrencesChooser.ReplaceChoice choice) { + super(IntroduceConstantHandler.REFACTORING_NAME, choice, context); myContext = context; - myReplaceAll = replaceAllOccurrences; - myExpressionRangeMarker = expressionRangeMarker; - myStringPartRangeMarker = stringPartRangeMarker; myPanel = new GrInplaceIntroduceConstantPanel(); + + mySuggestedNames = GroovyNameSuggestionUtil.suggestVariableNames(context.getExpression(), new GroovyInplaceFieldValidator(context), + true); } @Override - public LinkedHashSet suggestNames(GrIntroduceContext context) { - return ContainerUtil.newLinkedHashSet(GroovyNameSuggestionUtil.suggestVariableNames( - context.getExpression(), - new GroovyInplaceFieldValidator(context), - getVariable().hasModifierProperty(PsiModifier.STATIC)) - ); + protected String getActionName() { + return null; } @Override - protected void moveOffsetAfter(boolean success) { - if (success) { - final GrVariable field = getVariable(); - assert field != null; - GrIntroduceConstantProcessor processor = new GrIntroduceConstantProcessor(generateContext(), generateSettings()) { - @Override - protected GrVariableDeclaration addDeclaration(PsiClass targetClass, GrVariableDeclaration declaration) { - return (GrVariableDeclaration)field.getParent(); - } - - @Override - protected boolean checkErrors(@NotNull PsiClass targetClass) { - return false; - } - }; - processor.run(); - } - super.moveOffsetAfter(success); - } - - private GrIntroduceContext generateContext() { - final List occurrenceMarkers = getOccurrenceMarkers(); - - List occurrences = ContainerUtil.newArrayList(); - for (RangeMarker marker : occurrenceMarkers) { - ContainerUtil.addIfNotNull(occurrences, findExpression(marker)); - } - - GrExpression expr = null; - if (myExpressionRangeMarker != null) expr = findExpression(myExpressionRangeMarker); - if (myStringPartRangeMarker != null) { - expr = findExpressionFromStringPartMarker(myStringPartRangeMarker); - occurrences.add(expr); - } - - return new GrIntroduceContextImpl(myContext.getProject(), myContext.getEditor(), expr, null, null, PsiUtilCore.toPsiElementArray( - occurrences), myContext.getScope()); + protected String[] suggestNames(boolean replaceAll, @Nullable GrVariable variable) { + return mySuggestedNames; } @Nullable - private GrExpression findExpressionFromStringPartMarker(RangeMarker marker) { - PsiFile file = PsiDocumentManager.getInstance(myContext.getProject()).getPsiFile(marker.getDocument()); - if (file == null) return null; - PsiElement leaf = file.findElementAt(marker.getStartOffset()); - GrBinaryExpression binary = PsiTreeUtil.getParentOfType(leaf, GrBinaryExpression.class); - if (binary != null) { - return binary.getRightOperand(); + @Override + protected JComponent getComponent() { + return myPanel.getRootPane(); + } + + @Override + protected void saveSettings(@NotNull GrVariable variable) { + + } + + @Override + protected GrVariable runRefactoring(GrIntroduceContext context, GrIntroduceConstantSettings settings, boolean processUsages) { + if (processUsages) { + return new GrIntroduceConstantProcessor(context, settings).run(); + } + else { + PsiElement scope = context.getScope(); + return new GrIntroduceConstantProcessor(context, settings).addDeclaration(scope instanceof GroovyFileBase ? ((GroovyFileBase)scope).getScriptClass() : (PsiClass)scope).getVariables()[0]; } - return null; } @Nullable - private GrExpression findExpression(@NotNull RangeMarker marker) { - PsiFile file = PsiDocumentManager.getInstance(myContext.getProject()).getPsiFile(marker.getDocument()); - if (file == null) return null; - PsiElement leaf = file.findElementAt(marker.getStartOffset()); - if (leaf != null && leaf.getParent() instanceof GrReferenceExpression) { - return (GrExpression)leaf.getParent(); - } - return null; + @Override + protected GrIntroduceConstantSettings getInitialSettingsForInplace(@NotNull final GrIntroduceContext context, + @NotNull final OccurrencesChooser.ReplaceChoice choice, + final String[] names) { + return new GrIntroduceConstantSettings() { + @Override + public String getVisibilityModifier() { + return PsiModifier.PUBLIC; + } + + @Nullable + @Override + public PsiClass getTargetClass() { + return (PsiClass)context.getScope(); + } + + @Nullable + @Override + public String getName() { + return names[0]; + } + + @Override + public boolean replaceAllOccurrences() { + return isReplaceAllOccurrences(); + } + + @Nullable + @Override + public PsiType getSelectedType() { + GrExpression expression = context.getExpression(); + GrVariable var = context.getVar(); + StringPartInfo stringPart = context.getStringPart(); + return var != null ? var.getDeclaredType() : + expression != null ? expression.getType() : + stringPart != null ? stringPart.getLiteral().getType() : + null; + } + }; } - private GrIntroduceConstantSettings generateSettings() { + @Override + protected GrIntroduceConstantSettings getSettings() { return new GrIntroduceConstantSettings() { @Override public String getVisibilityModifier() { @@ -145,18 +136,18 @@ public class GrInplaceConstantIntroducer extends GrInplaceIntroducer { @Nullable @Override public String getName() { - return getVariable().getName(); + return getInputName(); } @Override public boolean replaceAllOccurrences() { - return myReplaceAll; + return isReplaceAllOccurrences(); } @Nullable @Override public PsiType getSelectedType() { - return getVariable().getDeclaredType(); + return GrInplaceConstantIntroducer.this.getSelectedType(); } @Nullable @@ -167,17 +158,30 @@ public class GrInplaceConstantIntroducer extends GrInplaceIntroducer { }; } - @Nullable - @Override - protected JComponent getComponent() { - //return myPanel.getRootPane(); - return null; - } - @Nullable @Override protected PsiElement checkLocalScope() { - return getVariable().getContainingFile(); + return ((PsiField)getVariable()).getContainingClass(); } + /** + * Created by Max Medvedev on 8/29/13 + */ + public class GrInplaceIntroduceConstantPanel { + private JBCheckBox myMoveToAnotherClassJBCheckBox; + private JPanel myRootPane; + private JComponent myPreview; + + public boolean isMoveToAnotherClass() { + return myMoveToAnotherClassJBCheckBox.isSelected(); + } + + public JComponent getRootPane() { + return myRootPane; + } + + private void createUIComponents() { + myPreview = getPreviewComponent(); + } + } } diff --git a/plugins/groovy/src/org/jetbrains/plugins/groovy/refactoring/introduce/constant/GrInplaceIntroduceConstantPanel.form b/plugins/groovy/src/org/jetbrains/plugins/groovy/refactoring/introduce/constant/GrInplaceIntroduceConstantPanel.form index da9c8bc90939..10e87c6fcd89 100644 --- a/plugins/groovy/src/org/jetbrains/plugins/groovy/refactoring/introduce/constant/GrInplaceIntroduceConstantPanel.form +++ b/plugins/groovy/src/org/jetbrains/plugins/groovy/refactoring/introduce/constant/GrInplaceIntroduceConstantPanel.form @@ -1,6 +1,6 @@ -
- + + @@ -10,17 +10,24 @@ - + - + + + + + + + + diff --git a/plugins/groovy/src/org/jetbrains/plugins/groovy/refactoring/introduce/constant/GrIntroduceConstantHandler.java b/plugins/groovy/src/org/jetbrains/plugins/groovy/refactoring/introduce/constant/GrIntroduceConstantHandler.java index 926c51eb5b77..9d03af8b5a78 100644 --- a/plugins/groovy/src/org/jetbrains/plugins/groovy/refactoring/introduce/constant/GrIntroduceConstantHandler.java +++ b/plugins/groovy/src/org/jetbrains/plugins/groovy/refactoring/introduce/constant/GrIntroduceConstantHandler.java @@ -15,7 +15,6 @@ */ package org.jetbrains.plugins.groovy.refactoring.introduce.constant; -import com.intellij.openapi.editor.RangeMarker; import com.intellij.psi.*; import com.intellij.psi.util.PsiTreeUtil; import com.intellij.refactoring.HelpID; @@ -27,16 +26,11 @@ import org.jetbrains.plugins.groovy.lang.psi.GroovyRecursiveElementVisitor; import org.jetbrains.plugins.groovy.lang.psi.api.statements.GrField; import org.jetbrains.plugins.groovy.lang.psi.api.statements.GrVariable; import org.jetbrains.plugins.groovy.lang.psi.api.statements.blocks.GrClosableBlock; -import org.jetbrains.plugins.groovy.lang.psi.api.statements.expressions.GrBinaryExpression; import org.jetbrains.plugins.groovy.lang.psi.api.statements.expressions.GrExpression; import org.jetbrains.plugins.groovy.lang.psi.api.statements.expressions.GrReferenceExpression; import org.jetbrains.plugins.groovy.refactoring.GrRefactoringError; import org.jetbrains.plugins.groovy.refactoring.GroovyRefactoringBundle; import org.jetbrains.plugins.groovy.refactoring.introduce.*; -import org.jetbrains.plugins.groovy.refactoring.introduce.field.GrFieldNameSuggester; -import org.jetbrains.plugins.groovy.refactoring.introduce.field.GroovyInplaceFieldValidator; - -import java.util.List; /** * @author Maxim.Medvedev @@ -99,65 +93,9 @@ public class GrIntroduceConstantHandler extends GrIntroduceFieldHandlerBase occurrenceMarkers, - RangeMarker varRangeMarker, RangeMarker expressionRangeMarker, - RangeMarker stringPartRangeMarker) { - if (varRangeMarker != null) { - context.getEditor().getCaretModel().moveToOffset(var.getNameIdentifierGroovy().getTextRange().getStartOffset()); - } - else if (expressionRangeMarker != null) { - context.getEditor().getCaretModel().moveToOffset(expressionRangeMarker.getStartOffset()); - } - else if (stringPartRangeMarker != null) { - int offset = stringPartRangeMarker.getStartOffset(); - PsiElement at = var.getContainingFile().findElementAt(offset); - GrExpression ref = PsiTreeUtil.getParentOfType(at, GrBinaryExpression.class).getRightOperand(); - context.getEditor().getCaretModel().moveToOffset(ref.getTextRange().getStartOffset()); - } - - return new GrInplaceConstantIntroducer(var, context, occurrenceMarkers, settings.replaceAllOccurrences(), expressionRangeMarker, stringPartRangeMarker); - } - - @Override - protected GrIntroduceConstantSettings getSettingsForInplace(final GrIntroduceContext context, final OccurrencesChooser.ReplaceChoice choice) { - return new GrIntroduceConstantSettings() { - @Override - public String getVisibilityModifier() { - return PsiModifier.PUBLIC; - } - - @Nullable - @Override - public PsiClass getTargetClass() { - return (PsiClass)context.getScope(); - } - - @Nullable - @Override - public String getName() { - return new GrFieldNameSuggester(context, new GroovyInplaceFieldValidator(context), false).suggestNames().iterator().next(); - } - - @Override - public boolean replaceAllOccurrences() { - return choice == OccurrencesChooser.ReplaceChoice.ALL; - } - - @Nullable - @Override - public PsiType getSelectedType() { - GrExpression expression = context.getExpression(); - GrVariable var = context.getVar(); - StringPartInfo stringPart = context.getStringPart(); - return var != null ? var.getDeclaredType() : - expression != null ? expression.getType() : - stringPart != null ? stringPart.getLiteral().getType() : - null; - } - }; + protected GrAbstractInplaceIntroducer getIntroducer(@NotNull GrIntroduceContext context, + OccurrencesChooser.ReplaceChoice choice) { + return new GrInplaceConstantIntroducer(context, choice); } private static class ConstantChecker extends GroovyRecursiveElementVisitor { diff --git a/plugins/groovy/src/org/jetbrains/plugins/groovy/refactoring/introduce/constant/GrIntroduceConstantProcessor.java b/plugins/groovy/src/org/jetbrains/plugins/groovy/refactoring/introduce/constant/GrIntroduceConstantProcessor.java index 2e2f0007350f..bb13241a8d9e 100644 --- a/plugins/groovy/src/org/jetbrains/plugins/groovy/refactoring/introduce/constant/GrIntroduceConstantProcessor.java +++ b/plugins/groovy/src/org/jetbrains/plugins/groovy/refactoring/introduce/constant/GrIntroduceConstantProcessor.java @@ -69,8 +69,7 @@ public class GrIntroduceConstantProcessor { return null; } - final GrVariableDeclaration rawDeclaration = createField(targetClass); - final GrVariableDeclaration declaration = addDeclaration(targetClass, rawDeclaration); + final GrVariableDeclaration declaration = addDeclaration(targetClass); final GrField field = (GrField)declaration.getVariables()[0]; if (context.getVar() != null) { @@ -102,7 +101,8 @@ public class GrIntroduceConstantProcessor { context.getEditor().getSelectionModel().removeSelection(); } - protected GrVariableDeclaration addDeclaration(PsiClass targetClass, GrVariableDeclaration declaration) { + protected GrVariableDeclaration addDeclaration(PsiClass targetClass) { + GrVariableDeclaration declaration = createField(targetClass); final GrVariableDeclaration added; if (targetClass instanceof GrEnumTypeDefinition) { final GrEnumConstantList enumConstants = ((GrEnumTypeDefinition)targetClass).getEnumConstantList(); diff --git a/plugins/groovy/src/org/jetbrains/plugins/groovy/refactoring/introduce/field/GrInplaceFieldIntroducer.java b/plugins/groovy/src/org/jetbrains/plugins/groovy/refactoring/introduce/field/GrInplaceFieldIntroducer.java index c37d13ddd471..58d907e23f0e 100644 --- a/plugins/groovy/src/org/jetbrains/plugins/groovy/refactoring/introduce/field/GrInplaceFieldIntroducer.java +++ b/plugins/groovy/src/org/jetbrains/plugins/groovy/refactoring/introduce/field/GrInplaceFieldIntroducer.java @@ -17,140 +17,133 @@ package org.jetbrains.plugins.groovy.refactoring.introduce.field; import com.intellij.openapi.application.Result; import com.intellij.openapi.command.WriteCommandAction; -import com.intellij.openapi.editor.RangeMarker; import com.intellij.openapi.project.Project; import com.intellij.psi.*; -import com.intellij.psi.util.PsiTreeUtil; -import com.intellij.psi.util.PsiUtilCore; import com.intellij.refactoring.introduce.inplace.KeyboardComboSwitcher; +import com.intellij.refactoring.introduce.inplace.OccurrencesChooser; import com.intellij.refactoring.introduceField.IntroduceFieldHandler; import com.intellij.ui.NonFocusableCheckBox; -import com.intellij.util.containers.ContainerUtil; import org.jetbrains.annotations.NotNull; import org.jetbrains.annotations.Nullable; import org.jetbrains.plugins.groovy.lang.psi.api.statements.GrVariable; -import org.jetbrains.plugins.groovy.lang.psi.api.statements.GrVariableDeclaration; -import org.jetbrains.plugins.groovy.lang.psi.api.statements.expressions.GrBinaryExpression; import org.jetbrains.plugins.groovy.lang.psi.api.statements.expressions.GrExpression; -import org.jetbrains.plugins.groovy.lang.psi.api.statements.expressions.GrReferenceExpression; +import org.jetbrains.plugins.groovy.lang.psi.util.PsiUtil; import org.jetbrains.plugins.groovy.refactoring.GroovyNameSuggestionUtil; +import org.jetbrains.plugins.groovy.refactoring.introduce.GrAbstractInplaceIntroducer; import org.jetbrains.plugins.groovy.refactoring.introduce.GrFinalListener; -import org.jetbrains.plugins.groovy.refactoring.introduce.GrInplaceIntroducer; import org.jetbrains.plugins.groovy.refactoring.introduce.GrIntroduceContext; -import org.jetbrains.plugins.groovy.refactoring.introduce.GrIntroduceContextImpl; +import org.jetbrains.plugins.groovy.refactoring.introduce.StringPartInfo; import javax.swing.*; import java.awt.event.ActionEvent; import java.awt.event.ActionListener; import java.util.EnumSet; -import java.util.LinkedHashSet; -import java.util.List; /** * @author Max Medvedev */ -public class GrInplaceFieldIntroducer extends GrInplaceIntroducer { - private final GrInplaceIntroduceFieldPanel myPanel; - private final GrIntroduceContext myContext; - private final RangeMarker myExpressionRangeMarker; - private final RangeMarker myStringPartRangeMarker; - private final GrExpression myInitializer; +public class GrInplaceFieldIntroducer extends GrAbstractInplaceIntroducer { + private GrInplaceIntroduceFieldPanel myPanel; private final GrFinalListener finalListener; - private final boolean myReplaceAll; + private String[] mySuggestedNames; + private boolean myIsStatic; @Nullable @Override protected PsiElement checkLocalScope() { - return getVariable().getContainingFile(); + return ((PsiField)getVariable()).getContainingClass(); } - public GrInplaceFieldIntroducer(GrVariable var, - GrIntroduceContext context, - List occurrences, - boolean replaceAll, - @Nullable RangeMarker expressionRangeMarker, - @Nullable RangeMarker stringPartRangeMarker, - GrExpression initializer) { - super(var, context.getEditor(), context.getProject(), IntroduceFieldHandler.REFACTORING_NAME, occurrences, context.getPlace()); - - myContext = context; - myReplaceAll = replaceAll; - myExpressionRangeMarker = expressionRangeMarker; - myStringPartRangeMarker = stringPartRangeMarker; - myInitializer = initializer; - - myPanel = new GrInplaceIntroduceFieldPanel(context.getProject(), - GrIntroduceFieldHandler.getApplicableInitPlaces(context, replaceAll)); + public GrInplaceFieldIntroducer(GrIntroduceContext context, OccurrencesChooser.ReplaceChoice choice) { + super(IntroduceFieldHandler.REFACTORING_NAME, choice, context); finalListener = new GrFinalListener(myEditor); + + mySuggestedNames = GroovyNameSuggestionUtil.suggestVariableNames(context.getExpression(), new GroovyInplaceFieldValidator(getContext()), false); } @Override - protected void moveOffsetAfter(boolean success) { - if (success) { - final GrVariable field = getVariable(); - assert field != null; - GrIntroduceFieldProcessor processor = new GrIntroduceFieldProcessor(generateContext(), generateSettings(), false) { - @NotNull - @Override - protected GrExpression getInitializer() { - return myInitializer; - } - - @NotNull - @Override - protected GrVariableDeclaration insertField(@NotNull PsiClass targetClass, @NotNull GrVariableDeclaration declaration) { - return (GrVariableDeclaration)field.getParent(); - } - }; - processor.run(); - } - super.moveOffsetAfter(success); - } - - private GrIntroduceContext generateContext() { - final List occurrenceMarkers = getOccurrenceMarkers(); - - List occurrences = ContainerUtil.newArrayList(); - for (RangeMarker marker : occurrenceMarkers) { - ContainerUtil.addIfNotNull(occurrences, findExpression(marker)); - } - - GrExpression expr = null; - if (myExpressionRangeMarker != null) expr = findExpression(myExpressionRangeMarker); - if (myStringPartRangeMarker != null) { - expr = findExpressionFromStringPartMarker(myStringPartRangeMarker); - occurrences.add(expr); - } - - return new GrIntroduceContextImpl(myContext.getProject(), myContext.getEditor(), expr, null, null, PsiUtilCore.toPsiElementArray( - occurrences), myContext.getScope()); + protected GrVariable runRefactoring(GrIntroduceContext context, GrIntroduceFieldSettings settings, boolean processUsages) { + GrIntroduceFieldProcessor processor = new GrIntroduceFieldProcessor(context, settings); + return processUsages ? processor.run() + : processor.insertField((PsiClass)context.getScope()).getVariables()[0]; } @Nullable - private GrExpression findExpressionFromStringPartMarker(RangeMarker marker) { - PsiFile file = PsiDocumentManager.getInstance(myContext.getProject()).getPsiFile(marker.getDocument()); - if (file == null) return null; - PsiElement leaf = file.findElementAt(marker.getStartOffset()); - GrBinaryExpression binary = PsiTreeUtil.getParentOfType(leaf, GrBinaryExpression.class); - if (binary != null) { - return binary.getRightOperand(); - } - return null; + @Override + protected GrIntroduceFieldSettings getInitialSettingsForInplace(@NotNull final GrIntroduceContext context, + @NotNull final OccurrencesChooser.ReplaceChoice choice, + final String[] names) { + return new GrIntroduceFieldSettings() { + @Override + public boolean declareFinal() { + return false; + } + + @Override + public Init initializeIn() { + return Init.FIELD_DECLARATION; + } + + @Override + public String getVisibilityModifier() { + return PsiModifier.PRIVATE; + } + + @Override + public boolean isStatic() { + boolean hasInstanceInScope = true; + PsiClass clazz = (PsiClass)context.getScope(); + if (replaceAllOccurrences()) { + for (PsiElement occurrence : context.getOccurrences()) { + if (!PsiUtil.hasEnclosingInstanceInScope(clazz, occurrence, false)) { + hasInstanceInScope = false; + break; + } + } + } + else if (context.getExpression() != null) { + hasInstanceInScope = PsiUtil.hasEnclosingInstanceInScope(clazz, context.getExpression(), false); + } + else if (context.getStringPart() != null) { + hasInstanceInScope = PsiUtil.hasEnclosingInstanceInScope(clazz, context.getStringPart().getLiteral(), false); + } + + return !hasInstanceInScope; + } + + @Override + public boolean removeLocalVar() { + return context.getVar() != null; + } + + @Nullable + @Override + public String getName() { + return names[0]; + } + + @Override + public boolean replaceAllOccurrences() { + return context.getVar() != null || choice == OccurrencesChooser.ReplaceChoice.ALL; + } + + @Nullable + @Override + public PsiType getSelectedType() { + GrExpression expression = context.getExpression(); + GrVariable var = context.getVar(); + StringPartInfo stringPart = context.getStringPart(); + return var != null ? var.getDeclaredType() : + expression != null ? expression.getType() : + stringPart != null ? stringPart.getLiteral().getType() : + null; + } + }; } - @Nullable - private GrExpression findExpression(@NotNull RangeMarker marker) { - PsiFile file = PsiDocumentManager.getInstance(myContext.getProject()).getPsiFile(marker.getDocument()); - if (file == null) return null; - PsiElement leaf = file.findElementAt(marker.getStartOffset()); - if (leaf != null && leaf.getParent() instanceof GrReferenceExpression) { - return (GrExpression)leaf.getParent(); - } - return null; - } - - private GrIntroduceFieldSettings generateSettings() { + @Override + protected GrIntroduceFieldSettings getSettings() { return new GrIntroduceFieldSettings() { @Override public boolean declareFinal() { @@ -169,7 +162,7 @@ public class GrInplaceFieldIntroducer extends GrInplaceIntroducer { @Override public boolean isStatic() { - return getVariable().hasModifierProperty(PsiModifier.STATIC); + return myIsStatic; } @Override @@ -180,39 +173,57 @@ public class GrInplaceFieldIntroducer extends GrInplaceIntroducer { @Nullable @Override public String getName() { - return getVariable().getName(); + return getInputName(); } @Override public boolean replaceAllOccurrences() { - return myReplaceAll; + return isReplaceAllOccurrences(); } @Nullable @Override public PsiType getSelectedType() { - return getVariable().getDeclaredType(); + return GrInplaceFieldIntroducer.this.getSelectedType(); } }; } + @Override + protected String getActionName() { + return IntroduceFieldHandler.REFACTORING_NAME; + } + + @Override + protected String[] suggestNames(boolean replaceAll, @Nullable GrVariable variable) { + return mySuggestedNames; + } + + @Override + protected void saveSettings(@NotNull GrVariable variable) { + + } + + @Override + protected void restoreState(GrVariable psiField) { + myIsStatic = psiField.hasModifierProperty(PsiModifier.STATIC); + + super.restoreState(psiField); + } + @Nullable @Override protected JComponent getComponent() { + myPanel = new GrInplaceIntroduceFieldPanel(myProject, GrIntroduceFieldHandler.getApplicableInitPlaces(getContext(), isReplaceAllOccurrences())); return myPanel.getRootPane(); } - @Override - public LinkedHashSet suggestNames(GrIntroduceContext context) { - return ContainerUtil.newLinkedHashSet( - GroovyNameSuggestionUtil.suggestVariableNames(myInitializer, new GroovyInplaceFieldValidator(context), false)); - } - public class GrInplaceIntroduceFieldPanel { private final Project myProject; private JPanel myRootPane; private JComboBox myInitCB; private NonFocusableCheckBox myDeclareFinalCB; + private JComponent myPreview; public GrInplaceIntroduceFieldPanel(Project project, EnumSet initPlaces) { myProject = project; @@ -251,5 +262,9 @@ public class GrInplaceFieldIntroducer extends GrInplaceIntroducer { public boolean isFinal() { return myDeclareFinalCB.isSelected(); } + + private void createUIComponents() { + myPreview = getPreviewComponent(); + } } } diff --git a/plugins/groovy/src/org/jetbrains/plugins/groovy/refactoring/introduce/field/GrInplaceIntroduceFieldPanel.form b/plugins/groovy/src/org/jetbrains/plugins/groovy/refactoring/introduce/field/GrInplaceIntroduceFieldPanel.form index 96f32e533680..c75e58c49327 100644 --- a/plugins/groovy/src/org/jetbrains/plugins/groovy/refactoring/introduce/field/GrInplaceIntroduceFieldPanel.form +++ b/plugins/groovy/src/org/jetbrains/plugins/groovy/refactoring/introduce/field/GrInplaceIntroduceFieldPanel.form @@ -1,9 +1,9 @@
- + - + @@ -11,7 +11,7 @@ - + @@ -35,13 +35,18 @@ - + + + + + + diff --git a/plugins/groovy/src/org/jetbrains/plugins/groovy/refactoring/introduce/field/GrIntroduceFieldHandler.java b/plugins/groovy/src/org/jetbrains/plugins/groovy/refactoring/introduce/field/GrIntroduceFieldHandler.java index 0211ee378a4c..a21dbe17f654 100644 --- a/plugins/groovy/src/org/jetbrains/plugins/groovy/refactoring/introduce/field/GrIntroduceFieldHandler.java +++ b/plugins/groovy/src/org/jetbrains/plugins/groovy/refactoring/introduce/field/GrIntroduceFieldHandler.java @@ -16,25 +16,21 @@ package org.jetbrains.plugins.groovy.refactoring.introduce.field; import com.intellij.codeInsight.TestFrameworks; -import com.intellij.openapi.application.ApplicationManager; -import com.intellij.openapi.editor.RangeMarker; import com.intellij.psi.PsiClass; import com.intellij.psi.PsiElement; import com.intellij.psi.PsiModifier; -import com.intellij.psi.PsiType; -import com.intellij.psi.util.PsiTreeUtil; import com.intellij.refactoring.HelpID; import com.intellij.refactoring.introduce.inplace.OccurrencesChooser; import com.intellij.refactoring.introduceField.IntroduceFieldHandler; import com.intellij.util.containers.ContainerUtil; import org.jetbrains.annotations.NotNull; import org.jetbrains.annotations.Nullable; -import org.jetbrains.plugins.groovy.lang.psi.GroovyPsiElementFactory; +import org.jetbrains.plugins.groovy.lang.psi.GroovyFileBase; import org.jetbrains.plugins.groovy.lang.psi.api.statements.GrVariable; -import org.jetbrains.plugins.groovy.lang.psi.api.statements.expressions.GrBinaryExpression; import org.jetbrains.plugins.groovy.lang.psi.api.statements.expressions.GrExpression; import org.jetbrains.plugins.groovy.lang.psi.api.statements.typedef.GrTypeDefinition; import org.jetbrains.plugins.groovy.lang.psi.api.statements.typedef.members.GrMember; +import org.jetbrains.plugins.groovy.lang.psi.impl.synthetic.GroovyScriptClass; import org.jetbrains.plugins.groovy.lang.psi.util.PsiUtil; import org.jetbrains.plugins.groovy.refactoring.GrRefactoringError; import org.jetbrains.plugins.groovy.refactoring.GroovyRefactoringBundle; @@ -100,133 +96,39 @@ public class GrIntroduceFieldHandler extends GrIntroduceFieldHandlerBase occurrenceMarkers, - @Nullable RangeMarker varRangeMarker, - @Nullable RangeMarker expressionRangeMarker, - @Nullable RangeMarker stringPartRangeMarker) { - if (varRangeMarker != null) { - context.getEditor().getCaretModel().moveToOffset(var.getNameIdentifierGroovy().getTextRange().getStartOffset()); - } - else if (expressionRangeMarker != null) { - context.getEditor().getCaretModel().moveToOffset(expressionRangeMarker.getStartOffset()); - } - else if (stringPartRangeMarker != null) { - int offset = stringPartRangeMarker.getStartOffset(); - PsiElement at = var.getContainingFile().findElementAt(offset); - GrExpression ref = PsiTreeUtil.getParentOfType(at, GrBinaryExpression.class).getRightOperand(); - context.getEditor().getCaretModel().moveToOffset(ref.getTextRange().getStartOffset()); - } - GrExpression initializer = - GroovyPsiElementFactory.getInstance(context.getProject()).createExpressionFromText(var.getInitializerGroovy().getText()); - ApplicationManager.getApplication().runWriteAction(new Runnable() { - @Override - public void run() { - var.setInitializerGroovy(null); - } - }); - return new GrInplaceFieldIntroducer(var, context, occurrenceMarkers, settings.replaceAllOccurrences(), expressionRangeMarker, - stringPartRangeMarker, initializer); + @Override + protected GrAbstractInplaceIntroducer getIntroducer(@NotNull GrIntroduceContext context, + OccurrencesChooser.ReplaceChoice choice) { + return new GrInplaceFieldIntroducer(context, choice); } static EnumSet getApplicableInitPlaces(GrIntroduceContext context, boolean replaceAll) { - EnumSet result = EnumSet.of(GrIntroduceFieldSettings.Init.FIELD_DECLARATION, - GrIntroduceFieldSettings.Init.CONSTRUCTOR); + EnumSet result = EnumSet.of(GrIntroduceFieldSettings.Init.FIELD_DECLARATION); + if (!(context.getScope() instanceof GroovyScriptClass || context.getScope() instanceof GroovyFileBase)) { + result.add(GrIntroduceFieldSettings.Init.CONSTRUCTOR); + } - GrTypeDefinition clazz = (GrTypeDefinition)context.getScope(); + PsiElement scope = context.getScope(); if (replaceAll) { - PsiElement anchor = GrIntroduceHandlerBase.findAnchor(context.getOccurrences(), clazz); + PsiElement anchor = GrIntroduceHandlerBase.findAnchor(context.getOccurrences(), scope); if (anchor != null) { result.add(GrIntroduceFieldSettings.Init.CUR_METHOD); } } - if (TestFrameworks.getInstance().isTestClass(clazz)) { + if (scope instanceof GrTypeDefinition && TestFrameworks.getInstance().isTestClass((PsiClass)scope)) { result.add(GrIntroduceFieldSettings.Init.SETUP_METHOD); } return result; } - @Override - protected GrIntroduceFieldSettings getSettingsForInplace(final GrIntroduceContext context, final OccurrencesChooser.ReplaceChoice choice) { - return new GrIntroduceFieldSettings() { - @Override - public boolean declareFinal() { - return false; - } - - @Override - public Init initializeIn() { - return Init.FIELD_DECLARATION; - } - - @Override - public String getVisibilityModifier() { - return PsiModifier.PRIVATE; - } - - @Override - public boolean isStatic() { - boolean hasInstanceInScope = true; - PsiClass clazz = (PsiClass)context.getScope(); - if (replaceAllOccurrences()) { - for (PsiElement occurrence : context.getOccurrences()) { - if (!PsiUtil.hasEnclosingInstanceInScope(clazz, occurrence, false)) { - hasInstanceInScope = false; - break; - } - } - } - else if (context.getExpression() != null) { - hasInstanceInScope = PsiUtil.hasEnclosingInstanceInScope(clazz, context.getExpression(), false); - } - else if (context.getStringPart() != null) { - hasInstanceInScope = PsiUtil.hasEnclosingInstanceInScope(clazz, context.getStringPart().getLiteral(), false); - } - - return !hasInstanceInScope; - } - - @Override - public boolean removeLocalVar() { - return context.getVar() != null; - } - - @Nullable - @Override - public String getName() { - return new GrFieldNameSuggester(context, new GroovyInplaceFieldValidator(context), false).suggestNames().iterator().next(); - } - - @Override - public boolean replaceAllOccurrences() { - return context.getVar() != null || choice == OccurrencesChooser.ReplaceChoice.ALL; - } - - @Nullable - @Override - public PsiType getSelectedType() { - GrExpression expression = context.getExpression(); - GrVariable var = context.getVar(); - StringPartInfo stringPart = context.getStringPart(); - return var != null ? var.getDeclaredType() : - expression != null ? expression.getType() : - stringPart != null ? stringPart.getLiteral().getType() : - null; - } - }; - } - @NotNull @Override protected PsiElement[] findOccurrences(@NotNull GrExpression expression, @NotNull PsiElement scope) { diff --git a/plugins/groovy/src/org/jetbrains/plugins/groovy/refactoring/introduce/field/GrIntroduceFieldProcessor.java b/plugins/groovy/src/org/jetbrains/plugins/groovy/refactoring/introduce/field/GrIntroduceFieldProcessor.java index 81da87ba01c7..5331e4388bad 100644 --- a/plugins/groovy/src/org/jetbrains/plugins/groovy/refactoring/introduce/field/GrIntroduceFieldProcessor.java +++ b/plugins/groovy/src/org/jetbrains/plugins/groovy/refactoring/introduce/field/GrIntroduceFieldProcessor.java @@ -25,8 +25,10 @@ import com.intellij.util.ArrayUtil; import com.intellij.util.containers.ContainerUtil; import org.jetbrains.annotations.NotNull; import org.jetbrains.annotations.Nullable; +import org.jetbrains.plugins.groovy.codeStyle.GrReferenceAdjuster; import org.jetbrains.plugins.groovy.lang.psi.GrQualifiedReference; import org.jetbrains.plugins.groovy.lang.psi.GroovyFile; +import org.jetbrains.plugins.groovy.lang.psi.GroovyFileBase; import org.jetbrains.plugins.groovy.lang.psi.GroovyPsiElementFactory; import org.jetbrains.plugins.groovy.lang.psi.api.auxiliary.modifiers.GrModifier; import org.jetbrains.plugins.groovy.lang.psi.api.statements.*; @@ -62,19 +64,19 @@ public class GrIntroduceFieldProcessor { private final GrIntroduceContext context; private final GrIntroduceFieldSettings settings; - private boolean myForInplacePrepare; - public GrIntroduceFieldProcessor(@NotNull GrIntroduceContext context, @NotNull GrIntroduceFieldSettings settings, boolean forInplacePrepare) { + public GrIntroduceFieldProcessor(@NotNull GrIntroduceContext context, + @NotNull GrIntroduceFieldSettings settings) { this.context = context; this.settings = settings; - myForInplacePrepare = forInplacePrepare; } public GrVariable run() { - final PsiClass targetClass = (PsiClass)context.getScope(); + PsiElement scope = context.getScope(); + final PsiClass targetClass = scope instanceof GroovyFileBase ? ((GroovyFileBase)scope).getScriptClass() : (PsiClass)scope; if (targetClass == null) return null; - final GrVariableDeclaration declaration = insertField(targetClass, createField()); + final GrVariableDeclaration declaration = insertField(targetClass); final GrVariable field = declaration.getVariables()[0]; switch (settings.initializeIn()) { @@ -119,7 +121,7 @@ public class GrIntroduceFieldProcessor { else { final GrExpression expression = context.getExpression(); assert expression != null; - if (!myForInplacePrepare && PsiUtil.isExpressionStatement(expression)) { + if (PsiUtil.isExpressionStatement(expression)) { expression.delete(); } else { @@ -135,7 +137,8 @@ public class GrIntroduceFieldProcessor { } @NotNull - protected GrVariableDeclaration insertField(@NotNull PsiClass targetClass, @NotNull GrVariableDeclaration declaration) { + protected GrVariableDeclaration insertField(@NotNull PsiClass targetClass) { + GrVariableDeclaration declaration = createField(targetClass); if (targetClass instanceof GrEnumTypeDefinition) { final GrEnumConstantList enumConstants = ((GrEnumTypeDefinition)targetClass).getEnumConstantList(); return (GrVariableDeclaration)targetClass.addAfter(declaration, enumConstants); @@ -304,7 +307,7 @@ public class GrIntroduceFieldProcessor { } if (replaced instanceof GrQualifiedReference) { - org.jetbrains.plugins.groovy.codeStyle.GrReferenceAdjuster.shortenReference((GrQualifiedReference)replaced); + GrReferenceAdjuster.shortenReference((GrQualifiedReference)replaced); } if (isOriginal) { updateCaretPosition(replaced); @@ -326,13 +329,13 @@ public class GrIntroduceFieldProcessor { return GroovyPsiElementFactory.getInstance(place.getProject()).createReferenceExpressionFromText(refText, place); } - private GrVariableDeclaration createField() { + private GrVariableDeclaration createField(PsiClass targetClass) { final String name = settings.getName(); final PsiType type = settings.getSelectedType(); final String modifier = settings.getVisibilityModifier(); List modifiers = new ArrayList(); - if (context.getScope() instanceof GroovyScriptClass) { + if (targetClass instanceof GroovyScriptClass) { modifiers.add("@" + GroovyCommonClassNames.GROOVY_TRANSFORM_FIELD); } if (settings.isStatic()) modifiers.add(PsiModifier.STATIC); @@ -341,7 +344,7 @@ public class GrIntroduceFieldProcessor { final String[] arr_modifiers = ArrayUtil.toStringArray(modifiers); final GroovyPsiElementFactory factory = GroovyPsiElementFactory.getInstance(context.getProject()); - if (context.getScope() instanceof GroovyScriptClass) { + if (targetClass instanceof GroovyScriptClass) { return factory.createVariableDeclaration(arr_modifiers, ((GrExpression)null), type, name); } else { diff --git a/plugins/groovy/src/org/jetbrains/plugins/groovy/refactoring/introduce/variable/GrInplaceVariableIntroducer.java b/plugins/groovy/src/org/jetbrains/plugins/groovy/refactoring/introduce/variable/GrInplaceVariableIntroducer.java index eb19b097c90f..a8732988a2c8 100644 --- a/plugins/groovy/src/org/jetbrains/plugins/groovy/refactoring/introduce/variable/GrInplaceVariableIntroducer.java +++ b/plugins/groovy/src/org/jetbrains/plugins/groovy/refactoring/introduce/variable/GrInplaceVariableIntroducer.java @@ -16,25 +16,31 @@ package org.jetbrains.plugins.groovy.refactoring.introduce.variable; import com.intellij.codeInsight.template.TemplateBuilderImpl; +import com.intellij.openapi.actionSystem.Shortcut; import com.intellij.openapi.application.Result; import com.intellij.openapi.command.WriteCommandAction; -import com.intellij.openapi.editor.Editor; -import com.intellij.openapi.editor.RangeMarker; -import com.intellij.openapi.project.Project; +import com.intellij.openapi.keymap.Keymap; +import com.intellij.openapi.keymap.KeymapManager; +import com.intellij.openapi.keymap.KeymapUtil; import com.intellij.psi.PsiDocumentManager; import com.intellij.psi.PsiElement; +import com.intellij.psi.PsiType; +import com.intellij.refactoring.introduce.inplace.OccurrencesChooser; +import com.intellij.refactoring.util.CanonicalTypes; import com.intellij.ui.NonFocusableCheckBox; -import com.intellij.util.containers.ContainerUtil; +import org.jetbrains.annotations.NotNull; import org.jetbrains.annotations.Nullable; import org.jetbrains.plugins.groovy.lang.psi.api.auxiliary.modifiers.GrModifier; import org.jetbrains.plugins.groovy.lang.psi.api.statements.GrVariable; +import org.jetbrains.plugins.groovy.lang.psi.api.statements.expressions.GrExpression; import org.jetbrains.plugins.groovy.lang.psi.expectedTypes.SupertypeConstraint; import org.jetbrains.plugins.groovy.lang.psi.expectedTypes.TypeConstraint; import org.jetbrains.plugins.groovy.lang.psi.util.PsiUtil; import org.jetbrains.plugins.groovy.refactoring.GroovyNameSuggestionUtil; +import org.jetbrains.plugins.groovy.refactoring.introduce.GrAbstractInplaceIntroducer; import org.jetbrains.plugins.groovy.refactoring.introduce.GrFinalListener; -import org.jetbrains.plugins.groovy.refactoring.introduce.GrInplaceIntroducer; import org.jetbrains.plugins.groovy.refactoring.introduce.GrIntroduceContext; +import org.jetbrains.plugins.groovy.refactoring.introduce.StringPartInfo; import org.jetbrains.plugins.groovy.settings.GroovyApplicationSettings; import org.jetbrains.plugins.groovy.template.expressions.ChooseTypeExpression; @@ -42,30 +48,40 @@ import javax.swing.*; import java.awt.*; import java.awt.event.ActionEvent; import java.awt.event.ActionListener; -import java.util.LinkedHashSet; -import java.util.List; /** - * @author Max Medvedev + * Created by Max Medvedev on 10/29/13 */ -public class GrInplaceVariableIntroducer extends GrInplaceIntroducer { +public abstract class GrInplaceVariableIntroducer extends GrAbstractInplaceIntroducer { private JCheckBox myCanBeFinalCb; - public GrInplaceVariableIntroducer(GrVariable elementToRename, - Editor editor, - Project project, - String title, - List occurrences, - @Nullable PsiElement elementToIntroduce) { - super(elementToRename, editor, project, title, occurrences, elementToIntroduce); - } - - @Override - public LinkedHashSet suggestNames(GrIntroduceContext context) { - return ContainerUtil.newLinkedHashSet(GroovyNameSuggestionUtil.suggestVariableNames(getVariable().getInitializerGroovy(), new GroovyVariableValidator(context))); + public GrInplaceVariableIntroducer(String title, + OccurrencesChooser.ReplaceChoice replaceChoice, + GrIntroduceContext context) { + super(title, replaceChoice, context); + setAdvertisementText(getAdvertisementText()); } @Nullable + private static String getAdvertisementText() { + final Keymap keymap = KeymapManager.getInstance().getActiveKeymap(); + final Shortcut[] shortcuts = keymap.getShortcuts("PreviousTemplateVariable"); + if (shortcuts.length > 0) { + return "Press " + KeymapUtil.getShortcutText(shortcuts[0]) + " to change type"; + } + return null; + } + + @Override + protected String getActionName() { + return GrIntroduceVariableHandler.REFACTORING_NAME; + } + + @Override + protected String[] suggestNames(boolean replaceAll, @Nullable GrVariable variable) { + return GroovyNameSuggestionUtil.suggestVariableNames(getContext().getExpression(), new GroovyVariableValidator(getContext())); + } + @Override protected JComponent getComponent() { myCanBeFinalCb = new NonFocusableCheckBox("Declare final"); @@ -91,22 +107,58 @@ public class GrInplaceVariableIntroducer extends GrInplaceIntroducer { panel.setBorder(null); if (myCanBeFinalCb != null) { - panel.add(myCanBeFinalCb, new GridBagConstraints(0, 1, 1, 1, 1, 0, GridBagConstraints.NORTHWEST, GridBagConstraints.HORIZONTAL, new Insets(5, 5, 5, 5), 0, 0)); + panel.add(myCanBeFinalCb, new GridBagConstraints(0, 1, 1, 1, 1, 0, GridBagConstraints.NORTHWEST, GridBagConstraints.HORIZONTAL, + new Insets(5, 5, 5, 5), 0, 0)); } - panel.add(Box.createVerticalBox(), new GridBagConstraints(0, 2, 1, 1, 1, 1, GridBagConstraints.NORTHWEST, GridBagConstraints.BOTH, new Insets(0,0,0,0), 0,0)); + panel.add(Box.createVerticalBox(), + new GridBagConstraints(0, 2, 1, 1, 1, 1, GridBagConstraints.NORTHWEST, GridBagConstraints.BOTH, new Insets(0, 0, 0, 0), 0, 0)); return panel; - } + @Nullable @Override - public void finish(boolean success) { - super.finish(success); + protected GroovyIntroduceVariableSettings getInitialSettingsForInplace(@NotNull final GrIntroduceContext context, + @NotNull final OccurrencesChooser.ReplaceChoice choice, + final String[] names) { + return new GroovyIntroduceVariableSettings() { + private final CanonicalTypes.Type myType; - if (success) { - GroovyApplicationSettings.getInstance().INTRODUCE_LOCAL_SELECT_DEF = getVariable().getDeclaredType() == null; - } + { + GrExpression expression = context.getExpression(); + StringPartInfo stringPart = context.getStringPart(); + GrVariable var = context.getVar(); + PsiType type = expression != null ? expression.getType() : + var != null ? var.getType() : + stringPart != null ? stringPart.getLiteral().getType() : + null; + myType = type != null ? CanonicalTypes.createTypeWrapper(type) : null; + } + + + @Override + public boolean isDeclareFinal() { + return myCanBeFinalCb != null ? myCanBeFinalCb.isSelected() : false; + } + + @Nullable + @Override + public String getName() { + return names[0]; + } + + @Override + public boolean replaceAllOccurrences() { + return choice == OccurrencesChooser.ReplaceChoice.ALL; + } + + @Nullable + @Override + public PsiType getSelectedType() { + return myType != null ? myType.getType(context.getPlace(), context.getPlace().getManager()) : null; + } + }; } @Override @@ -119,4 +171,40 @@ public class GrInplaceVariableIntroducer extends GrInplaceIntroducer { : PsiUtil.findModifierInList(variable.getModifierList(), GrModifier.DEF); builder.replaceElement(element, "Variable_type", typeExpression, true, true); } -} + + protected GroovyIntroduceVariableSettings getSettings() { + return new GroovyIntroduceVariableSettings() { + @Override + public boolean isDeclareFinal() { + return myCanBeFinalCb.isSelected(); + } + + @Nullable + @Override + public String getName() { + return GrInplaceVariableIntroducer.this.getInputName(); + } + + @Override + public boolean replaceAllOccurrences() { + return isReplaceAllOccurrences(); + } + + @Nullable + @Override + public PsiType getSelectedType() { + return GrInplaceVariableIntroducer.this.getSelectedType(); + } + }; + } + + @Override + protected void saveSettings(@NotNull GrVariable variable) { + GroovyApplicationSettings.getInstance().INTRODUCE_LOCAL_SELECT_DEF = variable.getDeclaredType() == null; + } + + @Override + protected int getCaretOffset() { + return getVariable().getNameIdentifierGroovy().getTextRange().getEndOffset(); + } +} \ No newline at end of file diff --git a/plugins/groovy/src/org/jetbrains/plugins/groovy/refactoring/introduce/variable/GrIntroduceLocalVariableProcessor.java b/plugins/groovy/src/org/jetbrains/plugins/groovy/refactoring/introduce/variable/GrIntroduceLocalVariableProcessor.java index 3d01195b1c4b..9546a20a24a4 100644 --- a/plugins/groovy/src/org/jetbrains/plugins/groovy/refactoring/introduce/variable/GrIntroduceLocalVariableProcessor.java +++ b/plugins/groovy/src/org/jetbrains/plugins/groovy/refactoring/introduce/variable/GrIntroduceLocalVariableProcessor.java @@ -46,26 +46,26 @@ import java.util.List; /** * @author Max Medvedev */ -public class GrIntroduceLocalVariableProcessor { +public abstract class GrIntroduceLocalVariableProcessor { private static final Logger LOG = Logger.getInstance(GrIntroduceLocalVariableProcessor.class); private final GrIntroduceContext myContext; private final GroovyIntroduceVariableSettings mySettings; + private final boolean myProcessUsages; private final PsiElement[] myOccurrences; private GrExpression myExpression; - private final GrIntroduceVariableHandler myHandler; public GrIntroduceLocalVariableProcessor(@NotNull GrIntroduceContext context, @NotNull GroovyIntroduceVariableSettings settings, @NotNull PsiElement[] occurrences, @NotNull GrExpression expression, - @NotNull GrIntroduceVariableHandler handler) { + boolean processUsages) { myContext = context; mySettings = settings; + myProcessUsages = processUsages; myOccurrences = settings.replaceAllOccurrences() ? occurrences : new PsiElement[]{expression}; myExpression = expression; - myHandler = handler; } @NotNull @@ -75,7 +75,7 @@ public class GrIntroduceLocalVariableProcessor { preprocessOccurrences(); int expressionIndex = ArrayUtilRt.find(myOccurrences, myExpression); - final PsiElement[] replaced = processOccurrences(); + final PsiElement[] replaced = myProcessUsages ? processOccurrences() : myOccurrences; PsiElement replacedExpression = replaced[expressionIndex]; GrStatement anchor = getAnchor(replaced); @@ -84,9 +84,7 @@ public class GrIntroduceLocalVariableProcessor { return insertVariableDefinition(declaration, anchor, replacedExpression); } - private void refreshPositionMarker(PsiElement e) { - myHandler.refreshPositionMarker(myContext.getEditor().getDocument().createRangeMarker(e.getTextRange())); - } + protected abstract void refreshPositionMarker(PsiElement e); private static boolean isControlStatementBranch(GrStatement statement) { return statement.getParent() instanceof GrLoopStatement && statement == ((GrLoopStatement)statement.getParent()).getBody() || diff --git a/plugins/groovy/src/org/jetbrains/plugins/groovy/refactoring/introduce/variable/GrIntroduceVariableHandler.java b/plugins/groovy/src/org/jetbrains/plugins/groovy/refactoring/introduce/variable/GrIntroduceVariableHandler.java index cd2d27b5bdbc..39fac55e7348 100644 --- a/plugins/groovy/src/org/jetbrains/plugins/groovy/refactoring/introduce/variable/GrIntroduceVariableHandler.java +++ b/plugins/groovy/src/org/jetbrains/plugins/groovy/refactoring/introduce/variable/GrIntroduceVariableHandler.java @@ -13,24 +13,16 @@ * See the License for the specific language governing permissions and * limitations under the License. */ - package org.jetbrains.plugins.groovy.refactoring.introduce.variable; -import com.intellij.openapi.actionSystem.Shortcut; import com.intellij.openapi.editor.Editor; import com.intellij.openapi.editor.RangeMarker; -import com.intellij.openapi.keymap.Keymap; -import com.intellij.openapi.keymap.KeymapManager; -import com.intellij.openapi.keymap.KeymapUtil; import com.intellij.openapi.util.Pass; import com.intellij.psi.PsiElement; import com.intellij.psi.PsiModifier; -import com.intellij.psi.PsiType; import com.intellij.refactoring.HelpID; import com.intellij.refactoring.introduce.inplace.OccurrencesChooser; -import com.intellij.refactoring.util.CanonicalTypes; import org.jetbrains.annotations.NotNull; -import org.jetbrains.annotations.Nullable; import org.jetbrains.plugins.groovy.codeInspection.utils.ControlFlowUtils; import org.jetbrains.plugins.groovy.lang.psi.GrControlFlowOwner; import org.jetbrains.plugins.groovy.lang.psi.GroovyFileBase; @@ -48,10 +40,8 @@ import org.jetbrains.plugins.groovy.refactoring.introduce.GrIntroduceContext; import org.jetbrains.plugins.groovy.refactoring.introduce.GrIntroduceHandlerBase; import org.jetbrains.plugins.groovy.refactoring.introduce.StringPartInfo; -import java.util.List; - /** - * @author ilyas + * Created by Max Medvedev on 10/29/13 */ public class GrIntroduceVariableHandler extends GrIntroduceHandlerBase { public static final String DUMMY_NAME = "________________xxx_________________"; @@ -129,8 +119,7 @@ public class GrIntroduceVariableHandler extends GrIntroduceHandlerBase occurrenceMarkers, - RangeMarker varRangeMarker, RangeMarker expressionRangeMarker, - RangeMarker stringPartRangeMarker) { - context.getEditor().getCaretModel().moveToOffset(var.getTextOffset()); - GrInplaceVariableIntroducer introducer = new GrInplaceVariableIntroducer(var, context.getEditor(), context.getProject(), REFACTORING_NAME, occurrenceMarkers, var); - introducer.setAdvertisementText(getAdvertisementText(var.getDeclaredType() != null)); - - return introducer; - } - - @Nullable - private static String getAdvertisementText(final boolean hasTypeSuggestion) { - final Keymap keymap = KeymapManager.getInstance().getActiveKeymap(); - if (hasTypeSuggestion) { - final Shortcut[] shortcuts = keymap.getShortcuts("PreviousTemplateVariable"); - if (shortcuts.length > 0) { - return "Press " + KeymapUtil.getShortcutText(shortcuts[0]) + " to change type"; - } - } - return null; - } - - @Override - protected GroovyIntroduceVariableSettings getSettingsForInplace(final GrIntroduceContext context, final OccurrencesChooser.ReplaceChoice choice) { - return new GroovyIntroduceVariableSettings() { - private final CanonicalTypes.Type myType; - private final String myName; - - - { - GrExpression expression = context.getExpression(); - StringPartInfo stringPart = context.getStringPart(); - GrVariable var = context.getVar(); - PsiType type = expression != null ? expression.getType() : - var != null ? var.getType() : - stringPart != null ? stringPart.getLiteral().getType() : - null; - myType = type != null ?CanonicalTypes.createTypeWrapper(type) : null; - - myName = new GrVariableNameSuggester(context, new GroovyVariableValidator(context)).suggestNames().iterator().next(); - } - - + protected GrInplaceVariableIntroducer getIntroducer(@NotNull GrIntroduceContext context, OccurrencesChooser.ReplaceChoice choice) { + return new GrInplaceVariableIntroducer(getRefactoringName(), choice, context) { @Override - public boolean isDeclareFinal() { - return false; - } - - @Nullable - @Override - public String getName() { - return myName; - } - - @Override - public boolean replaceAllOccurrences() { - return choice == OccurrencesChooser.ReplaceChoice.ALL; - } - - @Nullable - @Override - public PsiType getSelectedType() { - return myType != null ? myType.getType(context.getPlace(), context.getPlace().getManager()) : null; + protected GrVariable runRefactoring(GrIntroduceContext context, GroovyIntroduceVariableSettings settings, boolean processUsages) { + return processExpression(context, settings, processUsages); } }; } @@ -231,24 +159,31 @@ public class GrIntroduceVariableHandler extends GrIntroduceHandlerBase + + diff --git a/plugins/hg4idea/src/org/zmlx/hg4idea/log/HgContentRevisionFactory.java b/plugins/hg4idea/src/org/zmlx/hg4idea/log/HgContentRevisionFactory.java new file mode 100644 index 000000000000..777cad412c59 --- /dev/null +++ b/plugins/hg4idea/src/org/zmlx/hg4idea/log/HgContentRevisionFactory.java @@ -0,0 +1,58 @@ +/* + * 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. + */ +package org.zmlx.hg4idea.log; + +import com.intellij.openapi.components.ServiceManager; +import com.intellij.openapi.project.Project; +import com.intellij.openapi.vcs.changes.ContentRevision; +import com.intellij.openapi.vfs.VirtualFile; +import com.intellij.vcs.log.ContentRevisionFactory; +import com.intellij.vcs.log.Hash; +import org.jetbrains.annotations.NotNull; +import org.zmlx.hg4idea.HgContentRevision; +import org.zmlx.hg4idea.HgFile; +import org.zmlx.hg4idea.HgRevisionNumber; + +import java.io.File; + +/** +* +*/ +public class HgContentRevisionFactory extends ContentRevisionFactory { + + @NotNull private final Project myProject; + + @SuppressWarnings("UnusedDeclaration") + private HgContentRevisionFactory(@NotNull Project project) { + myProject = project; + } + + public static HgContentRevisionFactory getInstance(Project project) { + return ServiceManager.getService(project, HgContentRevisionFactory.class); + } + + @NotNull + @Override + public ContentRevision createRevision(@NotNull VirtualFile file, @NotNull Hash hash) { + return new HgContentRevision(myProject, new HgFile(myProject, file), HgRevisionNumber.getInstance("", hash.asString())); + } + + @NotNull + @Override + public ContentRevision createRevision(@NotNull VirtualFile root, @NotNull String path, @NotNull Hash hash) { + return new HgContentRevision(myProject, new HgFile(root, new File(path)), HgRevisionNumber.getInstance("", hash.asString())); + } +} diff --git a/plugins/hg4idea/src/org/zmlx/hg4idea/util/HgHistoryUtil.java b/plugins/hg4idea/src/org/zmlx/hg4idea/util/HgHistoryUtil.java index a5315c9bdc2a..f78d8fc23ce6 100644 --- a/plugins/hg4idea/src/org/zmlx/hg4idea/util/HgHistoryUtil.java +++ b/plugins/hg4idea/src/org/zmlx/hg4idea/util/HgHistoryUtil.java @@ -33,6 +33,7 @@ import org.zmlx.hg4idea.*; import org.zmlx.hg4idea.action.HgCommandResultNotifier; import org.zmlx.hg4idea.command.HgLogCommand; import org.zmlx.hg4idea.execution.HgCommandException; +import org.zmlx.hg4idea.log.HgContentRevisionFactory; import org.zmlx.hg4idea.provider.HgCommittedChangeList; import java.io.File; @@ -61,7 +62,7 @@ public class HgHistoryUtil { return ContainerUtil.mapNotNull(result, new Function() { @Override public VcsFullCommitDetails fun(HgCommittedChangeList record) { - return createCommit(root, record); + return createCommit(project, root, record); } }); } @@ -169,7 +170,7 @@ public class HgHistoryUtil { } @NotNull - private static VcsFullCommitDetails createCommit(@NotNull VirtualFile root, + private static VcsFullCommitDetails createCommit(@NotNull Project project, @NotNull VirtualFile root, @NotNull HgCommittedChangeList record) { final VcsLogObjectsFactory factory = ServiceManager.getService(VcsLogObjectsFactory.class); @@ -185,7 +186,7 @@ public class HgHistoryUtil { revNumber.getSubject(), revNumber.getAuthor(), "", revNumber.getCommitMessage(), record.getCommitterName(), "", record.getCommitDate().getTime(), - ContainerUtil.newArrayList(record.getChanges())); + ContainerUtil.newArrayList(record.getChanges()), HgContentRevisionFactory.getInstance(project)); } @Nullable diff --git a/python/helpers/pycharm_generator_utils/constants.py b/python/helpers/pycharm_generator_utils/constants.py index d50f7048c924..6b77e73049b9 100644 --- a/python/helpers/pycharm_generator_utils/constants.py +++ b/python/helpers/pycharm_generator_utils/constants.py @@ -224,10 +224,10 @@ SIMPLE_VALUE_RE = re.compile( ########################### parsing ########################################################### if version[0] < 3: - from pyparsing import * + from pycharm_generator_utils.pyparsing import * else: #noinspection PyUnresolvedReferences - from pyparsing_py3 import * + from pycharm_generator_utils.pyparsing_py3 import * # grammar to parse parameter lists diff --git a/python/psi-api/src/com/jetbrains/python/PyNames.java b/python/psi-api/src/com/jetbrains/python/PyNames.java index e93a12099cdb..81c05df64174 100644 --- a/python/psi-api/src/com/jetbrains/python/PyNames.java +++ b/python/psi-api/src/com/jetbrains/python/PyNames.java @@ -169,10 +169,12 @@ public class PyNames { "__all__", "__author__", "__bases__", + "__defaults__", "__dict__", "__doc__", "__docformat__", "__file__", + "__kwdefaults__", "__members__", "__metaclass__", "__mod__", @@ -304,6 +306,7 @@ public class PyNames { .put("__rdivmod__", _self_other_descr) .put("__reduce__", _only_self_descr) .put("__repr__", _only_self_descr) + .put("__reversed__", _only_self_descr) .put("__rfloordiv__", _self_other_descr) .put("__rlshift__", _self_other_descr) .put("__rmod__", _self_other_descr) @@ -338,6 +341,9 @@ public class PyNames { public static ImmutableMap PY3_BUILTIN_METHODS = ImmutableMap.builder() .putAll(BuiltinMethods) .put("__bool__", _only_self_descr) + .put("__bytes__", _only_self_descr) + .put("__format__", new BuiltinDescription("(self, format_spec)")) + .put("__round__", new BuiltinDescription("(self, n=None)")) .build(); public static ImmutableMap getBuiltinMethods(LanguageLevel level) { diff --git a/python/src/com/jetbrains/python/projectView/PyTreeStructureProvider.java b/python/src/com/jetbrains/python/projectView/PyTreeStructureProvider.java index a408f1335fa9..ae923ed2d7e8 100644 --- a/python/src/com/jetbrains/python/projectView/PyTreeStructureProvider.java +++ b/python/src/com/jetbrains/python/projectView/PyTreeStructureProvider.java @@ -17,15 +17,21 @@ package com.jetbrains.python.projectView; import com.intellij.ide.projectView.SelectableTreeStructureProvider; import com.intellij.ide.projectView.ViewSettings; +import com.intellij.ide.projectView.impl.nodes.NamedLibraryElementNode; +import com.intellij.ide.projectView.impl.nodes.PsiDirectoryNode; import com.intellij.ide.projectView.impl.nodes.PsiFileNode; import com.intellij.ide.util.treeView.AbstractTreeNode; import com.intellij.openapi.project.DumbAware; +import com.intellij.openapi.roots.JdkOrderEntry; +import com.intellij.openapi.roots.LibraryOrSdkOrderEntry; +import com.intellij.psi.PsiDirectory; import com.intellij.psi.PsiElement; import com.intellij.psi.PsiFile; import com.intellij.psi.util.PsiTreeUtil; import com.jetbrains.python.psi.PyDocStringOwner; import com.jetbrains.python.psi.PyFile; import com.jetbrains.python.psi.PyFunction; +import com.jetbrains.python.sdk.PythonSdkType; import java.util.ArrayList; import java.util.Collection; @@ -37,6 +43,9 @@ import java.util.List; public class PyTreeStructureProvider implements SelectableTreeStructureProvider, DumbAware { @Override public Collection modify(AbstractTreeNode parent, Collection children, ViewSettings settings) { + if (parent instanceof NamedLibraryElementNode) { + return hideSkeletons((NamedLibraryElementNode)parent, children); + } if (settings.isShowMembers()) { List newChildren = new ArrayList(); for (AbstractTreeNode child : children) { @@ -52,6 +61,25 @@ public class PyTreeStructureProvider implements SelectableTreeStructureProvider, return children; } + protected Collection hideSkeletons(NamedLibraryElementNode parent, Collection children) { + LibraryOrSdkOrderEntry orderEntry = parent.getValue().getOrderEntry(); + if (orderEntry instanceof JdkOrderEntry) { + List newChildren = new ArrayList(); + for (AbstractTreeNode child : children) { + if (child instanceof PsiDirectoryNode) { + PsiDirectory directory = ((PsiDirectoryNode)child).getValue(); + PsiDirectory dirParent = directory.getParent(); + if (dirParent != null && dirParent.getName().equals(PythonSdkType.SKELETON_DIR_NAME)) { + continue; + } + } + newChildren.add(child); + } + return newChildren; + } + return children; + } + @Override public Object getData(Collection selected, String dataName) { return null; diff --git a/python/src/com/jetbrains/python/sdk/flavors/VirtualEnvSdkFlavor.java b/python/src/com/jetbrains/python/sdk/flavors/VirtualEnvSdkFlavor.java index 26a215da6436..5bdecd7a521c 100644 --- a/python/src/com/jetbrains/python/sdk/flavors/VirtualEnvSdkFlavor.java +++ b/python/src/com/jetbrains/python/sdk/flavors/VirtualEnvSdkFlavor.java @@ -17,9 +17,9 @@ package com.jetbrains.python.sdk.flavors; import com.intellij.ide.DataManager; import com.intellij.openapi.actionSystem.CommonDataKeys; -import com.intellij.openapi.actionSystem.PlatformDataKeys; import com.intellij.openapi.project.Project; import com.intellij.openapi.util.SystemInfo; +import com.intellij.openapi.util.io.FileUtil; import com.intellij.openapi.util.text.StringUtil; import com.intellij.openapi.vfs.LocalFileSystem; import com.intellij.openapi.vfs.VirtualFile; @@ -67,7 +67,7 @@ public class VirtualEnvSdkFlavor extends CPythonSdkFlavor { public static VirtualFile getDefaultLocation() { final String path = System.getenv().get("WORKON_HOME"); if (!StringUtil.isEmpty(path)) { - return LocalFileSystem.getInstance().findFileByPath(path.replace('\\','/')); + return LocalFileSystem.getInstance().findFileByPath(FileUtil.expandUserHome(path).replace('\\','/')); } final VirtualFile userHome = LocalFileSystem.getInstance().findFileByPath(SystemProperties.getUserHome().replace('\\','/')); diff --git a/python/testData/inspections/PyArgumentListInspection/dictFromKeys.py b/python/testData/inspections/PyArgumentListInspection/dictFromKeys.py new file mode 100644 index 000000000000..e089bef33c2f --- /dev/null +++ b/python/testData/inspections/PyArgumentListInspection/dictFromKeys.py @@ -0,0 +1,2 @@ +print(dict.fromkeys()) +print(dict.fromkeys(['foo', 'bar'])) diff --git a/python/testData/inspections/PyArgumentListInspection/unicodeConstructor.py b/python/testData/inspections/PyArgumentListInspection/unicodeConstructor.py new file mode 100644 index 000000000000..b47f64aeb7d5 --- /dev/null +++ b/python/testData/inspections/PyArgumentListInspection/unicodeConstructor.py @@ -0,0 +1,5 @@ +print(unicode()) +print(unicode('')) +print(unicode('', 'utf-8')) +print(unicode('', 'utf-8', 'ignore')) +print(unicode('', 'utf-8', 'ignore', foo)) diff --git a/python/testSrc/com/jetbrains/python/inspections/PyArgumentListInspectionTest.java b/python/testSrc/com/jetbrains/python/inspections/PyArgumentListInspectionTest.java index d89792bdb079..affc095d1c3a 100644 --- a/python/testSrc/com/jetbrains/python/inspections/PyArgumentListInspectionTest.java +++ b/python/testSrc/com/jetbrains/python/inspections/PyArgumentListInspectionTest.java @@ -158,4 +158,14 @@ public class PyArgumentListInspectionTest extends PyTestCase { public void testPropertyReturnsCallable() { doTest(); } + + // PY-11162 + public void testUnicodeConstructor() { + doTest(); + } + + // PY-11169 + public void testDictFromKeys() { + doTest(); + } }