From 22804bf0ff3285972a53e0f8388ae82b27cd748c Mon Sep 17 00:00:00 2001 From: Yaroslav Lepenkin Date: Fri, 5 Dec 2014 14:14:08 +0200 Subject: [PATCH 01/22] JavaCodeStyleSettings: do not store additional values, when setting is imported. 1. import only when legacy setting is not default, when importing set it to default to let it happen only once 2. removed legacy boolean value from settings --- .../psi/codeStyle/JavaCodeStyleSettings.java | 17 +++++++++-------- 1 file changed, 9 insertions(+), 8 deletions(-) diff --git a/java/java-impl/src/com/intellij/psi/codeStyle/JavaCodeStyleSettings.java b/java/java-impl/src/com/intellij/psi/codeStyle/JavaCodeStyleSettings.java index f37d74bf9f72..fbf3b77ddf20 100644 --- a/java/java-impl/src/com/intellij/psi/codeStyle/JavaCodeStyleSettings.java +++ b/java/java-impl/src/com/intellij/psi/codeStyle/JavaCodeStyleSettings.java @@ -41,8 +41,6 @@ public class JavaCodeStyleSettings extends CustomCodeStyleSettings { public static final int FULLY_QUALIFY_NAMES_ALWAYS = 2; public static final int SHORTEN_NAMES_ALWAYS_AND_ADD_IMPORT = 3; - public boolean LEGACY_SETTING_USE_FQ_CLASS_NAMES_IN_JAVADOC_IMPORTED = false; - public int CLASS_NAMES_IN_JAVADOC = FULLY_QUALIFY_NAMES_IF_NOT_IMPORTED; public boolean useFqNamesInJavadocAlways() { @@ -51,12 +49,15 @@ public class JavaCodeStyleSettings extends CustomCodeStyleSettings { @Override public void importLegacySettings() { - if (!LEGACY_SETTING_USE_FQ_CLASS_NAMES_IN_JAVADOC_IMPORTED) { - CodeStyleSettings settings = getContainer(); - if (!settings.USE_FQ_CLASS_NAMES_IN_JAVADOC) { - CLASS_NAMES_IN_JAVADOC = SHORTEN_NAMES_ALWAYS_AND_ADD_IMPORT; - } - LEGACY_SETTING_USE_FQ_CLASS_NAMES_IN_JAVADOC_IMPORTED = true; + importLegacyUseFqClassNamesInJavadocSetting(); + } + + private void importLegacyUseFqClassNamesInJavadocSetting() { + CodeStyleSettings settings = getContainer(); + boolean isDefaultValue = settings.USE_FQ_CLASS_NAMES_IN_JAVADOC; + if (!isDefaultValue) { + CLASS_NAMES_IN_JAVADOC = SHORTEN_NAMES_ALWAYS_AND_ADD_IMPORT; + settings.USE_FQ_CLASS_NAMES_IN_JAVADOC = true; } } } From dc24f99727c2cb8cd40771b284fa06b9fa766b60 Mon Sep 17 00:00:00 2001 From: Nadya Zabrodina Date: Fri, 5 Dec 2014 14:18:11 +0300 Subject: [PATCH 02/22] test fix changed --- .../src/org/zmlx/hg4idea/repo/HgRepositoryImpl.java | 1 - .../hg4idea/test/repo/HgRealRepositoryReaderTest.java | 9 +++++---- 2 files changed, 5 insertions(+), 5 deletions(-) diff --git a/plugins/hg4idea/src/org/zmlx/hg4idea/repo/HgRepositoryImpl.java b/plugins/hg4idea/src/org/zmlx/hg4idea/repo/HgRepositoryImpl.java index 7ae35a1105ba..94860b9361b7 100644 --- a/plugins/hg4idea/src/org/zmlx/hg4idea/repo/HgRepositoryImpl.java +++ b/plugins/hg4idea/src/org/zmlx/hg4idea/repo/HgRepositoryImpl.java @@ -61,7 +61,6 @@ public class HgRepositoryImpl extends RepositoryImpl implements HgRepository { private HgRepositoryImpl(@NotNull VirtualFile rootDir, @NotNull HgVcs vcs, @NotNull Disposable parentDisposable) { super(vcs.getProject(), rootDir, parentDisposable); - rootDir.refresh(false, true); myHgDir = rootDir.findChild(HgUtil.DOT_HG); assert myHgDir != null : ".hg directory wasn't found under " + rootDir.getPresentableUrl(); myReader = new HgRepositoryReader(vcs, VfsUtilCore.virtualToIoFile(myHgDir)); diff --git a/plugins/hg4idea/testSrc/hg4idea/test/repo/HgRealRepositoryReaderTest.java b/plugins/hg4idea/testSrc/hg4idea/test/repo/HgRealRepositoryReaderTest.java index 0792a96a28d1..cf72883c7994 100644 --- a/plugins/hg4idea/testSrc/hg4idea/test/repo/HgRealRepositoryReaderTest.java +++ b/plugins/hg4idea/testSrc/hg4idea/test/repo/HgRealRepositoryReaderTest.java @@ -59,11 +59,12 @@ public class HgRealRepositoryReaderTest extends HgPlatformTest { public void testBranches() { VcsTestUtil.assertEqualCollections(myRepositoryReader.readBranches().keySet(), - Arrays.asList("default", "branchA", "branchB")); + Arrays.asList("default", "branchA", "branchB")); } public void testOpenedBranches() { cd(myRepository); + myRepository.refresh(false, true); HgRepository hgRepository = HgRepositoryImpl.getInstance(myRepository, myProject, myProject); hg("up branchA"); hg("commit -m 'close branch' --close-branch"); @@ -74,12 +75,12 @@ public class HgRealRepositoryReaderTest extends HgPlatformTest { public void testTags() { VcsTestUtil.assertEqualCollections(HgUtil.getNamesWithoutHashes(myRepositoryReader.readTags()), - Arrays.asList("tag1", "tag2")); + Arrays.asList("tag1", "tag2")); } public void testLocalTags() { VcsTestUtil.assertEqualCollections(HgUtil.getNamesWithoutHashes(myRepositoryReader.readLocalTags()), - Arrays.asList("localTag")); + Arrays.asList("localTag")); } public void testCurrentBookmark() { @@ -89,7 +90,7 @@ public class HgRealRepositoryReaderTest extends HgPlatformTest { public void testBookmarks() { VcsTestUtil.assertEqualCollections(HgUtil.getNamesWithoutHashes(myRepositoryReader.readBookmarks()), - Arrays.asList("A_BookMark", "B_BookMark", "C_BookMark")); + Arrays.asList("A_BookMark", "B_BookMark", "C_BookMark")); } private void createBranchesAndTags() { From 22a0deb9d24e604e5fe01d76a6c4588e415c22d8 Mon Sep 17 00:00:00 2001 From: Nadya Zabrodina Date: Fri, 5 Dec 2014 14:27:43 +0300 Subject: [PATCH 03/22] Vcs root detector,finder and notifier tests fixed --- .../intellij/openapi/vcs/roots/VcsIntegrationEnablerTest.java | 1 - .../com/intellij/openapi/vcs/roots/VcsRootDetectorTest.java | 3 +++ .../intellij/openapi/vcs/roots/VcsRootErrorsFinderTest.java | 1 + .../com/intellij/openapi/vcs/roots/VcsRootPlatformTest.java | 3 +++ 4 files changed, 7 insertions(+), 1 deletion(-) diff --git a/platform/vcs-impl/testSrc/com/intellij/openapi/vcs/roots/VcsIntegrationEnablerTest.java b/platform/vcs-impl/testSrc/com/intellij/openapi/vcs/roots/VcsIntegrationEnablerTest.java index ef04ac562f97..fce52463e7e5 100644 --- a/platform/vcs-impl/testSrc/com/intellij/openapi/vcs/roots/VcsIntegrationEnablerTest.java +++ b/platform/vcs-impl/testSrc/com/intellij/openapi/vcs/roots/VcsIntegrationEnablerTest.java @@ -20,7 +20,6 @@ import com.intellij.notification.NotificationType; import com.intellij.openapi.util.io.FileUtil; import com.intellij.openapi.vcs.*; import com.intellij.openapi.vcs.changes.committed.MockAbstractVcs; -import com.intellij.openapi.vfs.LocalFileSystem; import com.intellij.openapi.vfs.VirtualFile; import com.intellij.testFramework.PlatformTestCase; import com.intellij.util.Function; diff --git a/platform/vcs-impl/testSrc/com/intellij/openapi/vcs/roots/VcsRootDetectorTest.java b/platform/vcs-impl/testSrc/com/intellij/openapi/vcs/roots/VcsRootDetectorTest.java index fed3cf3341d1..debc963c6d5a 100644 --- a/platform/vcs-impl/testSrc/com/intellij/openapi/vcs/roots/VcsRootDetectorTest.java +++ b/platform/vcs-impl/testSrc/com/intellij/openapi/vcs/roots/VcsRootDetectorTest.java @@ -178,6 +178,9 @@ public class VcsRootDetectorTest extends VcsRootPlatformTest { @NotNull String... expectedPaths) throws IOException { initProject(vcsRootConfiguration); + if (startDir != null) { + startDir.refresh(false, true); + } Collection vcsRoots = detect(startDir); assertRoots(Arrays.asList(expectedPaths), getPaths( ContainerUtil.filter(vcsRoots, new Condition() { diff --git a/platform/vcs-impl/testSrc/com/intellij/openapi/vcs/roots/VcsRootErrorsFinderTest.java b/platform/vcs-impl/testSrc/com/intellij/openapi/vcs/roots/VcsRootErrorsFinderTest.java index 198cdbb92b89..9a91906e1fc2 100644 --- a/platform/vcs-impl/testSrc/com/intellij/openapi/vcs/roots/VcsRootErrorsFinderTest.java +++ b/platform/vcs-impl/testSrc/com/intellij/openapi/vcs/roots/VcsRootErrorsFinderTest.java @@ -178,6 +178,7 @@ public class VcsRootErrorsFinderTest extends VcsRootPlatformTest { Collection expected = new ArrayList(); expected.addAll(unregAll(vcsRootConfiguration.getUnregErrors())); expected.addAll(extraAll(vcsRootConfiguration.getExtraErrors())); + myProjectRoot.refresh(false, true); Collection actual = ContainerUtil.filter(new VcsRootErrorsFinder(myProject).find(), new Condition() { @Override public boolean value(VcsRootError error) { diff --git a/platform/vcs-impl/testSrc/com/intellij/openapi/vcs/roots/VcsRootPlatformTest.java b/platform/vcs-impl/testSrc/com/intellij/openapi/vcs/roots/VcsRootPlatformTest.java index 8b04b601f9ef..70ae96eea8da 100644 --- a/platform/vcs-impl/testSrc/com/intellij/openapi/vcs/roots/VcsRootPlatformTest.java +++ b/platform/vcs-impl/testSrc/com/intellij/openapi/vcs/roots/VcsRootPlatformTest.java @@ -86,6 +86,7 @@ public abstract class VcsRootPlatformTest extends UsefulTestCase { .getInstance()); myRootModel = ((ModuleRootManagerImpl)ModuleRootManager.getInstance(module)).getRootModel(); mkdir(myRepositoryFolderName); + myProjectRoot.refresh(false, true); myRepository = myProjectRoot.findChild(myRepositoryFolderName); myVcs = new MockAbstractVcs(myProject); myVcsManager = (ProjectLevelVcsManagerImpl)ProjectLevelVcsManager.getInstance(myProject); @@ -109,6 +110,7 @@ public abstract class VcsRootPlatformTest extends UsefulTestCase { point.registerExtension(myExtension); myVcsManager.registerVcs(myVcs); myVcsName = myVcs.getName(); + myRepository.refresh(false, true); } private static ExtensionPoint getExtensionPoint() { @@ -146,6 +148,7 @@ public abstract class VcsRootPlatformTest extends UsefulTestCase { createProjectStructure(myProject, contentRoots); if (!contentRoots.isEmpty()) { for (String root : contentRoots) { + myProjectRoot.refresh(false, true); VirtualFile f = myProjectRoot.findFileByRelativePath(root); if (f != null) { myRootModel.addContentEntry(f); From 0e22cfc998b8112a70d1f7b14648c57709a46cb4 Mon Sep 17 00:00:00 2001 From: Nadya Zabrodina Date: Fri, 5 Dec 2014 14:31:01 +0300 Subject: [PATCH 04/22] compile fixed --- .../intellij/openapi/vcs/roots/VcsIntegrationEnablerTest.java | 1 + 1 file changed, 1 insertion(+) diff --git a/platform/vcs-impl/testSrc/com/intellij/openapi/vcs/roots/VcsIntegrationEnablerTest.java b/platform/vcs-impl/testSrc/com/intellij/openapi/vcs/roots/VcsIntegrationEnablerTest.java index fce52463e7e5..ef04ac562f97 100644 --- a/platform/vcs-impl/testSrc/com/intellij/openapi/vcs/roots/VcsIntegrationEnablerTest.java +++ b/platform/vcs-impl/testSrc/com/intellij/openapi/vcs/roots/VcsIntegrationEnablerTest.java @@ -20,6 +20,7 @@ import com.intellij.notification.NotificationType; import com.intellij.openapi.util.io.FileUtil; import com.intellij.openapi.vcs.*; import com.intellij.openapi.vcs.changes.committed.MockAbstractVcs; +import com.intellij.openapi.vfs.LocalFileSystem; import com.intellij.openapi.vfs.VirtualFile; import com.intellij.testFramework.PlatformTestCase; import com.intellij.util.Function; From 315f1b9977e4cfd0f57d2f4984c9cc78f23b74be Mon Sep 17 00:00:00 2001 From: Andrey Starovoyt Date: Fri, 5 Dec 2014 14:25:18 +0300 Subject: [PATCH 05/22] reduce scope of try postfix template (2) after review IDEA-132878 --- .../TryStatementPostfixTemplate.java | 38 ++++++++++--------- .../templates/try/constructorStatement.java | 5 +++ .../try/constructorStatement_after.java | 9 +++++ .../templates/try/declarationStatement.java | 5 +++ .../try/declarationStatement_after.java | 9 +++++ .../templates/try/expressionInMethodBody.java | 9 +++++ .../try/expressionInMethodBody_after.java | 13 +++++++ .../templates/try/incompleteStatement.java | 11 ++++++ .../try/incompleteStatement_after.java | 11 ++++++ .../try/simpleWithThrowsCheckedException.java | 9 +++++ ...impleWithThrowsCheckedException_after.java | 13 +++++++ .../templates/TryPostfixTemplateTest.java | 20 ++++++++++ 12 files changed, 135 insertions(+), 17 deletions(-) create mode 100644 java/java-tests/testData/codeInsight/template/postfix/templates/try/constructorStatement.java create mode 100644 java/java-tests/testData/codeInsight/template/postfix/templates/try/constructorStatement_after.java create mode 100644 java/java-tests/testData/codeInsight/template/postfix/templates/try/declarationStatement.java create mode 100644 java/java-tests/testData/codeInsight/template/postfix/templates/try/declarationStatement_after.java create mode 100644 java/java-tests/testData/codeInsight/template/postfix/templates/try/expressionInMethodBody.java create mode 100644 java/java-tests/testData/codeInsight/template/postfix/templates/try/expressionInMethodBody_after.java create mode 100644 java/java-tests/testData/codeInsight/template/postfix/templates/try/incompleteStatement.java create mode 100644 java/java-tests/testData/codeInsight/template/postfix/templates/try/incompleteStatement_after.java create mode 100644 java/java-tests/testData/codeInsight/template/postfix/templates/try/simpleWithThrowsCheckedException.java create mode 100644 java/java-tests/testData/codeInsight/template/postfix/templates/try/simpleWithThrowsCheckedException_after.java diff --git a/java/java-impl/src/com/intellij/codeInsight/template/postfix/templates/TryStatementPostfixTemplate.java b/java/java-impl/src/com/intellij/codeInsight/template/postfix/templates/TryStatementPostfixTemplate.java index 8ed37ceb01a4..0044c599a851 100644 --- a/java/java-impl/src/com/intellij/codeInsight/template/postfix/templates/TryStatementPostfixTemplate.java +++ b/java/java-impl/src/com/intellij/codeInsight/template/postfix/templates/TryStatementPostfixTemplate.java @@ -16,37 +16,41 @@ package com.intellij.codeInsight.template.postfix.templates; import com.intellij.codeInsight.generation.surroundWith.JavaWithTryCatchSurrounder; +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.openapi.util.TextRange; import com.intellij.psi.*; import com.intellij.psi.util.PsiTreeUtil; +import com.intellij.psi.util.PsiUtil; import com.intellij.util.ArrayUtil; import org.jetbrains.annotations.NotNull; -import org.jetbrains.annotations.Nullable; -import static com.intellij.codeInsight.template.postfix.templates.PostfixTemplatesUtils.selectorTopmost; -import static com.intellij.codeInsight.template.postfix.util.JavaPostfixTemplatesUtils.JAVA_PSI_INFO; - -public class TryStatementPostfixTemplate extends PostfixTemplateWithExpressionSelector { - - public static Condition HAS_TYPE = new Condition() { - @Override - public boolean value(@Nullable PsiElement element) { - return element instanceof PsiExpression && ((PsiExpression)element).getType() != null; - } - }; +public class TryStatementPostfixTemplate extends PostfixTemplate { protected TryStatementPostfixTemplate() { - super("try", "try { exp } catch(Exception e)", JAVA_PSI_INFO, selectorTopmost(HAS_TYPE)); + super("try", "try { exp } catch(Exception e)"); } + @Override + public boolean isApplicable(@NotNull PsiElement context, @NotNull Document copyDocument, int newOffset) { + PsiStatement statementParent = PsiTreeUtil.getNonStrictParentOfType(context, PsiStatement.class); + if (statementParent == null || + newOffset != statementParent.getTextRange().getEndOffset()) return false; + + if (statementParent instanceof PsiDeclarationStatement) return true; + + if (statementParent instanceof PsiExpressionStatement) { + PsiExpression expression = ((PsiExpressionStatement)statementParent).getExpression(); + return null != expression.getType(); + } + + return false; + } @Override - public void expandForChooseExpression(@NotNull PsiElement context, @NotNull Editor editor) { - PsiExpression expr = (PsiExpression)context; - PsiStatement statement = PsiTreeUtil.getParentOfType(expr, PsiStatement.class, false); + public void expand(@NotNull PsiElement context, @NotNull Editor editor) { + PsiStatement statement = PsiTreeUtil.getNonStrictParentOfType(context, PsiStatement.class); assert statement != null; PsiFile file = statement.getContainingFile(); diff --git a/java/java-tests/testData/codeInsight/template/postfix/templates/try/constructorStatement.java b/java/java-tests/testData/codeInsight/template/postfix/templates/try/constructorStatement.java new file mode 100644 index 000000000000..05edd3342c64 --- /dev/null +++ b/java/java-tests/testData/codeInsight/template/postfix/templates/try/constructorStatement.java @@ -0,0 +1,5 @@ +public class Foo { + void m() { + new Object().try + } +} \ No newline at end of file diff --git a/java/java-tests/testData/codeInsight/template/postfix/templates/try/constructorStatement_after.java b/java/java-tests/testData/codeInsight/template/postfix/templates/try/constructorStatement_after.java new file mode 100644 index 000000000000..807cf33709ec --- /dev/null +++ b/java/java-tests/testData/codeInsight/template/postfix/templates/try/constructorStatement_after.java @@ -0,0 +1,9 @@ +public class Foo { + void m() { + try { + new Object() + } catch (Exception e) { + e.printStackTrace(); + } + } +} \ No newline at end of file diff --git a/java/java-tests/testData/codeInsight/template/postfix/templates/try/declarationStatement.java b/java/java-tests/testData/codeInsight/template/postfix/templates/try/declarationStatement.java new file mode 100644 index 000000000000..ae6f5b02395d --- /dev/null +++ b/java/java-tests/testData/codeInsight/template/postfix/templates/try/declarationStatement.java @@ -0,0 +1,5 @@ +public class Foo { + void m() { + Object obj = new Object().try + } +} \ No newline at end of file diff --git a/java/java-tests/testData/codeInsight/template/postfix/templates/try/declarationStatement_after.java b/java/java-tests/testData/codeInsight/template/postfix/templates/try/declarationStatement_after.java new file mode 100644 index 000000000000..c6c37844fc43 --- /dev/null +++ b/java/java-tests/testData/codeInsight/template/postfix/templates/try/declarationStatement_after.java @@ -0,0 +1,9 @@ +public class Foo { + void m() { + try { + Object obj = new Object() + } catch (Exception e) { + e.printStackTrace(); + } + } +} \ No newline at end of file diff --git a/java/java-tests/testData/codeInsight/template/postfix/templates/try/expressionInMethodBody.java b/java/java-tests/testData/codeInsight/template/postfix/templates/try/expressionInMethodBody.java new file mode 100644 index 000000000000..ab9cacffb71f --- /dev/null +++ b/java/java-tests/testData/codeInsight/template/postfix/templates/try/expressionInMethodBody.java @@ -0,0 +1,9 @@ +public class Foo { + void m() { + doAct() + "aaa".try + } + + String doAct() { + return null; + } +} \ No newline at end of file diff --git a/java/java-tests/testData/codeInsight/template/postfix/templates/try/expressionInMethodBody_after.java b/java/java-tests/testData/codeInsight/template/postfix/templates/try/expressionInMethodBody_after.java new file mode 100644 index 000000000000..ef09a53f103e --- /dev/null +++ b/java/java-tests/testData/codeInsight/template/postfix/templates/try/expressionInMethodBody_after.java @@ -0,0 +1,13 @@ +public class Foo { + void m() { + try { + doAct() + "aaa" + } catch (Exception e) { + e.printStackTrace(); + } + } + + String doAct() { + return null; + } +} \ No newline at end of file diff --git a/java/java-tests/testData/codeInsight/template/postfix/templates/try/incompleteStatement.java b/java/java-tests/testData/codeInsight/template/postfix/templates/try/incompleteStatement.java new file mode 100644 index 000000000000..b12d1eaeb327 --- /dev/null +++ b/java/java-tests/testData/codeInsight/template/postfix/templates/try/incompleteStatement.java @@ -0,0 +1,11 @@ +import java.lang.Exception; + +public class Foo { + void m() { + methodCall(.try + } + + void methodCall(String s) { + + } +} \ No newline at end of file diff --git a/java/java-tests/testData/codeInsight/template/postfix/templates/try/incompleteStatement_after.java b/java/java-tests/testData/codeInsight/template/postfix/templates/try/incompleteStatement_after.java new file mode 100644 index 000000000000..8e1763f0f221 --- /dev/null +++ b/java/java-tests/testData/codeInsight/template/postfix/templates/try/incompleteStatement_after.java @@ -0,0 +1,11 @@ +import java.lang.Exception; + +public class Foo { + void m() { + methodCall(.try + } + + void methodCall(String s) { + + } +} \ No newline at end of file diff --git a/java/java-tests/testData/codeInsight/template/postfix/templates/try/simpleWithThrowsCheckedException.java b/java/java-tests/testData/codeInsight/template/postfix/templates/try/simpleWithThrowsCheckedException.java new file mode 100644 index 000000000000..a28a0e66b63d --- /dev/null +++ b/java/java-tests/testData/codeInsight/template/postfix/templates/try/simpleWithThrowsCheckedException.java @@ -0,0 +1,9 @@ +import java.io.IOException; + +public class Foo { + void m() { + doAct().try + } + + void doAct() throws IOException {} +} \ No newline at end of file diff --git a/java/java-tests/testData/codeInsight/template/postfix/templates/try/simpleWithThrowsCheckedException_after.java b/java/java-tests/testData/codeInsight/template/postfix/templates/try/simpleWithThrowsCheckedException_after.java new file mode 100644 index 000000000000..5c893da1d0be --- /dev/null +++ b/java/java-tests/testData/codeInsight/template/postfix/templates/try/simpleWithThrowsCheckedException_after.java @@ -0,0 +1,13 @@ +import java.io.IOException; + +public class Foo { + void m() { + try { + doAct() + } catch (IOException e) { + e.printStackTrace(); + } + } + + void doAct() throws IOException {} +} \ No newline at end of file diff --git a/java/java-tests/testSrc/com/intellij/codeInsight/template/postfix/templates/TryPostfixTemplateTest.java b/java/java-tests/testSrc/com/intellij/codeInsight/template/postfix/templates/TryPostfixTemplateTest.java index e17d479f0fd5..1b2e9d62c013 100644 --- a/java/java-tests/testSrc/com/intellij/codeInsight/template/postfix/templates/TryPostfixTemplateTest.java +++ b/java/java-tests/testSrc/com/intellij/codeInsight/template/postfix/templates/TryPostfixTemplateTest.java @@ -39,4 +39,24 @@ public class TryPostfixTemplateTest extends PostfixTemplateTestCase { public void testNotResolvedExpression() { doTest(); } + + public void testDeclarationStatement() { + doTest(); + } + + public void testExpressionInMethodBody() { + doTest(); + } + + public void testSimpleWithThrowsCheckedException() { + doTest(); + } + + public void testIncompleteStatement() { + doTest(); + } + + public void testConstructorStatement() { + doTest(); + } } From a92f6b27e4db097d4d9bee0b0d44ad6a8a0163e3 Mon Sep 17 00:00:00 2001 From: "Egor.Ushakov" Date: Fri, 5 Dec 2014 14:43:58 +0300 Subject: [PATCH 06/22] IDEA-80966 Debugger "Resume" button - right next to the "STOP" button - added a separator --- platform/platform-resources/src/idea/LangActions.xml | 1 + 1 file changed, 1 insertion(+) diff --git a/platform/platform-resources/src/idea/LangActions.xml b/platform/platform-resources/src/idea/LangActions.xml index 13cfd5b731c9..2f1324ba9702 100644 --- a/platform/platform-resources/src/idea/LangActions.xml +++ b/platform/platform-resources/src/idea/LangActions.xml @@ -719,6 +719,7 @@ + From f9359d031a425b8753ec261bc868e91059e8d30e Mon Sep 17 00:00:00 2001 From: "Maxim.Mossienko" Date: Fri, 5 Dec 2014 10:56:49 +0100 Subject: [PATCH 07/22] singleton instances for internal file types --- .../src/com/intellij/ide/highlighter/WorkspaceFileType.java | 4 ++++ .../openapi/fileTypes/impl/InternalFileTypeFactory.java | 6 +++--- .../src/com/intellij/ide/highlighter/ModuleFileType.java | 4 ++++ .../src/com/intellij/ide/highlighter/ProjectFileType.java | 4 ++++ 4 files changed, 15 insertions(+), 3 deletions(-) diff --git a/platform/platform-api/src/com/intellij/ide/highlighter/WorkspaceFileType.java b/platform/platform-api/src/com/intellij/ide/highlighter/WorkspaceFileType.java index bff9dc107e43..3d1f3b9d2dea 100644 --- a/platform/platform-api/src/com/intellij/ide/highlighter/WorkspaceFileType.java +++ b/platform/platform-api/src/com/intellij/ide/highlighter/WorkspaceFileType.java @@ -26,9 +26,13 @@ import org.jetbrains.annotations.NotNull; import javax.swing.*; public class WorkspaceFileType implements InternalFileType { + public static final WorkspaceFileType INSTANCE = new WorkspaceFileType(); + @NonNls public static final String DEFAULT_EXTENSION = "iws"; @NonNls public static final String DOT_DEFAULT_EXTENSION = "." + DEFAULT_EXTENSION; + private WorkspaceFileType() {} + @Override @NotNull public String getName() { diff --git a/platform/platform-impl/src/com/intellij/openapi/fileTypes/impl/InternalFileTypeFactory.java b/platform/platform-impl/src/com/intellij/openapi/fileTypes/impl/InternalFileTypeFactory.java index 5224b1309f4d..b7cf3ec1e306 100644 --- a/platform/platform-impl/src/com/intellij/openapi/fileTypes/impl/InternalFileTypeFactory.java +++ b/platform/platform-impl/src/com/intellij/openapi/fileTypes/impl/InternalFileTypeFactory.java @@ -27,8 +27,8 @@ import org.jetbrains.annotations.NotNull; */ public class InternalFileTypeFactory extends FileTypeFactory { public void createFileTypes(@NotNull final FileTypeConsumer consumer) { - consumer.consume(new WorkspaceFileType(), WorkspaceFileType.DEFAULT_EXTENSION); - consumer.consume(new ModuleFileType(), ModuleFileType.DEFAULT_EXTENSION); - consumer.consume(new ProjectFileType(), ProjectFileType.DEFAULT_EXTENSION); + consumer.consume(WorkspaceFileType.INSTANCE, WorkspaceFileType.DEFAULT_EXTENSION); + consumer.consume(ModuleFileType.INSTANCE, ModuleFileType.DEFAULT_EXTENSION); + consumer.consume(ProjectFileType.INSTANCE, ProjectFileType.DEFAULT_EXTENSION); } } diff --git a/platform/projectModel-api/src/com/intellij/ide/highlighter/ModuleFileType.java b/platform/projectModel-api/src/com/intellij/ide/highlighter/ModuleFileType.java index 6cc0f8b21305..5895c2c1fe5c 100644 --- a/platform/projectModel-api/src/com/intellij/ide/highlighter/ModuleFileType.java +++ b/platform/projectModel-api/src/com/intellij/ide/highlighter/ModuleFileType.java @@ -26,9 +26,13 @@ import org.jetbrains.annotations.NotNull; import javax.swing.*; public class ModuleFileType implements InternalFileType { + public static final ModuleFileType INSTANCE = new ModuleFileType(); + @NonNls public static final String DEFAULT_EXTENSION = "iml"; @NonNls public static final String DOT_DEFAULT_EXTENSION = ".iml"; + private ModuleFileType() {} + @Override @NotNull public String getName() { diff --git a/platform/projectModel-api/src/com/intellij/ide/highlighter/ProjectFileType.java b/platform/projectModel-api/src/com/intellij/ide/highlighter/ProjectFileType.java index 347908a22a08..4988159d68b9 100644 --- a/platform/projectModel-api/src/com/intellij/ide/highlighter/ProjectFileType.java +++ b/platform/projectModel-api/src/com/intellij/ide/highlighter/ProjectFileType.java @@ -26,9 +26,13 @@ import org.jetbrains.annotations.NotNull; import javax.swing.*; public class ProjectFileType implements InternalFileType { + public static final ProjectFileType INSTANCE = new ProjectFileType(); + @NonNls public static final String DEFAULT_EXTENSION = "ipr"; @NonNls public static final String DOT_DEFAULT_EXTENSION = ".ipr"; + private ProjectFileType() {} + @Override @NotNull public String getName() { From b199734a0e41f2c44c2eb5301f2fbbb8a3560cec Mon Sep 17 00:00:00 2001 From: "Maxim.Mossienko" Date: Fri, 5 Dec 2014 11:46:59 +0100 Subject: [PATCH 08/22] move check for isProjectOrWorkspaceFile to be after project's isInContent condition, to avoid content loading for non project files via getFileType() content detection (IDEA-133507) --- .../compiler/server/BuildManager.java | 45 ++++++++++--------- 1 file changed, 23 insertions(+), 22 deletions(-) diff --git a/java/compiler/impl/src/com/intellij/compiler/server/BuildManager.java b/java/compiler/impl/src/com/intellij/compiler/server/BuildManager.java index a4dc856755bd..1341b8ff8c69 100644 --- a/java/compiler/impl/src/com/intellij/compiler/server/BuildManager.java +++ b/java/compiler/impl/src/com/intellij/compiler/server/BuildManager.java @@ -254,9 +254,6 @@ public class BuildManager implements ApplicationComponent{ if (!eventFile.isValid()) { return true; // should be deleted } - if (ProjectCoreUtil.isProjectOrWorkspaceFile(eventFile)) { - continue; - } if (project == null) { // lazy init @@ -268,6 +265,10 @@ public class BuildManager implements ApplicationComponent{ } if (fileIndex.isInContent(eventFile)) { + if (ProjectCoreUtil.isProjectOrWorkspaceFile(eventFile)) { + continue; + } + return true; } } @@ -387,9 +388,9 @@ public class BuildManager implements ApplicationComponent{ public void clearState(Project project) { final String projectPath = getProjectPath(project); - + cancelPreloadedBuilds(projectPath); - + synchronized (myProjectDataMap) { final ProjectData data = myProjectDataMap.get(projectPath); if (data != null) { @@ -823,7 +824,7 @@ public class BuildManager implements ApplicationComponent{ private Future, OSProcessHandler>> launchPreloadedBuildProcess(final Project project, SequentialTaskExecutor projectTaskQueue) throws Exception { ensureListening(); - + // launching build process from projectTaskQueue ensures that no other build process for this project is currently running return projectTaskQueue.submit(new Callable, OSProcessHandler>>() { public Pair, OSProcessHandler> call() throws Exception { @@ -845,7 +846,7 @@ public class BuildManager implements ApplicationComponent{ } }); } - + private OSProcessHandler launchBuildProcess(Project project, final int port, final UUID sessionId, boolean requestProjectPreload) throws ExecutionException { final String compilerPath; final String vmExecutablePath; @@ -951,7 +952,7 @@ public class BuildManager implements ApplicationComponent{ cmdLine.addParameter("-Dpreload.project.path=" + FileUtil.toCanonicalPath(getProjectPath(project))); cmdLine.addParameter("-Dpreload.config.path=" + FileUtil.toCanonicalPath(PathManager.getOptionsPath())); } - + final String shouldGenerateIndex = System.getProperty(GlobalOptions.GENERATE_CLASSPATH_INDEX_OPTION); if (shouldGenerateIndex != null) { cmdLine.addParameter("-D"+ GlobalOptions.GENERATE_CLASSPATH_INDEX_OPTION +"=" + shouldGenerateIndex); @@ -975,11 +976,11 @@ public class BuildManager implements ApplicationComponent{ cmdLine.addParameter(option); } } - + if (isProfilingMode) { cmdLine.addParameter("-agentlib:yjpagent=disablej2ee,disablealloc,delay=10000,sessionname=ExternalBuild"); } - + // debugging final int debugPort = Registry.intValue("compiler.process.debug.port"); if (debugPort > 0) { @@ -1016,10 +1017,10 @@ public class BuildManager implements ApplicationComponent{ final List args = provider.getVMArguments(); cmdLine.addParameters(args); } - - @SuppressWarnings("UnnecessaryFullyQualifiedName") + + @SuppressWarnings("UnnecessaryFullyQualifiedName") final Class launcherClass = org.jetbrains.jps.cmdline.Launcher.class; - + final List launcherCp = new ArrayList(); launcherCp.add(ClasspathBootstrap.getResourcePath(launcherClass)); launcherCp.add(compilerPath); @@ -1027,7 +1028,7 @@ public class BuildManager implements ApplicationComponent{ launcherCp.addAll(BuildProcessClasspathManager.getLauncherClasspath(project)); cmdLine.addParameter("-classpath"); cmdLine.addParameter(classpathToString(launcherCp)); - + cmdLine.addParameter(launcherClass.getName()); final List cp = ClasspathBootstrap.getBuildProcessApplicationClasspath(true); @@ -1064,7 +1065,7 @@ public class BuildManager implements ApplicationComponent{ } } }); - + return processHandler; } @@ -1239,7 +1240,7 @@ public class BuildManager implements ApplicationComponent{ @Override public void onTextAvailable(ProcessEvent event, Key outputType) { String text; - + synchronized (this) { if (myStoredLength > 2048) { return; @@ -1250,7 +1251,7 @@ public class BuildManager implements ApplicationComponent{ } myStoredLength += text.length(); } - + try { myOutput.append(text); } @@ -1454,7 +1455,7 @@ public class BuildManager implements ApplicationComponent{ } myPath = list.toArray(); } - + public abstract String getValue(); @Override @@ -1473,12 +1474,12 @@ public class BuildManager implements ApplicationComponent{ public int hashCode() { return Arrays.hashCode(myPath); } - + public static InternedPath create(String path) { - return path.startsWith("/")? new XInternedPath(path) : new WinInternedPath(path); + return path.startsWith("/")? new XInternedPath(path) : new WinInternedPath(path); } } - + private static class WinInternedPath extends InternedPath { private WinInternedPath(String path) { super(path); @@ -1491,7 +1492,7 @@ public class BuildManager implements ApplicationComponent{ // handle case of windows drive letter return name.length() == 2 && name.endsWith(":")? name + "/" : name; } - + final StringBuilder buf = new StringBuilder(); for (int element : myPath) { if (buf.length() > 0) { From 74781374ca4d98866e91f043f8e881c14a07f5c6 Mon Sep 17 00:00:00 2001 From: "Maxim.Mossienko" Date: Fri, 5 Dec 2014 11:59:25 +0100 Subject: [PATCH 09/22] more optimal isProjectOrWorkspaceFile calculation --- .../com/intellij/openapi/project/ProjectUtil.java | 12 ++++++++++-- 1 file changed, 10 insertions(+), 2 deletions(-) diff --git a/platform/lang-api/src/com/intellij/openapi/project/ProjectUtil.java b/platform/lang-api/src/com/intellij/openapi/project/ProjectUtil.java index 0dac0d7d3b0c..df93b434277d 100644 --- a/platform/lang-api/src/com/intellij/openapi/project/ProjectUtil.java +++ b/platform/lang-api/src/com/intellij/openapi/project/ProjectUtil.java @@ -22,6 +22,8 @@ import com.intellij.openapi.fileEditor.UniqueVFilePathBuilder; import com.intellij.openapi.fileTypes.FileType; import com.intellij.openapi.fileTypes.InternalFileType; import com.intellij.openapi.roots.ProjectRootManager; +import com.intellij.openapi.util.Comparing; +import com.intellij.openapi.util.SystemInfoRt; import com.intellij.openapi.util.io.FileUtil; import com.intellij.openapi.vfs.VirtualFile; import com.intellij.openapi.vfs.VirtualFilePathWrapper; @@ -110,8 +112,14 @@ public class ProjectUtil { return isProjectOrWorkspaceFile(file, file.getFileType()); } - public static boolean isProjectOrWorkspaceFile(@NotNull VirtualFile file, @NotNull FileType fileType) { - return fileType instanceof InternalFileType || file.getPath().contains('/' + ProjectCoreUtil.DIRECTORY_BASED_PROJECT_DIR + '/'); + public static boolean isProjectOrWorkspaceFile(@NotNull VirtualFile file, @Nullable FileType fileType) { + if (fileType instanceof InternalFileType) return true; + VirtualFile parent = file.isDirectory() ? file: file.getParent(); + while (parent != null) { + if (Comparing.equal(parent.getNameSequence(), ProjectCoreUtil.DIRECTORY_BASED_PROJECT_DIR, SystemInfoRt.isFileSystemCaseSensitive)) return true; + parent = parent.getParent(); + } + return false; } @NotNull From a845c6c764b5a013df27aa79ac0c7229f5e4d6ad Mon Sep 17 00:00:00 2001 From: "Maxim.Mossienko" Date: Fri, 5 Dec 2014 12:31:34 +0100 Subject: [PATCH 10/22] use ProjectCoreUtil.isProjectOrWorkspaceFile --- .../com/intellij/util/indexing/FileBasedIndexImpl.java | 8 +------- 1 file changed, 1 insertion(+), 7 deletions(-) diff --git a/platform/lang-impl/src/com/intellij/util/indexing/FileBasedIndexImpl.java b/platform/lang-impl/src/com/intellij/util/indexing/FileBasedIndexImpl.java index d8dd50719cf6..4ed9341ae882 100644 --- a/platform/lang-impl/src/com/intellij/util/indexing/FileBasedIndexImpl.java +++ b/platform/lang-impl/src/com/intellij/util/indexing/FileBasedIndexImpl.java @@ -254,13 +254,7 @@ public class FileBasedIndexImpl extends FileBasedIndex { } public static boolean isProjectOrWorkspaceFile(@NotNull VirtualFile file, @Nullable FileType fileType) { - if (fileType instanceof InternalFileType) return true; - VirtualFile parent = file.isDirectory() ? file: file.getParent(); - while (parent != null) { - if (Comparing.equal(parent.getNameSequence(), ProjectCoreUtil.DIRECTORY_BASED_PROJECT_DIR, SystemInfoRt.isFileSystemCaseSensitive)) return true; - parent = parent.getParent(); - } - return false; + return ProjectCoreUtil.isProjectOrWorkspaceFile(file, fileType); } @Override From de0e17a36b08e221c87aa625cd319084a7b0d43c Mon Sep 17 00:00:00 2001 From: "Maxim.Mossienko" Date: Fri, 5 Dec 2014 12:36:33 +0100 Subject: [PATCH 11/22] more optimal isProjectOrWorkspaceFile calculation --- .../src/com/intellij/openapi/project/ProjectCoreUtil.java | 8 +++++--- 1 file changed, 5 insertions(+), 3 deletions(-) diff --git a/platform/core-api/src/com/intellij/openapi/project/ProjectCoreUtil.java b/platform/core-api/src/com/intellij/openapi/project/ProjectCoreUtil.java index 83e8b6924fd4..fce99a0fb479 100644 --- a/platform/core-api/src/com/intellij/openapi/project/ProjectCoreUtil.java +++ b/platform/core-api/src/com/intellij/openapi/project/ProjectCoreUtil.java @@ -2,6 +2,8 @@ package com.intellij.openapi.project; import com.intellij.openapi.fileTypes.FileType; import com.intellij.openapi.fileTypes.InternalFileType; +import com.intellij.openapi.util.Comparing; +import com.intellij.openapi.util.SystemInfoRt; import com.intellij.openapi.vfs.VirtualFile; /** @@ -17,9 +19,9 @@ public class ProjectCoreUtil { public static boolean isProjectOrWorkspaceFile(final VirtualFile file, final FileType fileType) { if (fileType instanceof InternalFileType) return true; - VirtualFile parent = file.getParent(); - while(parent != null) { - if (DIRECTORY_BASED_PROJECT_DIR.equals(parent.getName())) return true; + VirtualFile parent = file.isDirectory() ? file: file.getParent(); + while (parent != null) { + if (Comparing.equal(parent.getNameSequence(), DIRECTORY_BASED_PROJECT_DIR, SystemInfoRt.isFileSystemCaseSensitive)) return true; parent = parent.getParent(); } return false; From aa944679a1744484d1d828558c3564b25e3ef9a4 Mon Sep 17 00:00:00 2001 From: "Maxim.Mossienko" Date: Fri, 5 Dec 2014 12:40:58 +0100 Subject: [PATCH 12/22] twice smaller data for indexing stamp --- .../src/com/intellij/psi/stubs/StubUpdatingIndex.java | 11 ++++++----- 1 file changed, 6 insertions(+), 5 deletions(-) diff --git a/platform/lang-impl/src/com/intellij/psi/stubs/StubUpdatingIndex.java b/platform/lang-impl/src/com/intellij/psi/stubs/StubUpdatingIndex.java index 577494fa216d..329820b8297a 100644 --- a/platform/lang-impl/src/com/intellij/psi/stubs/StubUpdatingIndex.java +++ b/platform/lang-impl/src/com/intellij/psi/stubs/StubUpdatingIndex.java @@ -31,6 +31,7 @@ import com.intellij.psi.tree.IStubFileElementType; import com.intellij.util.ExceptionUtil; import com.intellij.util.indexing.*; import com.intellij.util.io.DataExternalizer; +import com.intellij.util.io.DataInputOutputUtil; import com.intellij.util.io.IntInlineKeyDescriptor; import com.intellij.util.io.KeyDescriptor; import org.jetbrains.annotations.NotNull; @@ -45,7 +46,7 @@ public class StubUpdatingIndex extends CustomImplementationFileBasedIndexExtensi private static final Logger LOG = Logger.getInstance("#com.intellij.psi.stubs.StubUpdatingIndex"); // todo remove once we don't need this for stub-ast mismatch debug info - private static final FileAttribute INDEXED_STAMP = new FileAttribute("stubIndexStamp", 0, false); + private static final FileAttribute INDEXED_STAMP = new FileAttribute("stubIndexStamp", 1, false); public static final ID INDEX_ID = ID.create("Stubs"); @@ -145,8 +146,8 @@ public class StubUpdatingIndex extends CustomImplementationFileBasedIndexExtensi private static void rememberIndexingStamp(final VirtualFile file, long contentLength) { try { DataOutputStream stream = INDEXED_STAMP.writeAttribute(file); - stream.writeLong(file.getTimeStamp()); - stream.writeLong(contentLength); + DataInputOutputUtil.writeTIME(stream, file.getTimeStamp()); + DataInputOutputUtil.writeLONG(stream, contentLength); stream.close(); } catch (IOException e) { @@ -161,8 +162,8 @@ public class StubUpdatingIndex extends CustomImplementationFileBasedIndexExtensi return "no data"; } - long stamp = stream.readLong(); - long size = stream.readLong(); + long stamp = DataInputOutputUtil.readTIME(stream); + long size = DataInputOutputUtil.readLONG(stream); stream.close(); return "indexed at " + stamp + " with size " + size; } From c7fb83dd47cd4c19acd890238087ee5fdd4362e9 Mon Sep 17 00:00:00 2001 From: "Maxim.Mossienko" Date: Fri, 5 Dec 2014 13:01:22 +0100 Subject: [PATCH 13/22] - do not file.getFileType() to avoid autodetection by content loading for arbitrary files - use ProjectCoreUtil when possible --- .../com/intellij/openapi/project/ProjectUtil.java | 15 ++++----------- 1 file changed, 4 insertions(+), 11 deletions(-) diff --git a/platform/lang-api/src/com/intellij/openapi/project/ProjectUtil.java b/platform/lang-api/src/com/intellij/openapi/project/ProjectUtil.java index df93b434277d..dcd0e8ae3513 100644 --- a/platform/lang-api/src/com/intellij/openapi/project/ProjectUtil.java +++ b/platform/lang-api/src/com/intellij/openapi/project/ProjectUtil.java @@ -20,10 +20,8 @@ import com.intellij.openapi.actionSystem.CommonDataKeys; import com.intellij.openapi.actionSystem.DataContext; import com.intellij.openapi.fileEditor.UniqueVFilePathBuilder; import com.intellij.openapi.fileTypes.FileType; -import com.intellij.openapi.fileTypes.InternalFileType; +import com.intellij.openapi.fileTypes.FileTypeManager; import com.intellij.openapi.roots.ProjectRootManager; -import com.intellij.openapi.util.Comparing; -import com.intellij.openapi.util.SystemInfoRt; import com.intellij.openapi.util.io.FileUtil; import com.intellij.openapi.vfs.VirtualFile; import com.intellij.openapi.vfs.VirtualFilePathWrapper; @@ -109,17 +107,12 @@ public class ProjectUtil { } public static boolean isProjectOrWorkspaceFile(final VirtualFile file) { - return isProjectOrWorkspaceFile(file, file.getFileType()); + // do not use file.getFileType() to avoid autodetection by content loading for arbitrary files + return isProjectOrWorkspaceFile(file, FileTypeManager.getInstance().getFileTypeByFileName(file.getName())); } public static boolean isProjectOrWorkspaceFile(@NotNull VirtualFile file, @Nullable FileType fileType) { - if (fileType instanceof InternalFileType) return true; - VirtualFile parent = file.isDirectory() ? file: file.getParent(); - while (parent != null) { - if (Comparing.equal(parent.getNameSequence(), ProjectCoreUtil.DIRECTORY_BASED_PROJECT_DIR, SystemInfoRt.isFileSystemCaseSensitive)) return true; - parent = parent.getParent(); - } - return false; + return ProjectCoreUtil.isProjectOrWorkspaceFile(file, fileType); } @NotNull From b7f553c54d9f492ca9f8493f160288c3689073c2 Mon Sep 17 00:00:00 2001 From: "Egor.Ushakov" Date: Fri, 5 Dec 2014 15:16:41 +0300 Subject: [PATCH 14/22] EA-63198 - IAE: XDebuggerManager.getInstance --- .../actions/CustomizeContextViewAction.java | 17 +++++++++-------- 1 file changed, 9 insertions(+), 8 deletions(-) diff --git a/java/debugger/impl/src/com/intellij/debugger/actions/CustomizeContextViewAction.java b/java/debugger/impl/src/com/intellij/debugger/actions/CustomizeContextViewAction.java index 6214a9e44d7f..a36bc9ace4aa 100644 --- a/java/debugger/impl/src/com/intellij/debugger/actions/CustomizeContextViewAction.java +++ b/java/debugger/impl/src/com/intellij/debugger/actions/CustomizeContextViewAction.java @@ -29,7 +29,6 @@ import com.intellij.openapi.options.TabbedConfigurable; import com.intellij.openapi.options.ex.SingleConfigurableEditor; import com.intellij.openapi.project.Project; import com.intellij.openapi.util.Disposer; -import com.intellij.xdebugger.XDebugProcess; import com.intellij.xdebugger.XDebugSession; import com.intellij.xdebugger.XDebuggerManager; import com.intellij.xdebugger.impl.ui.tree.actions.XDebuggerTreeActionBase; @@ -88,13 +87,15 @@ public class CustomizeContextViewAction extends XDebuggerTreeActionBase { @Override public void update(AnActionEvent e) { - final XDebuggerManager debuggerManager = XDebuggerManager.getInstance(getEventProject(e)); - final XDebugSession currentSession = debuggerManager.getCurrentSession(); - if (currentSession != null) { - final XDebugProcess process = currentSession.getDebugProcess(); - e.getPresentation().setVisible(process instanceof JavaDebugProcess); - e.getPresentation().setEnabled(process instanceof JavaDebugProcess); - e.getPresentation().setText(ActionsBundle.actionText(DebuggerActions.CUSTOMIZE_VIEWS)); + e.getPresentation().setText(ActionsBundle.actionText(DebuggerActions.CUSTOMIZE_VIEWS)); + Project project = getEventProject(e); + if (project != null) { + final XDebugSession currentSession = XDebuggerManager.getInstance(project).getCurrentSession(); + if (currentSession != null) { + e.getPresentation().setEnabledAndVisible(currentSession.getDebugProcess() instanceof JavaDebugProcess); + return; + } } + e.getPresentation().setEnabledAndVisible(false); } } From bdb47353499fe86e230294543609f2c4ba815b45 Mon Sep 17 00:00:00 2001 From: Eugene Zhuravlev Date: Fri, 5 Dec 2014 13:20:44 +0100 Subject: [PATCH 15/22] if compiled class is associated with multiple sources, correctly update class data for not compiled associated sources --- .../java/dependencyView/Mappings.java | 39 +++++++++++++++++++ 1 file changed, 39 insertions(+) diff --git a/jps/jps-builders/src/org/jetbrains/jps/builders/java/dependencyView/Mappings.java b/jps/jps-builders/src/org/jetbrains/jps/builders/java/dependencyView/Mappings.java index be43de8349fb..9e0f18d2d9e7 100644 --- a/jps/jps-builders/src/org/jetbrains/jps/builders/java/dependencyView/Mappings.java +++ b/jps/jps-builders/src/org/jetbrains/jps/builders/java/dependencyView/Mappings.java @@ -2272,6 +2272,45 @@ public class Mappings { return true; } }); + + // some classes may be associated with multiple sources. + // In case some of these sources was not compiled, but the class was changed, we need to update + // sourceToClasses mapping for such sources to include the updated ClassRepr version of the changed class + final THashSet unchangedSources = new THashSet(FileUtil.FILE_HASHING_STRATEGY); + delta.mySourceFileToClasses.forEachEntry(new TObjectObjectProcedure>() { + @Override + public boolean execute(File source, Collection b) { + unchangedSources.add(source); + return true; + } + }); + unchangedSources.removeAll(delta.getChangedFiles()); + if (!unchangedSources.isEmpty()) { + unchangedSources.forEach(new TObjectProcedure() { + @Override + public boolean execute(File file) { + final Collection updatedClasses = delta.mySourceFileToClasses.get(file); + if (updatedClasses != null && !updatedClasses.isEmpty()) { + final List classesToAdd = new ArrayList(); + classesToAdd.addAll(updatedClasses); + Collection currentClasses = mySourceFileToClasses.get(file); + if (currentClasses != null) { + final TIntHashSet updatedClassNames = new TIntHashSet(); + for (ClassRepr aClass : updatedClasses) { + updatedClassNames.add(aClass.name); + } + for (ClassRepr aClass : currentClasses) { + if (!updatedClassNames.contains(aClass.name)) { + classesToAdd.add(aClass); + } + } + } + mySourceFileToClasses.replace(file, classesToAdd); + } + return true; + } + }); + } } else { myClassToSubclasses.putAll(delta.myClassToSubclasses); From 37841f9d73abef4953145b564e22babb94f1d999 Mon Sep 17 00:00:00 2001 From: Anna Kozlova Date: Thu, 4 Dec 2014 14:10:50 +0100 Subject: [PATCH 16/22] extract method: resolve conflicts during params rename (IDEABKL-3749) --- .../extractMethod/ExtractMethodProcessor.java | 5 ++++- .../DefaultNamesConflictResolution.java | 7 +++++++ .../DefaultNamesConflictResolution_after.java | 11 +++++++++++ .../com/intellij/refactoring/ExtractMethodTest.java | 12 ++++++++++++ 4 files changed, 34 insertions(+), 1 deletion(-) create mode 100644 java/java-tests/testData/refactoring/extractMethod/DefaultNamesConflictResolution.java create mode 100644 java/java-tests/testData/refactoring/extractMethod/DefaultNamesConflictResolution_after.java diff --git a/java/java-impl/src/com/intellij/refactoring/extractMethod/ExtractMethodProcessor.java b/java/java-impl/src/com/intellij/refactoring/extractMethod/ExtractMethodProcessor.java index ba4c2471c7ce..76717fa50985 100644 --- a/java/java-impl/src/com/intellij/refactoring/extractMethod/ExtractMethodProcessor.java +++ b/java/java-impl/src/com/intellij/refactoring/extractMethod/ExtractMethodProcessor.java @@ -1239,7 +1239,10 @@ public class ExtractMethodProcessor implements MatchProvider { } private void renameInputVariables() throws IncorrectOperationException { - for (VariableData data : myVariableDatum) { + //when multiple input variables should have the same name, unique names are generated + //without reverse, the second rename would rename variable without a prefix into second one though it was already renamed + for (int i = myVariableDatum.length - 1; i >= 0; i--) { + VariableData data = myVariableDatum[i]; PsiVariable variable = data.variable; if (!data.name.equals(variable.getName())) { for (PsiElement element : myElements) { diff --git a/java/java-tests/testData/refactoring/extractMethod/DefaultNamesConflictResolution.java b/java/java-tests/testData/refactoring/extractMethod/DefaultNamesConflictResolution.java new file mode 100644 index 000000000000..9acf21ea6efb --- /dev/null +++ b/java/java-tests/testData/refactoring/extractMethod/DefaultNamesConflictResolution.java @@ -0,0 +1,7 @@ +class X { + public static void main(String[] args) { + boolean _user = true; + String user = "foo"; + System.out.println(_user + " " + user); + } +} diff --git a/java/java-tests/testData/refactoring/extractMethod/DefaultNamesConflictResolution_after.java b/java/java-tests/testData/refactoring/extractMethod/DefaultNamesConflictResolution_after.java new file mode 100644 index 000000000000..0749b6ad85a7 --- /dev/null +++ b/java/java-tests/testData/refactoring/extractMethod/DefaultNamesConflictResolution_after.java @@ -0,0 +1,11 @@ +class X { + public static void main(String[] args) { + boolean _user = true; + String user = "foo"; + newMethod(_user, user); + } + + private static void newMethod(boolean user, String user2) { + System.out.println(user + " " + user2); + } +} diff --git a/java/java-tests/testSrc/com/intellij/refactoring/ExtractMethodTest.java b/java/java-tests/testSrc/com/intellij/refactoring/ExtractMethodTest.java index 58678084b5d0..13b7300eb00a 100644 --- a/java/java-tests/testSrc/com/intellij/refactoring/ExtractMethodTest.java +++ b/java/java-tests/testSrc/com/intellij/refactoring/ExtractMethodTest.java @@ -646,6 +646,18 @@ public class ExtractMethodTest extends LightCodeInsightTestCase { doTestPassFieldsAsParams(); } + public void testDefaultNamesConflictResolution() throws Exception { + final CodeStyleSettings settings = CodeStyleSettingsManager.getSettings(getProject()); + final String oldPrefix = settings.LOCAL_VARIABLE_NAME_PREFIX; + try { + settings.LOCAL_VARIABLE_NAME_PREFIX = "_"; + doTest(); + } + finally { + settings.LOCAL_VARIABLE_NAME_PREFIX = oldPrefix; + } + } + public void testCantPassFieldAsParameter() throws Exception { try { doTestPassFieldsAsParams(); From 47531ace5972747dd0c009a90c7f06e93cd3b08e Mon Sep 17 00:00:00 2001 From: Anna Kozlova Date: Thu, 4 Dec 2014 15:24:28 +0100 Subject: [PATCH 17/22] extract method: @Nullable --- .../extractMethod/ExtractMethodProcessor.java | 9 ++++++--- 1 file changed, 6 insertions(+), 3 deletions(-) diff --git a/java/java-impl/src/com/intellij/refactoring/extractMethod/ExtractMethodProcessor.java b/java/java-impl/src/com/intellij/refactoring/extractMethod/ExtractMethodProcessor.java index 76717fa50985..0fc07c490148 100644 --- a/java/java-impl/src/com/intellij/refactoring/extractMethod/ExtractMethodProcessor.java +++ b/java/java-impl/src/com/intellij/refactoring/extractMethod/ExtractMethodProcessor.java @@ -783,6 +783,7 @@ public class ExtractMethodProcessor implements MatchProvider { } } + @Nullable private DuplicatesFinder initDuplicates() { List elements = new ArrayList(); for (PsiElement element : myElements) { @@ -1671,9 +1672,11 @@ public class ExtractMethodProcessor implements MatchProvider { final DuplicatesFinder finder = initDuplicates(); if (hasDuplicates()) return true; - final PsiManager psiManager = PsiManager.getInstance(myProject); - for (VirtualFile file : files) { - if (!finder.findDuplicates(psiManager.findFile(file)).isEmpty()) return true; + if (finder != null) { + final PsiManager psiManager = PsiManager.getInstance(myProject); + for (VirtualFile file : files) { + if (!finder.findDuplicates(psiManager.findFile(file)).isEmpty()) return true; + } } return false; } From 5e2fa7be19452105769b660a0ce7b1a4dd9a0dba Mon Sep 17 00:00:00 2001 From: Anna Kozlova Date: Fri, 5 Dec 2014 13:45:53 +0100 Subject: [PATCH 18/22] extract method: new signature detector (IDEA-66281); initial --- .../util/duplicates/DuplicatesFinder.java | 24 +- .../extractMethod/ExtractMethodProcessor.java | 31 +- .../ExtractMethodSignatureSuggester.java | 328 ++++++++++++++++++ .../ExtractMethodObjectProcessor.java | 2 + .../duplicates/ConstantMatchProvider.java | 2 +- .../util/duplicates/DuplicatesImpl.java | 14 +- .../util/duplicates/MatchProvider.java | 5 +- .../duplicates/MethodDuplicatesHandler.java | 23 +- .../MethodDuplicatesMatchProvider.java | 2 +- ...ignatureLeaveSameExpressionsUntouched.java | 13 + ...reLeaveSameExpressionsUntouched_after.java | 15 + .../SuggestChangeSignatureOneParam.java | 11 + ...eSignatureOneParamMultipleTimesInside.java | 13 + ...tureOneParamMultipleTimesInside_after.java | 15 + .../SuggestChangeSignatureOneParam_after.java | 14 + .../SuggestChangeSignatureSameParamNames.java | 13 + ...stChangeSignatureSameParamNames_after.java | 15 + ...angeSignatureWithChangedParameterName.java | 13 + ...gnatureWithChangedParameterName_after.java | 16 + .../refactoring/ExtractMethodTest.java | 48 ++- 20 files changed, 585 insertions(+), 32 deletions(-) create mode 100644 java/java-impl/src/com/intellij/refactoring/extractMethod/ExtractMethodSignatureSuggester.java create mode 100644 java/java-tests/testData/refactoring/extractMethod/SuggestChangeSignatureLeaveSameExpressionsUntouched.java create mode 100644 java/java-tests/testData/refactoring/extractMethod/SuggestChangeSignatureLeaveSameExpressionsUntouched_after.java create mode 100644 java/java-tests/testData/refactoring/extractMethod/SuggestChangeSignatureOneParam.java create mode 100644 java/java-tests/testData/refactoring/extractMethod/SuggestChangeSignatureOneParamMultipleTimesInside.java create mode 100644 java/java-tests/testData/refactoring/extractMethod/SuggestChangeSignatureOneParamMultipleTimesInside_after.java create mode 100644 java/java-tests/testData/refactoring/extractMethod/SuggestChangeSignatureOneParam_after.java create mode 100644 java/java-tests/testData/refactoring/extractMethod/SuggestChangeSignatureSameParamNames.java create mode 100644 java/java-tests/testData/refactoring/extractMethod/SuggestChangeSignatureSameParamNames_after.java create mode 100644 java/java-tests/testData/refactoring/extractMethod/SuggestChangeSignatureWithChangedParameterName.java create mode 100644 java/java-tests/testData/refactoring/extractMethod/SuggestChangeSignatureWithChangedParameterName_after.java diff --git a/java/java-analysis-impl/src/com/intellij/refactoring/util/duplicates/DuplicatesFinder.java b/java/java-analysis-impl/src/com/intellij/refactoring/util/duplicates/DuplicatesFinder.java index 846e1fd5d0ee..38c0cf4abbf4 100644 --- a/java/java-analysis-impl/src/com/intellij/refactoring/util/duplicates/DuplicatesFinder.java +++ b/java/java-analysis-impl/src/com/intellij/refactoring/util/duplicates/DuplicatesFinder.java @@ -97,7 +97,18 @@ public class DuplicatesFinder { } + public InputVariables getParameters() { + return myParameters; + } + public PsiElement[] getPattern() { + return myPattern; + } + + @Nullable + public ReturnValue getReturnValue() { + return myReturnValue; + } public List findDuplicates(PsiElement scope) { annotatePattern(); @@ -164,9 +175,7 @@ public class DuplicatesFinder { @Nullable private Match isDuplicateFragment(PsiElement candidate, boolean ignoreParameterTypesAndPostVariableUsages) { - for (PsiElement pattern : myPattern) { - if (PsiTreeUtil.isAncestor(pattern, candidate, false)) return null; - } + if (isSelf(candidate)) return null; PsiElement sibling = candidate; ArrayList candidates = new ArrayList(); for (final PsiElement element : myPattern) { @@ -206,6 +215,15 @@ public class DuplicatesFinder { return match; } + protected boolean isSelf(PsiElement candidate) { + for (PsiElement pattern : myPattern) { + if (PsiTreeUtil.isAncestor(pattern, candidate, false)) { + return true; + } + } + return false; + } + private boolean checkPostVariableUsages(final ArrayList candidates, final Match match) { final PsiElement codeFragment = ControlFlowUtil.findCodeFragment(candidates.get(0)); try { diff --git a/java/java-impl/src/com/intellij/refactoring/extractMethod/ExtractMethodProcessor.java b/java/java-impl/src/com/intellij/refactoring/extractMethod/ExtractMethodProcessor.java index 0fc07c490148..3af0c948d209 100644 --- a/java/java-impl/src/com/intellij/refactoring/extractMethod/ExtractMethodProcessor.java +++ b/java/java-impl/src/com/intellij/refactoring/extractMethod/ExtractMethodProcessor.java @@ -47,7 +47,10 @@ import com.intellij.openapi.util.text.StringUtil; import com.intellij.openapi.vfs.VirtualFile; import com.intellij.openapi.wm.WindowManager; import com.intellij.psi.*; -import com.intellij.psi.codeStyle.*; +import com.intellij.psi.codeStyle.CodeStyleManager; +import com.intellij.psi.codeStyle.CodeStyleSettingsManager; +import com.intellij.psi.codeStyle.JavaCodeStyleManager; +import com.intellij.psi.codeStyle.VariableKind; import com.intellij.psi.controlFlow.ControlFlowUtil; import com.intellij.psi.impl.source.codeStyle.JavaCodeStyleManagerImpl; import com.intellij.psi.scope.processor.VariablesProcessor; @@ -725,6 +728,11 @@ public class ExtractMethodProcessor implements MatchProvider { myVariableDatum[i].passAsParameter = false; } + @TestOnly + public void changeParamName(int i, String param) { + myVariableDatum[i].name = param; + } + /** * Invoked in command and in atomic action */ @@ -1663,15 +1671,28 @@ public class ExtractMethodProcessor implements MatchProvider { return myExtractedMethod; } - public boolean hasDuplicates() { - final List duplicates = getDuplicates(); - return duplicates != null && !duplicates.isEmpty(); + public Boolean hasDuplicates() { + List duplicates = getDuplicates(); + if (duplicates != null && !duplicates.isEmpty()) { + return true; + } + final ExtractMethodSignatureSuggester suggester = new ExtractMethodSignatureSuggester(myProject, myExtractedMethod, myMethodCall, myVariableDatum); + duplicates = suggester.getDuplicates(myExtractedMethod, myMethodCall); + if (duplicates != null && !duplicates.isEmpty()) { + myDuplicates = duplicates; + myExtractedMethod = suggester.getExtractedMethod(); + myMethodCall = suggester.getMethodCall(); + myVariableDatum = suggester.getVariableData(); + return null; + } + return false; } public boolean hasDuplicates(Set files) { final DuplicatesFinder finder = initDuplicates(); - if (hasDuplicates()) return true; + final Boolean hasDuplicates = hasDuplicates(); + if (hasDuplicates == null || hasDuplicates) return true; if (finder != null) { final PsiManager psiManager = PsiManager.getInstance(myProject); for (VirtualFile file : files) { diff --git a/java/java-impl/src/com/intellij/refactoring/extractMethod/ExtractMethodSignatureSuggester.java b/java/java-impl/src/com/intellij/refactoring/extractMethod/ExtractMethodSignatureSuggester.java new file mode 100644 index 000000000000..eecedb1f4f4f --- /dev/null +++ b/java/java-impl/src/com/intellij/refactoring/extractMethod/ExtractMethodSignatureSuggester.java @@ -0,0 +1,328 @@ +/* + * Copyright 2000-2014 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.refactoring.extractMethod; + +import com.intellij.codeInsight.JavaPsiEquivalenceUtil; +import com.intellij.openapi.application.ApplicationManager; +import com.intellij.openapi.command.WriteCommandAction; +import com.intellij.openapi.diagnostic.Logger; +import com.intellij.openapi.project.Project; +import com.intellij.openapi.ui.Messages; +import com.intellij.psi.*; +import com.intellij.psi.codeStyle.JavaCodeStyleManager; +import com.intellij.psi.codeStyle.SuggestedNameInfo; +import com.intellij.psi.codeStyle.VariableKind; +import com.intellij.psi.search.LocalSearchScope; +import com.intellij.psi.util.PsiTreeUtil; +import com.intellij.psi.util.PsiUtil; +import com.intellij.refactoring.util.RefactoringUtil; +import com.intellij.refactoring.util.VariableData; +import com.intellij.refactoring.util.duplicates.DuplicatesFinder; +import com.intellij.refactoring.util.duplicates.Match; +import com.intellij.refactoring.util.duplicates.MethodDuplicatesHandler; +import com.intellij.util.text.UniqueNameGenerator; +import gnu.trove.THashMap; +import gnu.trove.THashSet; +import gnu.trove.TObjectHashingStrategy; +import org.jetbrains.annotations.Nullable; + +import java.util.*; + +public class ExtractMethodSignatureSuggester { + private static final Logger LOG = Logger.getInstance("#" + ExtractMethodSignatureSuggester.class.getName()); + private static final TObjectHashingStrategy ourEquivalenceStrategy = new TObjectHashingStrategy() { + @Override + public int computeHashCode(PsiExpression object) { + return RefactoringUtil.unparenthesizeExpression(object).getClass().hashCode(); + } + + @Override + public boolean equals(PsiExpression o1, PsiExpression o2) { + return JavaPsiEquivalenceUtil + .areExpressionsEquivalent(RefactoringUtil.unparenthesizeExpression(o1), RefactoringUtil.unparenthesizeExpression(o2)); + } + }; + + private Project myProject; + private PsiElementFactory myElementFactory; + + private PsiMethod myExtractedMethod; + private PsiMethodCallExpression myMethodCall; + private VariableData[] myVariableData; + + public ExtractMethodSignatureSuggester(Project project, + PsiMethod extractedMethod, + PsiMethodCallExpression methodCall, + VariableData[] variableDatum) { + myProject = project; + myElementFactory = JavaPsiFacade.getElementFactory(project); + + myExtractedMethod = (PsiMethod)extractedMethod.copy(); + myMethodCall = methodCall; + myVariableData = variableDatum; + } + + public List getDuplicates(final PsiMethod method, final PsiMethodCallExpression methodCall) { + final List duplicates = findDuplicatesSignature(method); + if (duplicates != null && !duplicates.isEmpty()) { + if (ApplicationManager.getApplication().isUnitTestMode() || + Messages.showYesNoDialog(myProject, "No exact duplicates found.\nWould you like to apply suggested changes to replace " + duplicates.size() + " duplicates?", "Extract Parameters to Replace Duplicates", + Messages.getQuestionIcon()) == Messages.YES) { + WriteCommandAction.runWriteCommandAction(myProject, new Runnable() { + @Override + public void run() { + myMethodCall = (PsiMethodCallExpression)methodCall.replace(myMethodCall); + myExtractedMethod = (PsiMethod)method.replace(myExtractedMethod); + } + }); + + final DuplicatesFinder finder = MethodDuplicatesHandler.createDuplicatesFinder(myExtractedMethod); + if (finder != null) { + final List datas = finder.getParameters().getInputVariables(); + myVariableData = datas.toArray(new VariableData[datas.size()]); + return finder.findDuplicates(myExtractedMethod.getContainingClass()); + } + } + } + return null; + } + + + public PsiMethod getExtractedMethod() { + return myExtractedMethod; + } + + public PsiMethodCallExpression getMethodCall() { + return myMethodCall; + } + + public VariableData[] getVariableData() { + return myVariableData; + } + + @Nullable + public List findDuplicatesSignature(final PsiMethod method) { + final List copies = new ArrayList(); + final InputVariables variables = detectTopLevelExpressionsToReplaceWithParameters(copies); + if (variables == null) { + return null; + } + + final DuplicatesFinder defaultFinder = MethodDuplicatesHandler.createDuplicatesFinder(myExtractedMethod); + if (defaultFinder == null) { + return null; + } + + final DuplicatesFinder finder = new DuplicatesFinder(defaultFinder.getPattern(), variables, defaultFinder.getReturnValue(), new ArrayList()) { + @Override + protected boolean isSelf(PsiElement candidate) { + return PsiTreeUtil.isAncestor(method, candidate, true); + } + }; + List duplicates = finder.findDuplicates(method.getContainingClass()); + + if (duplicates != null && !duplicates.isEmpty()) { + restoreRenamedParams(copies); + inlineSameArguments(method, copies, variables, duplicates); + myMethodCall = (PsiMethodCallExpression)myMethodCall.copy(); + for (PsiExpression expression : copies) { + myMethodCall.getArgumentList().add(expression); + } + return duplicates; + } + else { + return null; + } + } + + private void inlineSameArguments(PsiMethod method, List copies, InputVariables variables, List duplicates) { + final List variableDatum = variables.getInputVariables(); + final Map toInline = new HashMap(); + final int strongParamsCound = method.getParameterList().getParametersCount(); + for (int i = strongParamsCound; i < variableDatum.size(); i++) { + VariableData variableData = variableDatum.get(i); + final THashSet map = new THashSet(ourEquivalenceStrategy); + if (!collectParamValues(duplicates, variableData, map)) { + continue; + } + + final PsiExpression currentExpression = copies.get(i - strongParamsCound); + map.add(currentExpression); + + if (map.size() == 1) { + toInline.put(variableData.variable, currentExpression); + } + } + + if (!toInline.isEmpty()) { + copies.removeAll(toInline.values()); + inlineArgumentsInMethodBody(toInline); + removeRedundantParametersFromMethodSignature(toInline); + } + } + + private void removeRedundantParametersFromMethodSignature(Map param2ExprMap) { + for (PsiParameter parameter : myExtractedMethod.getParameterList().getParameters()) { + if (param2ExprMap.containsKey(parameter)) { + parameter.delete(); + } + } + } + + private void inlineArgumentsInMethodBody(final Map param2ExprMap) { + final Map replacement = new HashMap(); + myExtractedMethod.accept(new JavaRecursiveElementWalkingVisitor() { + @Override + public void visitReferenceExpression(PsiReferenceExpression expression) { + super.visitReferenceExpression(expression); + final PsiElement resolve = expression.resolve(); + if (resolve instanceof PsiVariable) { + final PsiExpression toInlineExpr = param2ExprMap.get((PsiVariable)resolve); + if (toInlineExpr != null) { + replacement.put(expression, toInlineExpr); + } + } + } + }); + for (PsiExpression expression : replacement.keySet()) { + expression.replace(replacement.get(expression)); + } + } + + private static boolean collectParamValues(List duplicates, VariableData variableData, THashSet map) { + for (Match duplicate : duplicates) { + final List values = duplicate.getParameterValues(variableData.variable); + if (values == null || values.isEmpty()) { + return false; + } + boolean found = false; + for (PsiElement value : values) { + if (value instanceof PsiExpression) { + map.add((PsiExpression)value); + found = true; + break; + } + } + if (!found) return false; + } + return true; + } + + private void restoreRenamedParams(List copies) { + final Map renameMap = new HashMap(); + for (VariableData data : myVariableData) { + if (!data.name.equals(data.variable.getName())) { + renameMap.put(data.name, data.variable); + } + } + + if (!renameMap.isEmpty()) { + for (PsiExpression currentExpression : copies) { + final Map params = new HashMap(); + currentExpression.accept(new JavaRecursiveElementWalkingVisitor() { + @Override + public void visitReferenceExpression(PsiReferenceExpression expression) { + super.visitReferenceExpression(expression); + final PsiElement resolve = expression.resolve(); + if (resolve instanceof PsiParameter && myExtractedMethod.equals(((PsiParameter)resolve).getDeclarationScope())) { + final String name = ((PsiParameter)resolve).getName(); + final PsiVariable variable = renameMap.get(name); + if (renameMap.containsKey(name)) { + params.put(expression, variable); + } + } + } + }); + for (PsiReferenceExpression expression : params.keySet()) { + final PsiVariable var = params.get(expression); + expression.replace(myElementFactory.createExpressionFromText(var.getName(), expression)); + } + } + } + } + + + @Nullable + private InputVariables detectTopLevelExpressionsToReplaceWithParameters(List copies) { + final PsiParameter[] parameters = myExtractedMethod.getParameterList().getParameters(); + final List inputVariables = new ArrayList(Arrays.asList(parameters)); + final PsiCodeBlock body = myExtractedMethod.getBody(); + LOG.assertTrue(body != null); + final PsiStatement[] pattern = body.getStatements(); + final List exprs = new ArrayList(); + for (PsiStatement statement : pattern) { + if (statement instanceof PsiExpressionStatement) { + final PsiExpression expression = ((PsiExpressionStatement)statement).getExpression(); + if (expression instanceof PsiIfStatement || expression instanceof PsiLoopStatement) { + continue; + } + } + statement.accept(new JavaRecursiveElementWalkingVisitor() { + @Override + public void visitCallExpression(PsiCallExpression callExpression) { + final PsiExpressionList list = callExpression.getArgumentList(); + if (list != null) { + for (PsiExpression expression : list.getExpressions()) { + if (expression instanceof PsiReferenceExpression) { + final PsiElement resolve = ((PsiReferenceExpression)expression).resolve(); + if (resolve instanceof PsiField) { + exprs.add(expression); + } + } else { + exprs.add(expression); + } + } + } + } + }); + } + + if (exprs.isEmpty()) { + return null; + } + + final UniqueNameGenerator uniqueNameGenerator = new UniqueNameGenerator(); + for (PsiParameter parameter : parameters) { + uniqueNameGenerator.addExistingName(parameter.getName()); + } + final THashMap unique = new THashMap(ourEquivalenceStrategy); + final Map replacement = new HashMap(); + for (PsiExpression expr : exprs) { + String name = unique.get(expr); + if (name == null) { + + final PsiType type = GenericsUtil.getVariableTypeByExpressionType(expr.getType()); + if (type == null || type == PsiType.NULL || PsiUtil.resolveClassInType(type) instanceof PsiAnonymousClass) return null; + + copies.add(myElementFactory.createExpressionFromText(expr.getText(), body)); + + final SuggestedNameInfo info = JavaCodeStyleManager.getInstance(myProject).suggestVariableName(VariableKind.PARAMETER, null, expr, null); + name = uniqueNameGenerator.generateUniqueName(info.names[0]); + + final PsiParameter parameter = (PsiParameter)myExtractedMethod.getParameterList().add(myElementFactory.createParameter(name, type)); + inputVariables.add(parameter); + unique.put(expr, name); + } + replacement.put(expr, name); + } + + for (PsiExpression expression : replacement.keySet()) { + expression.replace(myElementFactory.createExpressionFromText(replacement.get(expression), null)); + } + + return new InputVariables(inputVariables, myExtractedMethod.getProject(), new LocalSearchScope(myExtractedMethod), false); + } +} diff --git a/java/java-impl/src/com/intellij/refactoring/extractMethodObject/ExtractMethodObjectProcessor.java b/java/java-impl/src/com/intellij/refactoring/extractMethodObject/ExtractMethodObjectProcessor.java index 2a8741b88451..c7079345e98b 100644 --- a/java/java-impl/src/com/intellij/refactoring/extractMethodObject/ExtractMethodObjectProcessor.java +++ b/java/java-impl/src/com/intellij/refactoring/extractMethodObject/ExtractMethodObjectProcessor.java @@ -28,6 +28,7 @@ import com.intellij.openapi.editor.Editor; import com.intellij.openapi.project.Project; import com.intellij.openapi.ui.DialogWrapper; import com.intellij.openapi.util.Comparing; +import com.intellij.openapi.util.Pair; import com.intellij.openapi.util.text.StringUtil; import com.intellij.psi.*; import com.intellij.psi.codeStyle.CodeStyleManager; @@ -61,6 +62,7 @@ import com.intellij.util.IncorrectOperationException; import com.intellij.util.VisibilityUtil; import org.jetbrains.annotations.NonNls; import org.jetbrains.annotations.NotNull; +import org.jetbrains.annotations.Nullable; import javax.swing.*; import java.util.*; diff --git a/java/java-impl/src/com/intellij/refactoring/util/duplicates/ConstantMatchProvider.java b/java/java-impl/src/com/intellij/refactoring/util/duplicates/ConstantMatchProvider.java index 482cb6409b6c..7c66aaebcf03 100644 --- a/java/java-impl/src/com/intellij/refactoring/util/duplicates/ConstantMatchProvider.java +++ b/java/java-impl/src/com/intellij/refactoring/util/duplicates/ConstantMatchProvider.java @@ -58,7 +58,7 @@ class ConstantMatchProvider implements MatchProvider { } @Override - public boolean hasDuplicates() { + public Boolean hasDuplicates() { return !myMatches.isEmpty(); } diff --git a/java/java-impl/src/com/intellij/refactoring/util/duplicates/DuplicatesImpl.java b/java/java-impl/src/com/intellij/refactoring/util/duplicates/DuplicatesImpl.java index 5e5b620bcd31..38c798b5549d 100644 --- a/java/java-impl/src/com/intellij/refactoring/util/duplicates/DuplicatesImpl.java +++ b/java/java-impl/src/com/intellij/refactoring/util/duplicates/DuplicatesImpl.java @@ -59,13 +59,17 @@ public class DuplicatesImpl { private DuplicatesImpl() {} public static void invoke(@NotNull final Project project, @NotNull Editor editor, @NotNull MatchProvider provider) { + invoke(project, editor, provider, true); + } + + public static void invoke(@NotNull final Project project, @NotNull Editor editor, @NotNull MatchProvider provider, boolean skipPromptWhenOne) { final List duplicates = provider.getDuplicates(); int idx = 0; final Ref showAll = new Ref(); final String confirmDuplicatePrompt = getConfirmationPrompt(provider, duplicates); for (final Match match : duplicates) { if (!match.getMatchStart().isValid() || !match.getMatchEnd().isValid()) continue; - if (replaceMatch(project, provider, match, editor, ++idx, duplicates.size(), showAll, confirmDuplicatePrompt, true)) return; + if (replaceMatch(project, provider, match, editor, ++idx, duplicates.size(), showAll, confirmDuplicatePrompt, skipPromptWhenOne)) return; } } @@ -186,18 +190,18 @@ public class DuplicatesImpl { } public static void processDuplicates(@NotNull MatchProvider provider, @NotNull Project project, @NotNull Editor editor) { - boolean hasDuplicates = provider.hasDuplicates(); - if (hasDuplicates) { + Boolean hasDuplicates = provider.hasDuplicates(); + if (hasDuplicates == null || hasDuplicates.booleanValue()) { List duplicates = provider.getDuplicates(); if (duplicates.size() == 1) { previewMatch(project, duplicates.get(0), editor); } - final int answer = ApplicationManager.getApplication().isUnitTestMode() ? Messages.YES : Messages.showYesNoDialog(project, + final int answer = ApplicationManager.getApplication().isUnitTestMode() || hasDuplicates == null ? Messages.YES : Messages.showYesNoDialog(project, RefactoringBundle.message("0.has.detected.1.code.fragments.in.this.file.that.can.be.replaced.with.a.call.to.extracted.method", ApplicationNamesInfo.getInstance().getProductName(), duplicates.size()), "Process Duplicates", Messages.getQuestionIcon()); if (answer == Messages.YES) { - invoke(project, editor, provider); + invoke(project, editor, provider, hasDuplicates != null); } } } diff --git a/java/java-impl/src/com/intellij/refactoring/util/duplicates/MatchProvider.java b/java/java-impl/src/com/intellij/refactoring/util/duplicates/MatchProvider.java index abe57ef465ab..8c067a215ef3 100644 --- a/java/java-impl/src/com/intellij/refactoring/util/duplicates/MatchProvider.java +++ b/java/java-impl/src/com/intellij/refactoring/util/duplicates/MatchProvider.java @@ -30,7 +30,10 @@ public interface MatchProvider { List getDuplicates(); - boolean hasDuplicates(); + /** + * @return null if no confirmation prompt is expected + */ + @Nullable Boolean hasDuplicates(); @Nullable String getConfirmDuplicatePrompt(Match match); diff --git a/java/java-impl/src/com/intellij/refactoring/util/duplicates/MethodDuplicatesHandler.java b/java/java-impl/src/com/intellij/refactoring/util/duplicates/MethodDuplicatesHandler.java index d908d35ec3cd..78c4ed2ab216 100644 --- a/java/java-impl/src/com/intellij/refactoring/util/duplicates/MethodDuplicatesHandler.java +++ b/java/java-impl/src/com/intellij/refactoring/util/duplicates/MethodDuplicatesHandler.java @@ -257,6 +257,16 @@ public class MethodDuplicatesHandler implements RefactoringActionHandler { } public static List hasDuplicates(final PsiFile file, final PsiMember member) { + final DuplicatesFinder duplicatesFinder = createDuplicatesFinder(member); + if (duplicatesFinder == null) { + return Collections.emptyList(); + } + + return duplicatesFinder.findDuplicates(file); + } + + @Nullable + public static DuplicatesFinder createDuplicatesFinder(PsiMember member) { PsiElement[] pattern; ReturnValue matchedReturnValue = null; if (member instanceof PsiMethod) { @@ -288,17 +298,14 @@ public class MethodDuplicatesHandler implements RefactoringActionHandler { pattern = new PsiElement[]{((PsiField)member).getInitializer()}; } if (pattern.length == 0) { - return Collections.emptyList(); + return null; } final List inputVariables = member instanceof PsiMethod ? Arrays.asList(((PsiMethod)member).getParameterList().getParameters()) : new ArrayList(); - final DuplicatesFinder duplicatesFinder = - new DuplicatesFinder(pattern, - new InputVariables(inputVariables, member.getProject(), new LocalSearchScope(pattern), false), - matchedReturnValue, - new ArrayList()); - - return duplicatesFinder.findDuplicates(file); + return new DuplicatesFinder(pattern, + new InputVariables(inputVariables, member.getProject(), new LocalSearchScope(pattern), false), + matchedReturnValue, + new ArrayList()); } static String getStatusMessage(final int duplicatesNo) { diff --git a/java/java-impl/src/com/intellij/refactoring/util/duplicates/MethodDuplicatesMatchProvider.java b/java/java-impl/src/com/intellij/refactoring/util/duplicates/MethodDuplicatesMatchProvider.java index 7686126427b6..f7b06702bce0 100644 --- a/java/java-impl/src/com/intellij/refactoring/util/duplicates/MethodDuplicatesMatchProvider.java +++ b/java/java-impl/src/com/intellij/refactoring/util/duplicates/MethodDuplicatesMatchProvider.java @@ -149,7 +149,7 @@ class MethodDuplicatesMatchProvider implements MatchProvider { } @Override - public boolean hasDuplicates() { + public Boolean hasDuplicates() { return myDuplicates.isEmpty(); } diff --git a/java/java-tests/testData/refactoring/extractMethod/SuggestChangeSignatureLeaveSameExpressionsUntouched.java b/java/java-tests/testData/refactoring/extractMethod/SuggestChangeSignatureLeaveSameExpressionsUntouched.java new file mode 100644 index 000000000000..ad1e6d5f632c --- /dev/null +++ b/java/java-tests/testData/refactoring/extractMethod/SuggestChangeSignatureLeaveSameExpressionsUntouched.java @@ -0,0 +1,13 @@ +public class Test { + { + int x = 0; + + System.out.println("foo"); + System.out.println("bazz"); + System.out.println(x); + + System.out.println("bar"); + System.out.println("bazz"); + System.out.println(x); + } +} \ No newline at end of file diff --git a/java/java-tests/testData/refactoring/extractMethod/SuggestChangeSignatureLeaveSameExpressionsUntouched_after.java b/java/java-tests/testData/refactoring/extractMethod/SuggestChangeSignatureLeaveSameExpressionsUntouched_after.java new file mode 100644 index 000000000000..db07aa54c3a8 --- /dev/null +++ b/java/java-tests/testData/refactoring/extractMethod/SuggestChangeSignatureLeaveSameExpressionsUntouched_after.java @@ -0,0 +1,15 @@ +public class Test { + { + int x = 0; + + newMethod(x, "foo"); + + newMethod(x, "bar"); + } + + private void newMethod(int x, String foo) { + System.out.println(foo); + System.out.println("bazz"); + System.out.println(x); + } +} \ No newline at end of file diff --git a/java/java-tests/testData/refactoring/extractMethod/SuggestChangeSignatureOneParam.java b/java/java-tests/testData/refactoring/extractMethod/SuggestChangeSignatureOneParam.java new file mode 100644 index 000000000000..47681845c571 --- /dev/null +++ b/java/java-tests/testData/refactoring/extractMethod/SuggestChangeSignatureOneParam.java @@ -0,0 +1,11 @@ +public class Test { + { + int x = 0; + + System.out.println("foo"); + System.out.println(x); + + System.out.println("bar"); + System.out.println(x); + } +} \ No newline at end of file diff --git a/java/java-tests/testData/refactoring/extractMethod/SuggestChangeSignatureOneParamMultipleTimesInside.java b/java/java-tests/testData/refactoring/extractMethod/SuggestChangeSignatureOneParamMultipleTimesInside.java new file mode 100644 index 000000000000..a345233a9c37 --- /dev/null +++ b/java/java-tests/testData/refactoring/extractMethod/SuggestChangeSignatureOneParamMultipleTimesInside.java @@ -0,0 +1,13 @@ +public class Test { + { + int x = 0; + + System.out.println("foo"); + System.out.println("foo"); + System.out.println(x); + + System.out.println("bar"); + System.out.println("bar"); + System.out.println(x); + } +} \ No newline at end of file diff --git a/java/java-tests/testData/refactoring/extractMethod/SuggestChangeSignatureOneParamMultipleTimesInside_after.java b/java/java-tests/testData/refactoring/extractMethod/SuggestChangeSignatureOneParamMultipleTimesInside_after.java new file mode 100644 index 000000000000..c6d3c785933b --- /dev/null +++ b/java/java-tests/testData/refactoring/extractMethod/SuggestChangeSignatureOneParamMultipleTimesInside_after.java @@ -0,0 +1,15 @@ +public class Test { + { + int x = 0; + + newMethod(x, "foo"); + + newMethod(x, "bar"); + } + + private void newMethod(int x, String foo) { + System.out.println(foo); + System.out.println(foo); + System.out.println(x); + } +} \ No newline at end of file diff --git a/java/java-tests/testData/refactoring/extractMethod/SuggestChangeSignatureOneParam_after.java b/java/java-tests/testData/refactoring/extractMethod/SuggestChangeSignatureOneParam_after.java new file mode 100644 index 000000000000..ef16acc2489b --- /dev/null +++ b/java/java-tests/testData/refactoring/extractMethod/SuggestChangeSignatureOneParam_after.java @@ -0,0 +1,14 @@ +public class Test { + { + int x = 0; + + newMethod(x, "foo"); + + newMethod(x, "bar"); + } + + private void newMethod(int x, String foo) { + System.out.println(foo); + System.out.println(x); + } +} \ No newline at end of file diff --git a/java/java-tests/testData/refactoring/extractMethod/SuggestChangeSignatureSameParamNames.java b/java/java-tests/testData/refactoring/extractMethod/SuggestChangeSignatureSameParamNames.java new file mode 100644 index 000000000000..ebb9e5910770 --- /dev/null +++ b/java/java-tests/testData/refactoring/extractMethod/SuggestChangeSignatureSameParamNames.java @@ -0,0 +1,13 @@ +public class Test { + { + int x = 0; + + System.out.println(1); + System.out.println(2); + System.out.println(x); + + System.out.println(3); + System.out.println(4); + System.out.println(x); + } +} \ No newline at end of file diff --git a/java/java-tests/testData/refactoring/extractMethod/SuggestChangeSignatureSameParamNames_after.java b/java/java-tests/testData/refactoring/extractMethod/SuggestChangeSignatureSameParamNames_after.java new file mode 100644 index 000000000000..47d1ed9ed8c6 --- /dev/null +++ b/java/java-tests/testData/refactoring/extractMethod/SuggestChangeSignatureSameParamNames_after.java @@ -0,0 +1,15 @@ +public class Test { + { + int x = 0; + + newMethod(x, 1, 2); + + newMethod(x, 3, 4); + } + + private void newMethod(int x, int x2, int x3) { + System.out.println(x2); + System.out.println(x3); + System.out.println(x); + } +} \ No newline at end of file diff --git a/java/java-tests/testData/refactoring/extractMethod/SuggestChangeSignatureWithChangedParameterName.java b/java/java-tests/testData/refactoring/extractMethod/SuggestChangeSignatureWithChangedParameterName.java new file mode 100644 index 000000000000..2445f2264db8 --- /dev/null +++ b/java/java-tests/testData/refactoring/extractMethod/SuggestChangeSignatureWithChangedParameterName.java @@ -0,0 +1,13 @@ +public class Test { + { + int x = 0; + + + System.out.println(x); + System.out.println(x + 1); + + + System.out.println(x); + System.out.println(x + 2); + } +} \ No newline at end of file diff --git a/java/java-tests/testData/refactoring/extractMethod/SuggestChangeSignatureWithChangedParameterName_after.java b/java/java-tests/testData/refactoring/extractMethod/SuggestChangeSignatureWithChangedParameterName_after.java new file mode 100644 index 000000000000..b3e5880154f3 --- /dev/null +++ b/java/java-tests/testData/refactoring/extractMethod/SuggestChangeSignatureWithChangedParameterName_after.java @@ -0,0 +1,16 @@ +public class Test { + { + int x = 0; + + + newMethod(x, x + 1); + + + newMethod(x, x + 2); + } + + private void newMethod(int p, int x) { + System.out.println(p); + System.out.println(x); + } +} \ No newline at end of file diff --git a/java/java-tests/testSrc/com/intellij/refactoring/ExtractMethodTest.java b/java/java-tests/testSrc/com/intellij/refactoring/ExtractMethodTest.java index 13b7300eb00a..09e9863d6fc2 100644 --- a/java/java-tests/testSrc/com/intellij/refactoring/ExtractMethodTest.java +++ b/java/java-tests/testSrc/com/intellij/refactoring/ExtractMethodTest.java @@ -19,6 +19,7 @@ import com.intellij.JavaTestUtil; import com.intellij.codeInsight.CodeInsightUtil; import com.intellij.openapi.editor.Editor; import com.intellij.openapi.project.Project; +import com.intellij.openapi.util.Pair; import com.intellij.psi.*; import com.intellij.psi.codeStyle.CodeStyleSettings; import com.intellij.psi.codeStyle.CodeStyleSettingsManager; @@ -33,6 +34,7 @@ import com.intellij.util.IncorrectOperationException; import org.jetbrains.annotations.NonNls; import org.jetbrains.annotations.NotNull; +import java.util.ArrayList; import java.util.List; public class ExtractMethodTest extends LightCodeInsightTestCase { @@ -609,6 +611,29 @@ public class ExtractMethodTest extends LightCodeInsightTestCase { doDuplicatesTest(); } + public void testSuggestChangeSignatureOneParam() throws Exception { + doDuplicatesTest(); + } + + public void testSuggestChangeSignatureOneParamMultipleTimesInside() throws Exception { + doDuplicatesTest(); + } + + public void testSuggestChangeSignatureLeaveSameExpressionsUntouched() throws Exception { + doDuplicatesTest(); + } + + public void testSuggestChangeSignatureSameParamNames() throws Exception { + doDuplicatesTest(); + } + + public void testSuggestChangeSignatureWithChangedParameterName() throws Exception { + configureByFile(BASE_PATH + getTestName(false) + ".java"); + boolean success = performExtractMethod(true, true, getEditor(), getFile(), getProject(), false, null, false, "p"); + assertTrue(success); + checkResultByFile(BASE_PATH + getTestName(false) + "_after.java"); + } + public void testTargetAnonymous() throws Exception { doTest(); } @@ -682,7 +707,7 @@ public class ExtractMethodTest extends LightCodeInsightTestCase { settings.ELSE_ON_NEW_LINE = true; settings.CATCH_ON_NEW_LINE = myCatchOnNewLine; configureByFile(BASE_PATH + getTestName(false) + ".java"); - boolean success = performExtractMethod(true, true, getEditor(), getFile(), getProject(), false, type, false); + boolean success = performExtractMethod(true, true, getEditor(), getFile(), getProject(), false, type, false, null); assertTrue(success); checkResultByFile(BASE_PATH + getTestName(false) + "_after.java"); } @@ -692,7 +717,7 @@ public class ExtractMethodTest extends LightCodeInsightTestCase { settings.ELSE_ON_NEW_LINE = true; settings.CATCH_ON_NEW_LINE = myCatchOnNewLine; configureByFile(BASE_PATH + getTestName(false) + ".java"); - boolean success = performExtractMethod(true, true, getEditor(), getFile(), getProject(), false, null, true); + boolean success = performExtractMethod(true, true, getEditor(), getFile(), getProject(), false, null, true, null); assertTrue(success); checkResultByFile(BASE_PATH + getTestName(false) + "_after.java"); } @@ -752,7 +777,7 @@ public class ExtractMethodTest extends LightCodeInsightTestCase { final boolean extractChainedConstructor, int... disabledParams) throws PrepareFailedException, IncorrectOperationException { - return performExtractMethod(doRefactor, replaceAllDuplicates, editor, file, project, extractChainedConstructor, null, false, disabledParams); + return performExtractMethod(doRefactor, replaceAllDuplicates, editor, file, project, extractChainedConstructor, null, false, null, disabledParams); } public static boolean performExtractMethod(boolean doRefactor, @@ -763,6 +788,7 @@ public class ExtractMethodTest extends LightCodeInsightTestCase { final boolean extractChainedConstructor, PsiType returnType, boolean makeStatic, + String newNameOfFirstParam, int... disabledParams) throws PrepareFailedException, IncorrectOperationException { int startOffset = editor.getSelectionModel().getSelectionStart(); @@ -801,15 +827,21 @@ public class ExtractMethodTest extends LightCodeInsightTestCase { processor.doNotPassParameter(param); } } + if (newNameOfFirstParam != null) { + processor.changeParamName(0, newNameOfFirstParam); + } ExtractMethodHandler.run(project, editor, processor); } if (replaceAllDuplicates) { - final List duplicates = processor.getDuplicates(); - for (final Match match : duplicates) { - if (!match.getMatchStart().isValid() || !match.getMatchEnd().isValid()) continue; - PsiDocumentManager.getInstance(project).commitAllDocuments(); - processor.processMatch(match); + final Boolean hasDuplicates = processor.hasDuplicates(); + if (hasDuplicates == null || hasDuplicates.booleanValue()) { + final List duplicates = processor.getDuplicates(); + for (final Match match : duplicates) { + if (!match.getMatchStart().isValid() || !match.getMatchEnd().isValid()) continue; + PsiDocumentManager.getInstance(project).commitAllDocuments(); + processor.processMatch(match); + } } } From e7c61535649c902f3d6d92314564af4f8e14367e Mon Sep 17 00:00:00 2001 From: Kirill Likhodedov Date: Fri, 5 Dec 2014 15:58:53 +0300 Subject: [PATCH 19/22] [log] Don't store VcsUser duplicates: intern them. --- .../src/com/intellij/vcs/log/VcsUserRegistry.java | 2 ++ .../vcs/log/data/VcsUserRegistryImpl.java | 15 ++++++++++++--- .../vcs/log/impl/VcsLogObjectsFactoryImpl.java | 10 +++++++++- 3 files changed, 23 insertions(+), 4 deletions(-) diff --git a/platform/vcs-log/api/src/com/intellij/vcs/log/VcsUserRegistry.java b/platform/vcs-log/api/src/com/intellij/vcs/log/VcsUserRegistry.java index 90971a4f172e..57dc92da5b62 100644 --- a/platform/vcs-log/api/src/com/intellij/vcs/log/VcsUserRegistry.java +++ b/platform/vcs-log/api/src/com/intellij/vcs/log/VcsUserRegistry.java @@ -27,4 +27,6 @@ public interface VcsUserRegistry { @NotNull Set getUsers(); + @NotNull + VcsUser createUser(@NotNull String name, @NotNull String email); } diff --git a/platform/vcs-log/impl/src/com/intellij/vcs/log/data/VcsUserRegistryImpl.java b/platform/vcs-log/impl/src/com/intellij/vcs/log/data/VcsUserRegistryImpl.java index 8621f379ce65..58896e5f8f5f 100644 --- a/platform/vcs-log/impl/src/com/intellij/vcs/log/data/VcsUserRegistryImpl.java +++ b/platform/vcs-log/impl/src/com/intellij/vcs/log/data/VcsUserRegistryImpl.java @@ -22,6 +22,7 @@ import com.intellij.openapi.project.Project; import com.intellij.openapi.util.Disposer; import com.intellij.openapi.util.ThrowableComputable; import com.intellij.util.containers.ContainerUtil; +import com.intellij.util.containers.Interner; import com.intellij.util.io.*; import com.intellij.vcs.log.VcsUser; import com.intellij.vcs.log.VcsUserRegistry; @@ -52,15 +53,17 @@ public class VcsUserRegistryImpl implements Disposable, VcsUserRegistry { }; @Nullable private final PersistentEnumerator myPersistentEnumerator; + @NotNull private final Interner myInterner; VcsUserRegistryImpl(@NotNull Project project) { final File mapFile = new File(USER_CACHE_APP_DIR, project.getName() + "." + project.getLocationHash()); Disposer.register(project, this); myPersistentEnumerator = initEnumerator(mapFile); + myInterner = new Interner(); } @Nullable - private static PersistentEnumerator initEnumerator(@NotNull final File mapFile) { + private PersistentEnumerator initEnumerator(@NotNull final File mapFile) { try { return IOUtil.openCleanOrResetBroken(new ThrowableComputable, IOException>() { @Override @@ -75,6 +78,12 @@ public class VcsUserRegistryImpl implements Disposable, VcsUserRegistry { } } + @NotNull + @Override + public VcsUser createUser(@NotNull String name, @NotNull String email) { + return myInterner.intern(new VcsUserImpl(name, email)); + } + public void addUser(@NotNull VcsUser user) { try { if (myPersistentEnumerator != null) { @@ -125,7 +134,7 @@ public class VcsUserRegistryImpl implements Disposable, VcsUserRegistry { } } - private static class MyDescriptor implements KeyDescriptor { + private class MyDescriptor implements KeyDescriptor { @Override public void save(@NotNull DataOutput out, VcsUser value) throws IOException { IOUtil.writeUTF(out, value.getName()); @@ -136,7 +145,7 @@ public class VcsUserRegistryImpl implements Disposable, VcsUserRegistry { public VcsUser read(@NotNull DataInput in) throws IOException { String name = IOUtil.readUTF(in); String email = IOUtil.readUTF(in); - return new VcsUserImpl(name, email); + return createUser(name, email); } @Override 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 06c1bc4564b9..b5502310bda5 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 @@ -11,6 +11,14 @@ import java.util.List; public class VcsLogObjectsFactoryImpl implements VcsLogObjectsFactory { + @NotNull private final VcsUserRegistry myUserRegistry; + + // created as application service + @SuppressWarnings("unused") + private VcsLogObjectsFactoryImpl(@NotNull VcsUserRegistry userRegistry) { + myUserRegistry = userRegistry; + } + @NotNull @Override public Hash createHash(@NotNull String stringHash) { @@ -60,7 +68,7 @@ public class VcsLogObjectsFactoryImpl implements VcsLogObjectsFactory { @NotNull @Override public VcsUser createUser(@NotNull String name, @NotNull String email) { - return new VcsUserImpl(name, email); + return myUserRegistry.createUser(name, email); } @NotNull From f7092c7cf5005cc854958b8bc139eadb9c25a538 Mon Sep 17 00:00:00 2001 From: "Egor.Ushakov" Date: Fri, 5 Dec 2014 16:00:08 +0300 Subject: [PATCH 20/22] fixed incorrect gutter background in code fragments (folding preview) in destruction free mode --- .../impl/EditorGutterComponentImpl.java | 45 ++++++++----------- 1 file changed, 18 insertions(+), 27 deletions(-) diff --git a/platform/platform-impl/src/com/intellij/openapi/editor/impl/EditorGutterComponentImpl.java b/platform/platform-impl/src/com/intellij/openapi/editor/impl/EditorGutterComponentImpl.java index edc4b642d25a..1d03c327030d 100644 --- a/platform/platform-impl/src/com/intellij/openapi/editor/impl/EditorGutterComponentImpl.java +++ b/platform/platform-impl/src/com/intellij/openapi/editor/impl/EditorGutterComponentImpl.java @@ -38,7 +38,6 @@ import com.intellij.openapi.diagnostic.Logger; import com.intellij.openapi.editor.*; import com.intellij.openapi.editor.colors.ColorKey; import com.intellij.openapi.editor.colors.EditorColors; -import com.intellij.openapi.editor.colors.EditorColorsScheme; import com.intellij.openapi.editor.colors.EditorFontType; import com.intellij.openapi.editor.event.EditorMouseEventArea; import com.intellij.openapi.editor.ex.*; @@ -96,7 +95,6 @@ class EditorGutterComponentImpl extends EditorGutterComponentEx implements Mouse private ArrayList myTextAnnotationGutters = new ArrayList(); private final Map myProviderToListener = new HashMap(); private static final int GAP_BETWEEN_ANNOTATIONS = 5; - private Color myBackgroundColor = null; private String myLastGutterToolTip = null; @NotNull private TIntFunction myLineNumberConvertor; private boolean myShowDefaultGutterPopup = true; @@ -174,7 +172,6 @@ class EditorGutterComponentImpl extends EditorGutterComponentEx implements Mouse } public void reinitSettings() { - myBackgroundColor = null; revalidateMarkup(); repaint(); } @@ -197,8 +194,9 @@ class EditorGutterComponentImpl extends EditorGutterComponentEx implements Mouse } UISettings.setupAntialiasing(g); - paintLineNumbersBackground(g, clip); - paintAnnotationsBackground(g, clip); + Color backgroundColor = getBackground(); + paintLineNumbersBackground(g, clip, backgroundColor); + paintAnnotationsBackground(g, clip, backgroundColor); Object hint = g2.getRenderingHint(RenderingHints.KEY_ANTIALIASING); if (!UIUtil.isRetina()) g2.setRenderingHint(RenderingHints.KEY_ANTIALIASING, RenderingHints.VALUE_ANTIALIAS_OFF); @@ -206,9 +204,9 @@ class EditorGutterComponentImpl extends EditorGutterComponentEx implements Mouse try { int firstVisibleOffset = myEditor.logicalPositionToOffset(myEditor.xyToLogicalPosition(new Point(0, clip.y - myEditor.getLineHeight()))); int lastVisibleOffset = myEditor.logicalPositionToOffset(myEditor.xyToLogicalPosition(new Point(0, clip.y + clip.height + myEditor.getLineHeight()))); - paintFoldingBackground(g, clip); - paintLineMarkersBackground(g, clip); - paintBackground(g, clip, getLineMarkerAreaOffset(), getLineMarkerAreaWidth()); + paintFoldingBackground(g, clip, backgroundColor); + paintLineMarkersBackground(g, clip, backgroundColor); + paintBackground(g, clip, getLineMarkerAreaOffset(), getLineMarkerAreaWidth(), backgroundColor); paintEditorBackgrounds(g, firstVisibleOffset, lastVisibleOffset); paintAnnotations(g, clip); paintLineMarkers(g, firstVisibleOffset, lastVisibleOffset); @@ -298,11 +296,10 @@ class EditorGutterComponentImpl extends EditorGutterComponentEx implements Mouse } } - private void paintAnnotationsBackground(Graphics g, Rectangle clip) { + private void paintAnnotationsBackground(Graphics g, Rectangle clip, Color backgroundColor) { int w = getAnnotationsAreaWidthEx(); if (w == 0) return; - final Color background = myEditor.isInDistractionFreeMode() ? myEditor.getBackgroundColor() : getBackground(); - paintBackground(g, clip, getAnnotationsAreaOffset(), w, background); + paintBackground(g, clip, getAnnotationsAreaOffset(), w, backgroundColor); } private void paintAnnotations(Graphics g, Rectangle clip) { @@ -356,9 +353,9 @@ class EditorGutterComponentImpl extends EditorGutterComponentEx implements Mouse } } - private void paintLineMarkersBackground(Graphics g, Rectangle clip) { + private void paintLineMarkersBackground(Graphics g, Rectangle clip, Color bgColor) { if (isLineMarkersShown()) { - paintBackground(g, clip, getLineMarkerAreaOffset(), getLineMarkerAreaWidth()); + paintBackground(g, clip, getLineMarkerAreaOffset(), getLineMarkerAreaWidth(), bgColor); } } @@ -368,10 +365,6 @@ class EditorGutterComponentImpl extends EditorGutterComponentEx implements Mouse } } - private void paintBackground(final Graphics g, final Rectangle clip, final int x, final int width) { - paintBackground(g, clip, x, width, getBackground()); - } - private void paintBackground(final Graphics g, final Rectangle clip, final int x, @@ -399,21 +392,19 @@ class EditorGutterComponentImpl extends EditorGutterComponentEx implements Mouse } } - private void paintLineNumbersBackground(Graphics g, Rectangle clip) { + private void paintLineNumbersBackground(Graphics g, Rectangle clip, Color bgColor) { if (isLineNumbersShown()) { - paintBackground(g, clip, getLineNumberAreaOffset(), getLineNumberAreaWidth()); + paintBackground(g, clip, getLineNumberAreaOffset(), getLineNumberAreaWidth(), bgColor); } } @Override public Color getBackground() { - if (myBackgroundColor == null) { - EditorColorsScheme colorsScheme = myEditor.getColorsScheme(); - boolean distractionMode = myEditor.isInDistractionFreeMode(); - Color color = distractionMode ? colorsScheme.getDefaultBackground() : colorsScheme.getColor(EditorColors.GUTTER_BACKGROUND); - myBackgroundColor = color == null ? EditorColors.GUTTER_BACKGROUND.getDefaultColor() : color; + if (myEditor.isInDistractionFreeMode()) { + return myEditor.getBackgroundColor(); } - return myBackgroundColor; + Color color = myEditor.getColorsScheme().getColor(EditorColors.GUTTER_BACKGROUND); + return color != null ? color : EditorColors.GUTTER_BACKGROUND.getDefaultColor(); } private void doPaintLineNumbers(Graphics g, Rectangle clip) { @@ -850,9 +841,9 @@ class EditorGutterComponentImpl extends EditorGutterComponentEx implements Mouse } } - private void paintFoldingBackground(Graphics g, Rectangle clip) { + private void paintFoldingBackground(Graphics g, Rectangle clip, Color bgColor) { int lineX = getWhitespaceSeparatorOffset(); - paintBackground(g, clip, getFoldingAreaOffset(), getFoldingAreaWidth()); + paintBackground(g, clip, getFoldingAreaOffset(), getFoldingAreaWidth(), bgColor); g.setColor(myEditor.getBackgroundColor()); g.fillRect(lineX, clip.y, getFoldingAreaWidth(), clip.height); From f1f4efb944dddcb61fa719de7c133c49ee8a69ad Mon Sep 17 00:00:00 2001 From: Kirill Likhodedov Date: Fri, 5 Dec 2014 16:06:39 +0300 Subject: [PATCH 21/22] [git] Use more specific method for branch names in pull dialog --- plugins/git4idea/src/git4idea/merge/GitPullDialog.java | 3 +-- 1 file changed, 1 insertion(+), 2 deletions(-) diff --git a/plugins/git4idea/src/git4idea/merge/GitPullDialog.java b/plugins/git4idea/src/git4idea/merge/GitPullDialog.java index faf9398ba966..be1ebac877ab 100644 --- a/plugins/git4idea/src/git4idea/merge/GitPullDialog.java +++ b/plugins/git4idea/src/git4idea/merge/GitPullDialog.java @@ -24,7 +24,6 @@ import com.intellij.openapi.vfs.VirtualFile; import com.intellij.ui.ListCellRendererWrapper; import com.intellij.util.Function; import com.intellij.util.containers.ContainerUtil; -import git4idea.GitBranch; import git4idea.GitRemoteBranch; import git4idea.GitUtil; import git4idea.commands.GitCommand; @@ -175,7 +174,7 @@ public class GitPullDialog extends DialogWrapper { myBranchChooser.setElements(ContainerUtil.mapNotNull(remoteBranches, new Function() { @Override public String fun(GitRemoteBranch branch) { - return branch.getRemote().getName().equals(selectedRemote) ? branch.getName() : null; + return branch.getRemote().getName().equals(selectedRemote) ? branch.getNameForLocalOperations() : null; } }), false); if (currentRemoteBranch != null && currentRemoteBranch.getRemote().getName().equals(selectedRemote)) { From c236371f2c742990a63abaf569dfeb517479e649 Mon Sep 17 00:00:00 2001 From: Mikhail Golubev Date: Fri, 5 Dec 2014 15:59:08 +0300 Subject: [PATCH 22/22] Use SearchParameters#getScopeDeterminedByUser in PyKeywordArgumentSearchExecutor Also added missing read action for ScopeUtil#getScopeOwner(element). --- .../search/PyKeywordArgumentSearchExecutor.java | 16 +++++++--------- 1 file changed, 7 insertions(+), 9 deletions(-) diff --git a/python/src/com/jetbrains/python/psi/search/PyKeywordArgumentSearchExecutor.java b/python/src/com/jetbrains/python/psi/search/PyKeywordArgumentSearchExecutor.java index 135a4b908bbf..2aa7d86b18c7 100644 --- a/python/src/com/jetbrains/python/psi/search/PyKeywordArgumentSearchExecutor.java +++ b/python/src/com/jetbrains/python/psi/search/PyKeywordArgumentSearchExecutor.java @@ -20,7 +20,6 @@ import com.intellij.openapi.application.QueryExecutorBase; import com.intellij.openapi.util.Computable; import com.intellij.psi.PsiElement; import com.intellij.psi.PsiReference; -import com.intellij.psi.search.SearchScope; import com.intellij.psi.search.searches.ReferencesSearch; import com.intellij.psi.util.PsiTreeUtil; import com.intellij.util.Processor; @@ -39,17 +38,16 @@ public class PyKeywordArgumentSearchExecutor extends QueryExecutorBase() { + @Override + public ScopeOwner compute() { + return ScopeUtil.getScopeOwner(element); + } + }); if (!(owner instanceof PyFunction)) { return; } - SearchScope scope = ApplicationManager.getApplication().runReadAction(new Computable() { - @Override - public SearchScope compute() { - return queryParameters.getEffectiveSearchScope(); - } - }); - ReferencesSearch.search(owner, scope).forEach(new Processor() { + ReferencesSearch.search(owner, queryParameters.getScopeDeterminedByUser()).forEach(new Processor() { @Override public boolean process(PsiReference reference) { final PsiElement refElement = reference.getElement();