From 4cbd103a240c223b7ff071f0c764860b94adb964 Mon Sep 17 00:00:00 2001 From: Bas Leijdekkers Date: Mon, 30 Jan 2012 10:36:10 +0100 Subject: [PATCH 1/9] improve quickfix for "'StringBuffer' can be replaced with 'String'" inspection and add some tests for it --- ...ngBufferReplaceableByStringInspection.java | 45 ++++++++++++------- .../SimpleStringBuffer.after.java | 7 +++ .../SimpleStringBuffer.java | 7 +++ .../StartsWithPrimitive.after.java | 6 +++ .../StartsWithPrimitive.java | 6 +++ .../StringBufferVariable.after.java | 6 +++ .../StringBufferVariable.java | 6 +++ .../StringBuilderAppend.after.java | 5 +++ .../StringBuilderAppend.java | 5 +++ ...ingBufferReplaceableWithStringFixTest.java | 36 +++++++++++++++ 10 files changed, 112 insertions(+), 17 deletions(-) create mode 100644 plugins/InspectionGadgets/test/com/siyeh/igfixes/style/replace_with_string/SimpleStringBuffer.after.java create mode 100644 plugins/InspectionGadgets/test/com/siyeh/igfixes/style/replace_with_string/SimpleStringBuffer.java create mode 100644 plugins/InspectionGadgets/test/com/siyeh/igfixes/style/replace_with_string/StartsWithPrimitive.after.java create mode 100644 plugins/InspectionGadgets/test/com/siyeh/igfixes/style/replace_with_string/StartsWithPrimitive.java create mode 100644 plugins/InspectionGadgets/test/com/siyeh/igfixes/style/replace_with_string/StringBufferVariable.after.java create mode 100644 plugins/InspectionGadgets/test/com/siyeh/igfixes/style/replace_with_string/StringBufferVariable.java create mode 100644 plugins/InspectionGadgets/test/com/siyeh/igfixes/style/replace_with_string/StringBuilderAppend.after.java create mode 100644 plugins/InspectionGadgets/test/com/siyeh/igfixes/style/replace_with_string/StringBuilderAppend.java create mode 100644 plugins/InspectionGadgets/testsrc/com/siyeh/ig/fixes/style/StringBufferReplaceableWithStringFixTest.java diff --git a/plugins/InspectionGadgets/src/com/siyeh/ig/style/StringBufferReplaceableByStringInspection.java b/plugins/InspectionGadgets/src/com/siyeh/ig/style/StringBufferReplaceableByStringInspection.java index 38eed03f36cd..a7e13174cc6f 100644 --- a/plugins/InspectionGadgets/src/com/siyeh/ig/style/StringBufferReplaceableByStringInspection.java +++ b/plugins/InspectionGadgets/src/com/siyeh/ig/style/StringBufferReplaceableByStringInspection.java @@ -66,7 +66,8 @@ public class StringBufferReplaceableByStringInspection extends BaseInspection { public String getName() { if (isStringBuilder) { return InspectionGadgetsBundle.message("string.builder.replaceable.by.string.quickfix"); - } else { + } + else { return InspectionGadgetsBundle.message("string.buffer.replaceable.by.string.quickfix"); } } @@ -110,20 +111,16 @@ public class StringBufferReplaceableByStringInspection extends BaseInspection { final PsiNewExpression newExpression = (PsiNewExpression)initializer; final PsiExpressionList argumentList = newExpression.getArgumentList(); final PsiExpression[] arguments = argumentList.getExpressions(); - if (arguments.length == 0) { - result.append("\"\""); - } else if (arguments.length == 1) { + if (arguments.length == 1) { final PsiExpression argument = arguments[0]; final PsiType type = argument.getType(); - if (PsiType.INT.equals(type)) { - result.append("\"\""); - } else { + if (!PsiType.INT.equals(type)) { result.append(argument.getText()); } - } else { - return null; } - } else if (initializer instanceof PsiMethodCallExpression) { + return result; + } + else if (initializer instanceof PsiMethodCallExpression) { final PsiMethodCallExpression methodCallExpression = (PsiMethodCallExpression)initializer; final PsiReferenceExpression methodExpression = methodCallExpression.getMethodExpression(); final PsiExpression qualifier = methodExpression.getQualifierExpression(); @@ -131,20 +128,34 @@ public class StringBufferReplaceableByStringInspection extends BaseInspection { if (result == null) { return null; } - if (!"toString".equals(methodExpression.getReferenceName())) { + if ("toString".equals(methodExpression.getReferenceName())) { + if (result.length() == 0) { + result.append("\"\""); + } + } + else { final PsiExpressionList argumentList = methodCallExpression.getArgumentList(); final PsiExpression[] arguments = argumentList.getExpressions(); if (arguments.length != 1) { return null; } final PsiExpression argument = arguments[0]; - result.append('+'); - result.append(argument.getText()); + if (result.length() != 0) { + result.append('+').append(argument.getText()); + } + else { + final PsiType type = argument.getType(); + if (type instanceof PsiPrimitiveType) { + result.append("String.valueOf(").append(argument.getText()).append(")"); + } + else { + result.append(argument.getText()); + } + } } - } else { - return null; + return result; } - return result; + return null; } } @@ -261,7 +272,7 @@ public class StringBufferReplaceableByStringInspection extends BaseInspection { } completeExpression = grandParent; if (found) { - return (PsiExpression) completeExpression; + return (PsiExpression)completeExpression; } } return null; diff --git a/plugins/InspectionGadgets/test/com/siyeh/igfixes/style/replace_with_string/SimpleStringBuffer.after.java b/plugins/InspectionGadgets/test/com/siyeh/igfixes/style/replace_with_string/SimpleStringBuffer.after.java new file mode 100644 index 000000000000..f948a968151e --- /dev/null +++ b/plugins/InspectionGadgets/test/com/siyeh/igfixes/style/replace_with_string/SimpleStringBuffer.after.java @@ -0,0 +1,7 @@ +package com.siyeh.igfixes.style.replace_with_string; + +public class SimpleStringBuffer { + String foo() { + return ""; + } +} diff --git a/plugins/InspectionGadgets/test/com/siyeh/igfixes/style/replace_with_string/SimpleStringBuffer.java b/plugins/InspectionGadgets/test/com/siyeh/igfixes/style/replace_with_string/SimpleStringBuffer.java new file mode 100644 index 000000000000..77902d4bcc51 --- /dev/null +++ b/plugins/InspectionGadgets/test/com/siyeh/igfixes/style/replace_with_string/SimpleStringBuffer.java @@ -0,0 +1,7 @@ +package com.siyeh.igfixes.style.replace_with_string; + +public class SimpleStringBuffer { + String foo() { + return new StringBuffer().toString(); + } +} diff --git a/plugins/InspectionGadgets/test/com/siyeh/igfixes/style/replace_with_string/StartsWithPrimitive.after.java b/plugins/InspectionGadgets/test/com/siyeh/igfixes/style/replace_with_string/StartsWithPrimitive.after.java new file mode 100644 index 000000000000..89721d3ace90 --- /dev/null +++ b/plugins/InspectionGadgets/test/com/siyeh/igfixes/style/replace_with_string/StartsWithPrimitive.after.java @@ -0,0 +1,6 @@ +class StartsWithPrimitive { + + String foo(int i) { + return String.valueOf(i); + } +} \ No newline at end of file diff --git a/plugins/InspectionGadgets/test/com/siyeh/igfixes/style/replace_with_string/StartsWithPrimitive.java b/plugins/InspectionGadgets/test/com/siyeh/igfixes/style/replace_with_string/StartsWithPrimitive.java new file mode 100644 index 000000000000..c0f4d874fb49 --- /dev/null +++ b/plugins/InspectionGadgets/test/com/siyeh/igfixes/style/replace_with_string/StartsWithPrimitive.java @@ -0,0 +1,6 @@ +class StartsWithPrimitive { + + String foo(int i) { + return new StringBuffer().append(i).toString(); + } +} \ No newline at end of file diff --git a/plugins/InspectionGadgets/test/com/siyeh/igfixes/style/replace_with_string/StringBufferVariable.after.java b/plugins/InspectionGadgets/test/com/siyeh/igfixes/style/replace_with_string/StringBufferVariable.after.java new file mode 100644 index 000000000000..9f7b9e2af3a0 --- /dev/null +++ b/plugins/InspectionGadgets/test/com/siyeh/igfixes/style/replace_with_string/StringBufferVariable.after.java @@ -0,0 +1,6 @@ +class StringBufferVariable { + void foo() { + String sb = "asdf" + "asdf"; + System.out.println(sb.toString()); + } +} \ No newline at end of file diff --git a/plugins/InspectionGadgets/test/com/siyeh/igfixes/style/replace_with_string/StringBufferVariable.java b/plugins/InspectionGadgets/test/com/siyeh/igfixes/style/replace_with_string/StringBufferVariable.java new file mode 100644 index 000000000000..27b16ee7b452 --- /dev/null +++ b/plugins/InspectionGadgets/test/com/siyeh/igfixes/style/replace_with_string/StringBufferVariable.java @@ -0,0 +1,6 @@ +class StringBufferVariable { + void foo() { + StringBuffer sb = new StringBuffer("asdf").append("asdf"); + System.out.println(sb.toString()); + } +} \ No newline at end of file diff --git a/plugins/InspectionGadgets/test/com/siyeh/igfixes/style/replace_with_string/StringBuilderAppend.after.java b/plugins/InspectionGadgets/test/com/siyeh/igfixes/style/replace_with_string/StringBuilderAppend.after.java new file mode 100644 index 000000000000..8282bb29cafe --- /dev/null +++ b/plugins/InspectionGadgets/test/com/siyeh/igfixes/style/replace_with_string/StringBuilderAppend.after.java @@ -0,0 +1,5 @@ +class StringBuilderAppend { + String foo(int i) { + return "test: " + i; + } +} \ No newline at end of file diff --git a/plugins/InspectionGadgets/test/com/siyeh/igfixes/style/replace_with_string/StringBuilderAppend.java b/plugins/InspectionGadgets/test/com/siyeh/igfixes/style/replace_with_string/StringBuilderAppend.java new file mode 100644 index 000000000000..ff584cf2c249 --- /dev/null +++ b/plugins/InspectionGadgets/test/com/siyeh/igfixes/style/replace_with_string/StringBuilderAppend.java @@ -0,0 +1,5 @@ +class StringBuilderAppend { + String foo(int i) { + return new StringBuilder().append("test: ").append(i).toString(); + } +} \ No newline at end of file diff --git a/plugins/InspectionGadgets/testsrc/com/siyeh/ig/fixes/style/StringBufferReplaceableWithStringFixTest.java b/plugins/InspectionGadgets/testsrc/com/siyeh/ig/fixes/style/StringBufferReplaceableWithStringFixTest.java new file mode 100644 index 000000000000..0d03db24fa17 --- /dev/null +++ b/plugins/InspectionGadgets/testsrc/com/siyeh/ig/fixes/style/StringBufferReplaceableWithStringFixTest.java @@ -0,0 +1,36 @@ +/* + * Copyright 2012 Bas Leijdekkers + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ +package com.siyeh.ig.fixes.style; + +import com.siyeh.InspectionGadgetsBundle; +import com.siyeh.ig.IGQuickFixesTestCase; +import com.siyeh.ig.style.StringBufferReplaceableByStringInspection; + +public class StringBufferReplaceableWithStringFixTest extends IGQuickFixesTestCase { + + @Override + public void setUp() throws Exception { + super.setUp(); + myFixture.enableInspections(new StringBufferReplaceableByStringInspection()); + myRelativePath = "style/replace_with_string"; + myDefaultHint = InspectionGadgetsBundle.message("string.buffer.replaceable.by.string.quickfix"); + } + + public void testSimpleStringBuffer() { doTest(); } + public void testStringBuilderAppend() { doTest("StringBuilderAppend", InspectionGadgetsBundle.message("string.builder.replaceable.by.string.quickfix")); } + public void testStringBufferVariable() { doTest(); } + public void testStartsWithPrimitive() { doTest(); } +} From af2342af0aa8ef2087c2e625ef48dd483155c78c Mon Sep 17 00:00:00 2001 From: Dennis Ushakov Date: Mon, 30 Jan 2012 13:09:37 +0400 Subject: [PATCH 2/9] middle click close support --- .../ui/layout/actions/CloseViewAction.java | 10 +++++++--- .../execution/ui/layout/impl/RunnerContentUi.java | 15 +++++++++++++++ 2 files changed, 22 insertions(+), 3 deletions(-) diff --git a/platform/lang-impl/src/com/intellij/execution/ui/layout/actions/CloseViewAction.java b/platform/lang-impl/src/com/intellij/execution/ui/layout/actions/CloseViewAction.java index cb18ab9d5840..54ccf41abb3b 100644 --- a/platform/lang-impl/src/com/intellij/execution/ui/layout/actions/CloseViewAction.java +++ b/platform/lang-impl/src/com/intellij/execution/ui/layout/actions/CloseViewAction.java @@ -29,16 +29,20 @@ public class CloseViewAction extends BaseViewAction { private static final Icon HOVERED_ICON = IconLoader.getIcon("/actions/closeNewHovered.png"); protected void update(final AnActionEvent e, final ViewContext context, final Content[] content) { - setEnabled(e, isEnabled(context, content, e.getPlace())); + setEnabled(e, isEnabled(content)); e.getPresentation().setIcon(ICON); e.getPresentation().setHoveredIcon(HOVERED_ICON); } protected void actionPerformed(final AnActionEvent e, final ViewContext context, final Content[] content) { - context.getContentManager().removeContent(content[0], context.isToDisposeRemovedContent()); + perform(context, content[0]); } - public static boolean isEnabled(ViewContext context, Content[] content, String place) { + public static boolean perform(ViewContext context, Content content) { + return context.getContentManager().removeContent(content, context.isToDisposeRemovedContent()); + } + + public static boolean isEnabled(Content[] content) { return content.length == 1 && content[0].isCloseable(); } diff --git a/platform/lang-impl/src/com/intellij/execution/ui/layout/impl/RunnerContentUi.java b/platform/lang-impl/src/com/intellij/execution/ui/layout/impl/RunnerContentUi.java index 5846a58bd543..988721d50064 100644 --- a/platform/lang-impl/src/com/intellij/execution/ui/layout/impl/RunnerContentUi.java +++ b/platform/lang-impl/src/com/intellij/execution/ui/layout/impl/RunnerContentUi.java @@ -18,6 +18,7 @@ package com.intellij.execution.ui.layout.impl; import com.intellij.execution.ui.RunnerLayoutUi; import com.intellij.execution.ui.layout.*; +import com.intellij.execution.ui.layout.actions.CloseViewAction; import com.intellij.execution.ui.layout.actions.RestoreViewAction; import com.intellij.ide.DataManager; import com.intellij.openapi.Disposable; @@ -56,6 +57,7 @@ import org.jetbrains.annotations.Nullable; import javax.swing.*; import javax.swing.border.EmptyBorder; import java.awt.*; +import java.awt.event.MouseAdapter; import java.awt.event.MouseEvent; import java.beans.PropertyChangeEvent; import java.beans.PropertyChangeListener; @@ -236,6 +238,19 @@ public class RunnerContentUi implements ContentUI, Disposable, CellTransform.Fac } } }); + myTabs.addTabMouseListener(new MouseAdapter() { + @Override + public void mousePressed(MouseEvent e) { + if (UIUtil.isCloseClick(e)) { + final TabInfo tabInfo = myTabs.findInfo(e); + final GridImpl grid = getGridFor(tabInfo); + final Content[] contents = grid != null ? CONTENT_KEY.getData(grid) : null; + if (contents != null && CloseViewAction.isEnabled(contents)) { + CloseViewAction.perform(RunnerContentUi.this, contents[0]); + } + } + } + }); if (myOriginal != null) { final ContentManager manager = ContentFactory.SERVICE.getInstance().createContentManager(this, false, myProject); From f5e57a553cf0dd8b84cedc578e9a3259670c9804 Mon Sep 17 00:00:00 2001 From: Konstantin Bulenkov Date: Mon, 30 Jan 2012 10:37:42 +0100 Subject: [PATCH 3/9] fix useless components loading --- .../persistence/ApplicationStatisticsPersistenceComponent.java | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/platform/platform-impl/src/com/intellij/internal/statistic/persistence/ApplicationStatisticsPersistenceComponent.java b/platform/platform-impl/src/com/intellij/internal/statistic/persistence/ApplicationStatisticsPersistenceComponent.java index 5521c2286217..319cd705803a 100644 --- a/platform/platform-impl/src/com/intellij/internal/statistic/persistence/ApplicationStatisticsPersistenceComponent.java +++ b/platform/platform-impl/src/com/intellij/internal/statistic/persistence/ApplicationStatisticsPersistenceComponent.java @@ -19,7 +19,6 @@ package com.intellij.internal.statistic.persistence; import com.intellij.ide.AppLifecycleListener; import com.intellij.internal.statistic.AbstractApplicationUsagesCollector; import com.intellij.internal.statistic.UsagesCollector; -import com.intellij.internal.statistic.beans.ConvertUsagesUtil; import com.intellij.internal.statistic.beans.GroupDescriptor; import com.intellij.internal.statistic.beans.UsageDescriptor; import com.intellij.openapi.application.ApplicationManager; @@ -29,6 +28,7 @@ import com.intellij.openapi.components.PersistentStateComponent; import com.intellij.openapi.components.State; import com.intellij.openapi.components.Storage; import com.intellij.openapi.extensions.Extensions; +import com.intellij.openapi.project.DumbService; import com.intellij.openapi.project.Project; import com.intellij.openapi.project.ProjectManager; import com.intellij.openapi.project.ProjectManagerListener; @@ -218,6 +218,7 @@ public class ApplicationStatisticsPersistenceComponent extends ApplicationStatis } private static void doPersistProjectUsages(@NotNull Project project) { + if (DumbService.isDumb(project)) return; for (UsagesCollector usagesCollector : Extensions.getExtensions(UsagesCollector.EP_NAME)) { if (usagesCollector instanceof AbstractApplicationUsagesCollector) { ((AbstractApplicationUsagesCollector)usagesCollector).persistProjectUsages(project); From cd608ea812081e8406f333b643dc16c3789f1ed5 Mon Sep 17 00:00:00 2001 From: Bas Leijdekkers Date: Mon, 30 Jan 2012 11:15:12 +0100 Subject: [PATCH 4/9] add space before "cherry-picked" message, remove unnecessary StringBuilder --- .../git4idea/src/git4idea/history/browser/CherryPicker.java | 3 +-- 1 file changed, 1 insertion(+), 2 deletions(-) diff --git a/plugins/git4idea/src/git4idea/history/browser/CherryPicker.java b/plugins/git4idea/src/git4idea/history/browser/CherryPicker.java index 9ce3a4615a40..f76af153ddaf 100644 --- a/plugins/git4idea/src/git4idea/history/browser/CherryPicker.java +++ b/plugins/git4idea/src/git4idea/history/browser/CherryPicker.java @@ -148,8 +148,7 @@ public class CherryPicker { final Collection paths = ChangesUtil.getPaths(changes); String message = ce.getDefaultMessageFor(paths.toArray(new FilePath[paths.size()])); - message = (message == null) ? new StringBuilder().append(commit.getDescription()).append("(cherry picked from commit ") - .append(commit.getShortHash()).append(")").toString() : message; + message = (message == null) ? commit.getDescription() + " (cherry picked from commit " + commit.getShortHash() + ")" : message; myMessagesInOrder.add(message); myFilesToMove.put(message, paths); From d70ddb25fd4816063664e81e8c20bd292d30b8b3 Mon Sep 17 00:00:00 2001 From: dboulytchev Date: Mon, 30 Jan 2012 14:26:32 +0400 Subject: [PATCH 5/9] Continue retooling incremental tests to the new builders (compiler server). --- .../jps/incremental/IncProjectBuilder.java | 37 +++--- .../jetbrains/ether/IncrementalTestCase.java | 111 +++++++++--------- 2 files changed, 76 insertions(+), 72 deletions(-) diff --git a/jps/jps-builders/src/org/jetbrains/jps/incremental/IncProjectBuilder.java b/jps/jps-builders/src/org/jetbrains/jps/incremental/IncProjectBuilder.java index cfba0719cf25..931bc55ca636 100644 --- a/jps/jps-builders/src/org/jetbrains/jps/incremental/IncProjectBuilder.java +++ b/jps/jps-builders/src/org/jetbrains/jps/incremental/IncProjectBuilder.java @@ -390,6 +390,8 @@ public class IncProjectBuilder { final BuildDataManager dataManager = context.getDataManager(); final boolean compilingTests = context.isCompilingTests(); try { + final Collection allOutputs = new LinkedList(); + context.processFilesToRecompile(chunk, new FileProcessor() { private final Map storageMap = new HashMap(); @@ -403,24 +405,11 @@ public class IncProjectBuilder { final String srcPath = FileUtil.toSystemIndependentName(file.getPath()); final Collection outputs = srcToOut.getState(srcPath); - if (LOG.isDebugEnabled()) { - if (outputs != null && context.isMake()) { - LOG.info("Cleaning output files:"); - final String[] buffer = new String[outputs.size()]; - int i = 0; - for (String output : outputs) { - buffer[i++] = output; - } - Arrays.sort(buffer); - for (String output : buffer) { - LOG.info(output); - } - LOG.info("End of files"); - } - } - if (outputs != null) { for (String output : outputs) { + if (LOG.isDebugEnabled()) { + allOutputs.add(output); + } FileUtil.delete(new File(output)); } srcToOut.remove(srcPath); @@ -428,6 +417,22 @@ public class IncProjectBuilder { return true; } }); + + if (LOG.isDebugEnabled()) { + if (context.isMake() && allOutputs.size() > 0) { + LOG.info("Cleaning output files:"); + final String[] buffer = new String[allOutputs.size()]; + int i = 0; + for (String output : allOutputs) { + buffer[i++] = output; + } + Arrays.sort(buffer); + for (String output : buffer) { + LOG.info(output); + } + LOG.info("End of files"); + } + } } catch (Exception e) { throw new ProjectBuildException(e); diff --git a/jps/jps-builders/testSrc/org/jetbrains/ether/IncrementalTestCase.java b/jps/jps-builders/testSrc/org/jetbrains/ether/IncrementalTestCase.java index d2e63772a39e..d0ea12113625 100644 --- a/jps/jps-builders/testSrc/org/jetbrains/ether/IncrementalTestCase.java +++ b/jps/jps-builders/testSrc/org/jetbrains/ether/IncrementalTestCase.java @@ -59,7 +59,61 @@ public abstract class IncrementalTestCase extends TestCase { return s; } } - + + static { + Logger.setFactory(new Logger.Factory() { + @Override + public Logger getLoggerInstance(String category) { + final org.apache.log4j.Logger logger = org.apache.log4j.Logger.getLogger(category); + + final boolean affectedLogger = category.equals("#org.jetbrains.jps.incremental.java.JavaBuilder") || + category.equals("#org.jetbrains.jps.incremental.IncProjectBuilder"); + + return new Logger() { + @Override + public boolean isDebugEnabled() { + return affectedLogger; + } + + @Override + public void debug(@NonNls String message) { + } + + @Override + public void debug(@Nullable Throwable t) { + } + + @Override + public void debug(@NonNls String message, @Nullable Throwable t) { + } + + @Override + public void error(@NonNls String message, @Nullable Throwable t, @NonNls String... details) { + } + + @Override + public void info(@NonNls String message) { + if (affectedLogger) { + logger.info(stripper.strip(message)); + } + } + + @Override + public void info(@NonNls String message, @Nullable Throwable t) { + } + + @Override + public void warn(@NonNls String message, @Nullable Throwable t) { + } + + @Override + public void setLevel(Level level) { + } + }; + } + }); + } + private static RootStripper stripper = new RootStripper(); private final String groupName; @@ -198,61 +252,6 @@ public abstract class IncrementalTestCase extends TestCase { properties.setProperty("log4j.appender.A1.layout.ConversionPattern", "%m%n"); PropertyConfigurator.configure(properties); - - Logger.setFactory(new Logger.Factory() { - @Override - public Logger getLoggerInstance(String category) { - final org.apache.log4j.Logger logger = org.apache.log4j.Logger.getLogger(category); - - final boolean affectedLogger = category.equals("#org.jetbrains.jps.incremental.java.JavaBuilder") || - category.equals("#org.jetbrains.jps.incremental.IncProjectBuilder"); - - final String root = getWorkDir() + File.separator; - final int pos = root.length(); - - return new Logger() { - @Override - public boolean isDebugEnabled() { - return affectedLogger; - } - - @Override - public void debug(@NonNls String message) { - } - - @Override - public void debug(@Nullable Throwable t) { - } - - @Override - public void debug(@NonNls String message, @Nullable Throwable t) { - } - - @Override - public void error(@NonNls String message, @Nullable Throwable t, @NonNls String... details) { - } - - @Override - public void info(@NonNls String message) { - if (affectedLogger) { - logger.info(stripper.strip(message)); - } - } - - @Override - public void info(@NonNls String message, @Nullable Throwable t) { - } - - @Override - public void warn(@NonNls String message, @Nullable Throwable t) { - } - - @Override - public void setLevel(Level level) { - } - }; - } - }); } public void doTest() throws Exception { From 894f63ec7084ffebe47b7d8de45c152dc25fa10f Mon Sep 17 00:00:00 2001 From: Konstantin Bulenkov Date: Mon, 30 Jan 2012 12:53:57 +0100 Subject: [PATCH 6/9] file structure base test case --- .../ide/actions/ViewStructureAction.java | 2 +- .../intellij/ide/util/FileStructurePopup.java | 85 ++++++++----- .../ide/util/treeView/AbstractTreeUi.java | 18 ++- .../filtered/FilteringTreeBuilder.java | 39 ++++-- .../testFramework/FileStructureTestBase.java | 119 ++++++++++++++++++ 5 files changed, 215 insertions(+), 48 deletions(-) create mode 100644 platform/testFramework/src/com/intellij/testFramework/FileStructureTestBase.java diff --git a/platform/lang-impl/src/com/intellij/ide/actions/ViewStructureAction.java b/platform/lang-impl/src/com/intellij/ide/actions/ViewStructureAction.java index a1e115a7f014..4e64b7c3983c 100644 --- a/platform/lang-impl/src/com/intellij/ide/actions/ViewStructureAction.java +++ b/platform/lang-impl/src/com/intellij/ide/actions/ViewStructureAction.java @@ -90,7 +90,7 @@ public class ViewStructureAction extends AnAction { } @Nullable - private static FileStructurePopup createPopup(final Editor editor, Project project, Navigatable navigatable, final FileEditor fileEditor) { + public static FileStructurePopup createPopup(final Editor editor, Project project, @Nullable Navigatable navigatable, final FileEditor fileEditor) { final StructureViewBuilder structureViewBuilder = fileEditor.getStructureViewBuilder(); if (structureViewBuilder == null) return null; StructureView structureView = structureViewBuilder.createStructureView(fileEditor, project); diff --git a/platform/lang-impl/src/com/intellij/ide/util/FileStructurePopup.java b/platform/lang-impl/src/com/intellij/ide/util/FileStructurePopup.java index 2285504fe806..9d885b1e49d8 100644 --- a/platform/lang-impl/src/com/intellij/ide/util/FileStructurePopup.java +++ b/platform/lang-impl/src/com/intellij/ide/util/FileStructurePopup.java @@ -149,6 +149,7 @@ public class FileStructurePopup implements Disposable { myTree = new JBTreeWithHintProvider(new DefaultMutableTreeNode(myTreeStructure.getRootElement())) { @Override protected PsiElement getPsiElementForHint(Object selectedValue) { + //noinspection ConstantConditions return getPsi((FilteringTreeStructure.FilteringNode)((DefaultMutableTreeNode)selectedValue).getUserObject()); } }; @@ -218,12 +219,13 @@ public class FileStructurePopup implements Disposable { return current.isEmpty() ? null : findClosestTo(myInitialPsiElement, current); } + @Nullable private Object findClosestTo(PsiElement path, ArrayList paths) { if (path == null || myInitialPsiElement == null) { return paths.get(0).node; } final Set parents = getAllParents(myInitialPsiElement); - Object cur = paths.get(0).node; + ArrayList cur = new ArrayList(); int max = -1; for (ObjectWithWeight p : paths) { final Object last = ((TreePath)p.node).getLastPathComponent(); @@ -238,14 +240,21 @@ public class FileStructurePopup implements Disposable { final int size = ContainerUtil.intersection(parents, elements).size(); if (size > max) { max = size; - cur = p.node; - } else if (size == max && size == parents.size()) { - cur = p.node; + cur.clear(); + cur.add((TreePath)p.node); + } else if (size == max) { + cur.add((TreePath)p.node); } } } - return cur; + Collections.sort(cur, new Comparator() { + @Override + public int compare(TreePath o1, TreePath o2) { + return o2.getPathCount() - o1.getPathCount(); + } + }); + return cur.isEmpty() ? null : cur.get(0); } class ObjectWithWeight { @@ -285,7 +294,7 @@ public class FileStructurePopup implements Disposable { mySpeedSearch.setComparator(new SpeedSearchComparator(false, true)); final FileStructurePopupFilter filter = new FileStructurePopupFilter(); - myFilteringStructure = new FilteringTreeStructure(filter, myTreeStructure, false); + myFilteringStructure = new FilteringTreeStructure(filter, myTreeStructure, ApplicationManager.getApplication().isUnitTestMode()); myAbstractTreeBuilder = new FilteringTreeBuilder(myTree, filter, myFilteringStructure, null) { @Override protected boolean validateNode(Object child) { @@ -385,35 +394,37 @@ public class FileStructurePopup implements Disposable { }); } }); - final Alarm alarm = new Alarm(Alarm.ThreadToUse.SHARED_THREAD, myPopup); - alarm.addRequest(new Runnable() { - String filter = ""; + if (!ApplicationManager.getApplication().isUnitTestMode()) { + final Alarm alarm = new Alarm(Alarm.ThreadToUse.SHARED_THREAD, myPopup); + alarm.addRequest(new Runnable() { + String filter = ""; - @Override - public void run() { - alarm.cancelAllRequests(); - String prefix = mySpeedSearch.getEnteredPrefix(); - myTree.getEmptyText().setText(StringUtil.isEmpty(prefix) ? "Nothing to show" : "Can't find '" + prefix + "'"); - if (prefix == null) prefix = ""; + @Override + public void run() { + alarm.cancelAllRequests(); + String prefix = mySpeedSearch.getEnteredPrefix(); + myTree.getEmptyText().setText(StringUtil.isEmpty(prefix) ? "Nothing to show" : "Can't find '" + prefix + "'"); + if (prefix == null) prefix = ""; - if (!filter.equals(prefix)) { - filter = prefix; - myAbstractTreeBuilder.refilter(null, false, false).doWhenProcessed(new Runnable() { - @Override - public void run() { - myTree.repaint(); - //if (mySpeedSearch.isPopupActive()) { - // mySpeedSearch.refreshSelection(); - //} - } - }); + if (!filter.equals(prefix)) { + filter = prefix; + myAbstractTreeBuilder.refilter(null, false, false).doWhenProcessed(new Runnable() { + @Override + public void run() { + myTree.repaint(); + //if (mySpeedSearch.isPopupActive()) { + // mySpeedSearch.refreshSelection(); + //} + } + }); + } + alarm.addRequest(this, 300); } - alarm.addRequest(this, 300); - } - }, 300); + }, 300); + } } - private void selectPsiElement(PsiElement element) { + public void selectPsiElement(PsiElement element) { Set parents = getAllParents(element); FilteringTreeStructure.FilteringNode node = (FilteringTreeStructure.FilteringNode)myAbstractTreeBuilder.getRootElement(); @@ -478,7 +489,7 @@ public class FileStructurePopup implements Disposable { } @Nullable - protected PsiElement getCurrentElement(@Nullable final PsiFile psiFile) { + public PsiElement getCurrentElement(@Nullable final PsiFile psiFile) { if (psiFile == null) return null; PsiDocumentManager.getInstance(myProject).commitAllDocuments(); @@ -718,6 +729,18 @@ public class FileStructurePopup implements Disposable { myTitle = title; } + public Tree getTree() { + return myTree; + } + + public TreeSpeedSearch getSpeedSearch() { + return mySpeedSearch; + } + + public FilteringTreeBuilder getTreeBuilder() { + return myAbstractTreeBuilder; + } + private class FileStructurePopupFilter implements ElementFilter { private String myLastFilter = null; private HashSet myVisibleParents = new HashSet(); diff --git a/platform/platform-api/src/com/intellij/ide/util/treeView/AbstractTreeUi.java b/platform/platform-api/src/com/intellij/ide/util/treeView/AbstractTreeUi.java index ced3ab62d05d..43423a359932 100644 --- a/platform/platform-api/src/com/intellij/ide/util/treeView/AbstractTreeUi.java +++ b/platform/platform-api/src/com/intellij/ide/util/treeView/AbstractTreeUi.java @@ -2362,7 +2362,7 @@ public class AbstractTreeUi { final ActionCallback done = new ActionCallback(); - invokeLaterIfNeeded(new Runnable() { + final Runnable cancelUpdate = new Runnable() { public void run() { if (isReleased()) { done.setRejected(); @@ -2371,21 +2371,29 @@ public class AbstractTreeUi { if (myResettingToReadyNow.get()) { _getReady().notify(done); - } else if (isReady()) { + } + else if (isReady()) { resetToReadyNow(); done.setDone(); - } else { + } + else { if (isIdle() && hasPendingWork()) { resetToReadyNow(); done.setDone(); - } else { + } + else { _getReady().notify(done); } } maybeReady(); } - }, false); + }; + if (ApplicationManager.getApplication().isUnitTestMode()) { + cancelUpdate.run(); + } else { + invokeLaterIfNeeded(cancelUpdate, false); + } if (isEdt() || isPassthroughMode()) { maybeReady(); diff --git a/platform/platform-api/src/com/intellij/ui/treeStructure/filtered/FilteringTreeBuilder.java b/platform/platform-api/src/com/intellij/ui/treeStructure/filtered/FilteringTreeBuilder.java index 941dafef44eb..71f152e5fc58 100644 --- a/platform/platform-api/src/com/intellij/ui/treeStructure/filtered/FilteringTreeBuilder.java +++ b/platform/platform-api/src/com/intellij/ui/treeStructure/filtered/FilteringTreeBuilder.java @@ -18,6 +18,7 @@ package com.intellij.ui.treeStructure.filtered; import com.intellij.ide.util.treeView.AbstractTreeBuilder; import com.intellij.ide.util.treeView.AbstractTreeStructure; import com.intellij.ide.util.treeView.NodeDescriptor; +import com.intellij.openapi.application.ApplicationManager; import com.intellij.openapi.util.ActionCallback; import com.intellij.openapi.util.Disposer; import com.intellij.ui.speedSearch.ElementFilter; @@ -120,7 +121,7 @@ public class FilteringTreeBuilder extends AbstractTreeBuilder { myRefilterQueue.cancelAllUpdates(); } final ActionCallback callback = new ActionCallback(); - getUi().cancelUpdate().doWhenProcessed(new Runnable() { + final Runnable afterCancelUpdate = new Runnable() { @Override public void run() { if (myRefilterQueue == null || now) { @@ -145,7 +146,12 @@ public class FilteringTreeBuilder extends AbstractTreeBuilder { }); } } - }); + }; + if (!ApplicationManager.getApplication().isUnitTestMode()) { + getUi().cancelUpdate().doWhenProcessed(afterCancelUpdate); + } else { + afterCancelUpdate.run(); + } return callback; } @@ -155,7 +161,7 @@ public class FilteringTreeBuilder extends AbstractTreeBuilder { final ActionCallback selectionDone = new ActionCallback(); getFilteredStructure().refilter(); - queueUpdate().doWhenProcessed(new Runnable() { + final Runnable selectionRunnable = new Runnable() { public void run() { revalidateTree(); @@ -173,25 +179,36 @@ public class FilteringTreeBuilder extends AbstractTreeBuilder { selectionDone.setDone(); } }); - } else { + } + else { TreeUtil.ensureSelection(myTree); selectionDone.setDone(); } - } else { + } + else { selectionDone.setDone(); } } - }); + }; + if (!ApplicationManager.getApplication().isUnitTestMode()) { + queueUpdate().doWhenProcessed(selectionRunnable); + } else { + selectionRunnable.run(); + } final ActionCallback result = new ActionCallback(); selectionDone.doWhenDone(new Runnable() { public void run() { - scrollSelectionToVisible(new Runnable() { - public void run() { - getReady(this).notify(result); - } - }, false); + if (!ApplicationManager.getApplication().isUnitTestMode()) { + scrollSelectionToVisible(new Runnable() { + public void run() { + getReady(this).notify(result); + } + }, false); + } else { + result.setDone(); + } } }).doWhenRejected(new Runnable() { @Override diff --git a/platform/testFramework/src/com/intellij/testFramework/FileStructureTestBase.java b/platform/testFramework/src/com/intellij/testFramework/FileStructureTestBase.java new file mode 100644 index 000000000000..3f991b0cb683 --- /dev/null +++ b/platform/testFramework/src/com/intellij/testFramework/FileStructureTestBase.java @@ -0,0 +1,119 @@ +/* + * Copyright 2000-2012 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.testFramework; + +import com.intellij.ide.actions.ViewStructureAction; +import com.intellij.ide.util.FileStructurePopup; +import com.intellij.openapi.fileEditor.impl.text.TextEditorProvider; +import com.intellij.openapi.util.Disposer; +import com.intellij.openapi.util.io.FileUtil; +import com.intellij.openapi.util.text.StringUtil; +import com.intellij.testFramework.fixtures.CodeInsightFixtureTestCase; +import com.intellij.ui.TreeSpeedSearch; +import com.intellij.ui.treeStructure.Tree; +import com.intellij.ui.treeStructure.filtered.FilteringTreeBuilder; +import com.intellij.ui.treeStructure.filtered.FilteringTreeStructure; +import com.intellij.util.ui.tree.TreeUtil; +import junit.framework.Assert; +import org.junit.Before; + +import java.io.File; + +/** + * @author Konstantin Bulenkov + */ +public abstract class FileStructureTestBase extends CodeInsightFixtureTestCase { + FileStructurePopup myPopup; + + @Before + public void setUp() throws Exception { + super.setUp(); + myFixture.configureByFile(getFileName(getFileExtension())); + myPopup = ViewStructureAction.createPopup(myFixture.getEditor(), + myFixture.getProject(), + null, + TextEditorProvider.getInstance().getTextEditor(myFixture.getEditor())); + update(); + } + + protected abstract String getFileExtension(); + + @Override + public void tearDown() throws Exception { + Disposer.dispose(myPopup); + super.tearDown(); + } + + private String getFileName(String ext) { + return getTestName(false) + (StringUtil.isEmpty(ext) ? "" : "." + ext); + } + + protected String getTreeFileName() { + return getFileName("tree"); + } + + protected void checkTree() throws Exception { + final String expected = FileUtil.loadFile(new File(getTestDataPath() + "/" + getTreeFileName())); + Assert.assertEquals(expected, PlatformTestUtil.print(getTree(), true)); + } + + + private void update() throws InterruptedException { + myPopup.getTreeBuilder().refilter().doWhenProcessed(new Runnable() { + @Override + public void run() { + getStructure().rebuild(); + updateTree(); + TreeUtil.expandAll(getTree()); + myPopup.selectPsiElement(getFile()); + } + }); + } + + protected Tree getTree() { + return myPopup.getTree(); + } + + protected FilteringTreeBuilder getBuilder() { + return myPopup.getTreeBuilder(); + } + + protected TreeSpeedSearch getSpeedSearch() { + return myPopup.getSpeedSearch(); + } + + + protected void updateTree() { + updateRecursively(getRootNode()); + } + + protected FilteringTreeStructure getStructure() { + final FilteringTreeStructure structure = (FilteringTreeStructure)getBuilder().getTreeStructure(); + assert structure != null; + return structure; + } + + protected FilteringTreeStructure.FilteringNode getRootNode() { + return (FilteringTreeStructure.FilteringNode)getStructure().getRootElement(); + } + + protected void updateRecursively(final FilteringTreeStructure.FilteringNode node) { + node.update(); + for (FilteringTreeStructure.FilteringNode child : node.children()) { + updateRecursively(child); + } + } +} From d33ec0506941b94f881b5ed257716d16e19883a6 Mon Sep 17 00:00:00 2001 From: "Maxim.Mossienko" Date: Mon, 30 Jan 2012 14:10:21 +0400 Subject: [PATCH 7/9] less synchronization --- .../intellij/openapi/vcs/persistent/SmallMapSerializer.java | 4 +++- 1 file changed, 3 insertions(+), 1 deletion(-) diff --git a/platform/vcs-api/src/com/intellij/openapi/vcs/persistent/SmallMapSerializer.java b/platform/vcs-api/src/com/intellij/openapi/vcs/persistent/SmallMapSerializer.java index 004dee277a1b..41d28da4acb8 100644 --- a/platform/vcs-api/src/com/intellij/openapi/vcs/persistent/SmallMapSerializer.java +++ b/platform/vcs-api/src/com/intellij/openapi/vcs/persistent/SmallMapSerializer.java @@ -20,7 +20,9 @@ import com.intellij.openapi.diagnostic.Logger; import com.intellij.openapi.util.io.BufferExposingByteArrayOutputStream; import com.intellij.openapi.util.io.FileUtil; import com.intellij.util.io.DataExternalizer; +import com.intellij.util.io.DataOutputStream; import com.intellij.util.io.KeyDescriptor; +import com.intellij.util.io.UnsyncByteArrayInputStream; import org.jetbrains.annotations.NotNull; import java.io.*; @@ -51,7 +53,7 @@ public class SmallMapSerializer implements Forceable { private void init() { try { final byte[] bytes = FileUtil.loadFileBytes(myFile); - final DataInputStream dis = new DataInputStream(new ByteArrayInputStream(bytes)); + final DataInputStream dis = new DataInputStream(new UnsyncByteArrayInputStream(bytes)); final int size = dis.readInt(); for (int i = 0; i < size; i++) { final KeyWrapper keyWrapper = new KeyWrapper(myKeyDescriptor, myKeyDescriptor.read(dis)); From 7c835859fceb3db882dea8ab30fec95b64d90fae Mon Sep 17 00:00:00 2001 From: "Maxim.Mossienko" Date: Mon, 30 Jan 2012 16:01:55 +0400 Subject: [PATCH 8/9] avoid exception on trying to detect injection inside another injection (WI-9523) --- .../psi/impl/source/tree/injected/InjectedLanguageUtil.java | 2 ++ 1 file changed, 2 insertions(+) diff --git a/platform/lang-impl/src/com/intellij/psi/impl/source/tree/injected/InjectedLanguageUtil.java b/platform/lang-impl/src/com/intellij/psi/impl/source/tree/injected/InjectedLanguageUtil.java index 050f1efad069..7baf631f9661 100644 --- a/platform/lang-impl/src/com/intellij/psi/impl/source/tree/injected/InjectedLanguageUtil.java +++ b/platform/lang-impl/src/com/intellij/psi/impl/source/tree/injected/InjectedLanguageUtil.java @@ -132,6 +132,8 @@ public class InjectedLanguageUtil { if (file == null || !file.isPhysical() && file.getOriginalFile() == file) return; } + if (containingFile.getViewProvider() instanceof InjectedFileViewProvider) return; // no injection inside injection + PsiElement inTree = loadTree(host, containingFile); if (inTree != host) { host = inTree; From eb135916126805f9d7473ad56eaf8fa8177e214e Mon Sep 17 00:00:00 2001 From: "Maxim.Mossienko" Date: Mon, 30 Jan 2012 16:03:08 +0400 Subject: [PATCH 9/9] smaller upper limit for mapped byte buffers on x64 when using btree based enumerator --- platform/util/src/com/intellij/util/io/PagedFileStorage.java | 2 +- .../src/com/intellij/util/io/PersistentEnumeratorDelegate.java | 3 +-- 2 files changed, 2 insertions(+), 3 deletions(-) diff --git a/platform/util/src/com/intellij/util/io/PagedFileStorage.java b/platform/util/src/com/intellij/util/io/PagedFileStorage.java index a8acc9b21219..4cf6dfbde294 100644 --- a/platform/util/src/com/intellij/util/io/PagedFileStorage.java +++ b/platform/util/src/com/intellij/util/io/PagedFileStorage.java @@ -49,7 +49,7 @@ public class PagedFileStorage implements Forceable { static { final int lower = 100; - final int upper = SystemInfo.is64Bit ? 500 : 200; + final int upper = SystemInfo.is64Bit && !PersistentEnumeratorDelegate.useBtree() ? 500 : 200; BUFFER_SIZE = Math.max(1, SystemInfo.getIntProperty("idea.paged.storage.page.size", 10)) * MB; if (ByteBufferWrapper.NO_MMAP) { diff --git a/platform/util/src/com/intellij/util/io/PersistentEnumeratorDelegate.java b/platform/util/src/com/intellij/util/io/PersistentEnumeratorDelegate.java index c7c689eedae5..7dc5f0a802da 100644 --- a/platform/util/src/com/intellij/util/io/PersistentEnumeratorDelegate.java +++ b/platform/util/src/com/intellij/util/io/PersistentEnumeratorDelegate.java @@ -16,7 +16,6 @@ package com.intellij.util.io; import com.intellij.openapi.Forceable; -import com.intellij.openapi.util.SystemInfo; import org.jetbrains.annotations.Nullable; import java.io.Closeable; @@ -32,7 +31,7 @@ public class PersistentEnumeratorDelegate implements Closeable, Forceable new PersistentEnumerator(file, dataDescriptor, initialSize); } - private boolean useBtree() { + static boolean useBtree() { String property = System.getProperty("idea.use.btree"); return !"false".equals(property); }