From 32c8a5ab2be3b55b82a663f6c3b49f6902e0e845 Mon Sep 17 00:00:00 2001 From: Dmitry Trofimov Date: Wed, 1 Jul 2015 14:39:43 +0200 Subject: [PATCH 01/39] Fix community plugin version. --- python/pluginResources/META-INF/plugin.xml | 3 +-- 1 file changed, 1 insertion(+), 2 deletions(-) diff --git a/python/pluginResources/META-INF/plugin.xml b/python/pluginResources/META-INF/plugin.xml index c08a7e2cccc3..d649272573c3 100644 --- a/python/pluginResources/META-INF/plugin.xml +++ b/python/pluginResources/META-INF/plugin.xml @@ -15,8 +15,7 @@ The Python plug-in provides smart editing for Python scripts. The feature set of Issue tracker
]]> - - @@PYCHARM_VERSION@@ @@BUILD_NUMBER@@ + @@PYCHARM_VERSION@@ com.intellij.modules.java From b5ccb211d234b94dfdea78875d6dc00625bce303 Mon Sep 17 00:00:00 2001 From: Anton Makeev Date: Thu, 2 Jul 2015 21:00:48 +0200 Subject: [PATCH 02/39] FileUtil.toCanonicalPath can now expand symlinks when it's required to build the valid path that contains /../ * test adjusted to Windows behavior --- .../openapi/util/io/FileUtilHeavyTest.java | 36 +++++++++++++------ 1 file changed, 25 insertions(+), 11 deletions(-) diff --git a/platform/util/testSrc/com/intellij/openapi/util/io/FileUtilHeavyTest.java b/platform/util/testSrc/com/intellij/openapi/util/io/FileUtilHeavyTest.java index 0e118cab81bb..58a20e148ab1 100644 --- a/platform/util/testSrc/com/intellij/openapi/util/io/FileUtilHeavyTest.java +++ b/platform/util/testSrc/com/intellij/openapi/util/io/FileUtilHeavyTest.java @@ -233,13 +233,15 @@ public class FileUtilHeavyTest { public void testToCanonicalPathSymLinksAware() throws Exception { assumeTrue(SystemInfo.areSymLinksSupported); - File root = IoTestUtil.createTestDir(myTempDirectory, "root"); - assertTrue(new File(root, "dir1/dir2/dir3/dir4").mkdirs()); + File rootDir = IoTestUtil.createTestDir(myTempDirectory, "root"); + assertTrue(new File(rootDir, "dir1/dir2/dir3/dir4").mkdirs()); + + String root = FileUtil.toSystemIndependentName(FileUtil.resolveShortWindowsName(rootDir.getPath())); // non-recursive link - IoTestUtil.createSymLink(new File(root, "dir1/dir2").getPath(), new File(root, "dir1/dir2_link").getPath()); + IoTestUtil.createSymLink(new File(rootDir, "dir1/dir2").getPath(), new File(rootDir, "dir1/dir2_link").getPath()); // recursive links to a parent dir - IoTestUtil.createSymLink(new File(root, "dir1").getPath(), new File(root, "dir1/dir1_link").getPath()); + IoTestUtil.createSymLink(new File(rootDir, "dir1").getPath(), new File(rootDir, "dir1/dir1_link").getPath()); // I) links should NOT be resolved when ../ stays inside the linked path // I.I) non-recursive links @@ -266,13 +268,25 @@ public class FileUtilHeavyTest { assertEquals(root + "/dir1/dir2", FileUtil.toCanonicalPath(root + "/dir1/dir2_link/dir3/../../../dir1/dir2", true)); assertEquals(root + "/dir1/dir2", FileUtil.toCanonicalPath(root + "/dir1/../dir1/dir2_link/../dir2", true)); - // II.I) recursive links - assertEquals(root.getPath(), FileUtil.toCanonicalPath(root + "/dir1/dir1_link/../", true)); - assertEquals(root + "/dir1", FileUtil.toCanonicalPath(root + "/dir1/dir1_link/../dir1", true)); - assertEquals(root + "/dir1", FileUtil.toCanonicalPath(root + "/dir1/dir1_link/../../root/dir1", true)); - assertEquals(root + "/dir1", FileUtil.toCanonicalPath(root + "/dir1/dir1_link/dir3/../../dir1", true)); - assertEquals(root + "/dir1", FileUtil.toCanonicalPath(root + "/dir1/dir1_link/dir3/../../../root/dir1", true)); - assertEquals(root + "/dir1", FileUtil.toCanonicalPath(root + "/dir1/../dir1/dir1_link/../dir1", true)); + // II.I) recursive links + // the rules seems to be different when ../ goes over recursive link: + // * on Windows ../ goes to link's parent + // * on Unix ../ goes to target's parent + if (SystemInfo.isWindows) { + assertEquals(root + "/dir1", FileUtil.toCanonicalPath(root + "/dir1/dir1_link/../", true)); + assertEquals(root + "/dir1/dir2", FileUtil.toCanonicalPath(root + "/dir1/dir1_link/../dir2", true)); + assertEquals(root + "/dir1/dir2", FileUtil.toCanonicalPath(root + "/dir1/dir1_link/../../dir1/dir2", true)); + assertEquals(root + "/dir1/dir2", FileUtil.toCanonicalPath(root + "/dir1/dir1_link/dir2/../../dir2", true)); + assertEquals(root + "/dir1/dir2", FileUtil.toCanonicalPath(root + "/dir1/dir1_link/dir2/../../../dir1/dir2", true)); + assertEquals(root + "/dir1/dir2", FileUtil.toCanonicalPath(root + "/dir1/../dir1/dir1_link/../dir2", true)); + } else { + assertEquals(root, FileUtil.toCanonicalPath(root + "/dir1/dir1_link/../", true)); + assertEquals(root + "/dir1", FileUtil.toCanonicalPath(root + "/dir1/dir1_link/../dir1", true)); + assertEquals(root + "/dir1", FileUtil.toCanonicalPath(root + "/dir1/dir1_link/../../root/dir1", true)); + assertEquals(root + "/dir1", FileUtil.toCanonicalPath(root + "/dir1/dir1_link/dir2/../../dir1", true)); + assertEquals(root + "/dir1", FileUtil.toCanonicalPath(root + "/dir1/dir1_link/dir2/../../../root/dir1", true)); + assertEquals(root + "/dir1", FileUtil.toCanonicalPath(root + "/dir1/../dir1/dir1_link/../dir1", true)); + } // some corner cases, behavior should be the same as the default FileUtil.toCanonicalPath assertEquals(FileUtil.toCanonicalPath("..", false), FileUtil.toCanonicalPath("..", true)); From 84087d7b89f381a6b910b00783271806d6785568 Mon Sep 17 00:00:00 2001 From: "Vassiliy.Kudryashov" Date: Thu, 2 Jul 2015 23:21:47 +0300 Subject: [PATCH 03/39] IDEA-14883 Run Configuration: Should have option to 'Run in background' --- .../RunnerAndConfigurationSettings.java | 14 +++++++++++ .../execution/runners/BaseProgramRunner.java | 9 ++++--- .../execution/impl/BeforeRunStepsPanel.java | 25 +++++++++++++++++-- .../ConfigurationSettingsEditorWrapper.java | 2 ++ .../execution/impl/RunConfigurable.java | 1 + .../RunnerAndConfigurationSettingsImpl.java | 18 +++++++++++++ .../src/messages/ExecutionBundle.properties | 1 + 7 files changed, 64 insertions(+), 6 deletions(-) diff --git a/platform/lang-api/src/com/intellij/execution/RunnerAndConfigurationSettings.java b/platform/lang-api/src/com/intellij/execution/RunnerAndConfigurationSettings.java index 8e1ec4e47a21..2740cd0254aa 100644 --- a/platform/lang-api/src/com/intellij/execution/RunnerAndConfigurationSettings.java +++ b/platform/lang-api/src/com/intellij/execution/RunnerAndConfigurationSettings.java @@ -161,6 +161,20 @@ public interface RunnerAndConfigurationSettings { */ boolean isEditBeforeRun(); + /** + * Sets the "Before launch: Activate tool window" flag (for activation tool window Run/Debug etc.) + * + * @param b if true, the tool window will be activated before launching this configuration. + */ + void setActivateToolWindowBeforeRun(boolean activate); + + /** + * Returns the "Before launch: Activate tool window" flag (for activation tool window Run/Debug etc.) + * + * @return if true (it's default value), the tool window will be activated before launching this configuration. + */ + boolean isActivateToolWindowBeforeRun(); + /** * Sets the "Single instance only" flag (meaning that only one instance of this run configuration can be run at the same time). * diff --git a/platform/lang-api/src/com/intellij/execution/runners/BaseProgramRunner.java b/platform/lang-api/src/com/intellij/execution/runners/BaseProgramRunner.java index a2028185089b..637729d795cc 100644 --- a/platform/lang-api/src/com/intellij/execution/runners/BaseProgramRunner.java +++ b/platform/lang-api/src/com/intellij/execution/runners/BaseProgramRunner.java @@ -16,10 +16,7 @@ package com.intellij.execution.runners; -import com.intellij.execution.ExecutionException; -import com.intellij.execution.ExecutionResult; -import com.intellij.execution.Executor; -import com.intellij.execution.RunManager; +import com.intellij.execution.*; import com.intellij.execution.configurations.*; import com.intellij.execution.ui.RunContentDescriptor; import com.intellij.openapi.options.SettingsEditor; @@ -72,6 +69,10 @@ abstract class BaseProgramRunner implements Pro static RunContentDescriptor postProcess(@NotNull ExecutionEnvironment environment, @Nullable RunContentDescriptor descriptor, @Nullable Callback callback) { if (descriptor != null) { descriptor.setExecutionId(environment.getExecutionId()); + RunnerAndConfigurationSettings settings = environment.getRunnerAndConfigurationSettings(); + if (settings != null) { + descriptor.setActivateToolWindowWhenAdded(settings.isActivateToolWindowBeforeRun()); + } } if (callback != null) { callback.processStarted(descriptor); diff --git a/platform/lang-impl/src/com/intellij/execution/impl/BeforeRunStepsPanel.java b/platform/lang-impl/src/com/intellij/execution/impl/BeforeRunStepsPanel.java index 191c0f79b25c..60d3819df9e2 100644 --- a/platform/lang-impl/src/com/intellij/execution/impl/BeforeRunStepsPanel.java +++ b/platform/lang-impl/src/com/intellij/execution/impl/BeforeRunStepsPanel.java @@ -35,6 +35,7 @@ import com.intellij.openapi.util.SystemInfo; import com.intellij.ui.*; import com.intellij.ui.components.JBList; import com.intellij.util.containers.hash.HashSet; +import com.intellij.util.ui.JBUI; import org.jetbrains.annotations.Nullable; import javax.swing.*; @@ -52,6 +53,7 @@ import java.util.List; class BeforeRunStepsPanel extends JPanel { private final JCheckBox myShowSettingsBeforeRunCheckBox; + private final JCheckBox myActivateToolWindowBeforeRunCheckBox; private final JBList myList; private final CollectionListModel myModel; private RunConfiguration myRunConfiguration; @@ -138,12 +140,22 @@ class BeforeRunStepsPanel extends JPanel { updateText(); } }); + myActivateToolWindowBeforeRunCheckBox = new JCheckBox(ExecutionBundle.message("configuration.activate.toolwindow.before.run")); + myActivateToolWindowBeforeRunCheckBox.addActionListener(new ActionListener() { + @Override + public void actionPerformed(ActionEvent e) { + updateText(); + } + }); myPanel = myDecorator.createPanel(); setLayout(new BorderLayout()); add(myPanel, BorderLayout.CENTER); - add(myShowSettingsBeforeRunCheckBox, BorderLayout.SOUTH); + JPanel checkboxPanel = new JPanel(new FlowLayout(FlowLayout.LEADING, JBUI.scale(5), JBUI.scale(5))); + checkboxPanel.add(myShowSettingsBeforeRunCheckBox); + checkboxPanel.add(myActivateToolWindowBeforeRunCheckBox); + add(checkboxPanel, BorderLayout.SOUTH); } @Nullable @@ -165,7 +177,9 @@ class BeforeRunStepsPanel extends JPanel { originalTasks.addAll(runManager.getBeforeRunTasks(myRunConfiguration)); myModel.replaceAll(originalTasks); myShowSettingsBeforeRunCheckBox.setSelected(settings.isEditBeforeRun()); - myShowSettingsBeforeRunCheckBox.setEnabled(!(isUnknown())); + myShowSettingsBeforeRunCheckBox.setEnabled(!isUnknown()); + myActivateToolWindowBeforeRunCheckBox.setSelected(settings.isActivateToolWindowBeforeRun()); + myActivateToolWindowBeforeRunCheckBox.setEnabled(!isUnknown()); myPanel.setVisible(checkBeforeRunTasksAbility(false)); updateText(); } @@ -209,6 +223,9 @@ class BeforeRunStepsPanel extends JPanel { } } } + if (myActivateToolWindowBeforeRunCheckBox.isSelected()) { + sb.append(sb.length() > 0 ? ", " : "").append(ExecutionBundle.message("configuration.activate.toolwindow.before.run")); + } if (sb.length() > 0) { sb.insert(0, ": "); } @@ -228,6 +245,10 @@ class BeforeRunStepsPanel extends JPanel { return myShowSettingsBeforeRunCheckBox.isSelected(); } + public boolean needActivateToolWindowBeforeRun() { + return myActivateToolWindowBeforeRunCheckBox.isSelected(); + } + private boolean checkBeforeRunTasksAbility(boolean checkOnlyAddAction) { if (isUnknown()) { return false; diff --git a/platform/lang-impl/src/com/intellij/execution/impl/ConfigurationSettingsEditorWrapper.java b/platform/lang-impl/src/com/intellij/execution/impl/ConfigurationSettingsEditorWrapper.java index 9d097a5dabfb..568e8d20ea16 100644 --- a/platform/lang-impl/src/com/intellij/execution/impl/ConfigurationSettingsEditorWrapper.java +++ b/platform/lang-impl/src/com/intellij/execution/impl/ConfigurationSettingsEditorWrapper.java @@ -130,8 +130,10 @@ public class ConfigurationSettingsEditorWrapper extends SettingsEditor Date: Thu, 2 Jul 2015 23:42:25 +0300 Subject: [PATCH 04/39] IDEA-14883 Run Configuration: Should have option to 'Run in background' --- .../execution/impl/RunnerAndConfigurationSettingsImpl.java | 1 + 1 file changed, 1 insertion(+) diff --git a/platform/lang-impl/src/com/intellij/execution/impl/RunnerAndConfigurationSettingsImpl.java b/platform/lang-impl/src/com/intellij/execution/impl/RunnerAndConfigurationSettingsImpl.java index 0e96eb362454..03e7a51c96e1 100644 --- a/platform/lang-impl/src/com/intellij/execution/impl/RunnerAndConfigurationSettingsImpl.java +++ b/platform/lang-impl/src/com/intellij/execution/impl/RunnerAndConfigurationSettingsImpl.java @@ -487,6 +487,7 @@ public class RunnerAndConfigurationSettingsImpl implements JDOMExternalizable, C setSingleton(template.isSingleton()); setEditBeforeRun(template.isEditBeforeRun()); + setActivateToolWindowBeforeRun(template.isActivateToolWindowBeforeRun()); } @SuppressWarnings("deprecation") From 30b0a964c90aa7841b3a183d62d083e1d6883cd6 Mon Sep 17 00:00:00 2001 From: Sergey Ignatov Date: Thu, 2 Jul 2015 19:46:28 +0300 Subject: [PATCH 05/39] cleanup --- .../tools/fragmented/UnifiedDiffViewer.java | 4 ++-- .../src/com/intellij/diff/util/DiffUtil.java | 18 +----------------- 2 files changed, 3 insertions(+), 19 deletions(-) diff --git a/platform/diff-impl/src/com/intellij/diff/tools/fragmented/UnifiedDiffViewer.java b/platform/diff-impl/src/com/intellij/diff/tools/fragmented/UnifiedDiffViewer.java index f0cf5497bf83..21ba91b76207 100644 --- a/platform/diff-impl/src/com/intellij/diff/tools/fragmented/UnifiedDiffViewer.java +++ b/platform/diff-impl/src/com/intellij/diff/tools/fragmented/UnifiedDiffViewer.java @@ -346,8 +346,8 @@ public class UnifiedDiffViewer extends ListenerDiffViewerBase { EditorHighlighter highlighter2 = DiffUtil.initEditorHighlighter(project, content2, text2); if (highlighter1 == null && highlighter2 == null) return null; - if (highlighter1 == null) highlighter1 = DiffUtil.initEmptyEditorHighlighter(project, text1); - if (highlighter2 == null) highlighter2 = DiffUtil.initEmptyEditorHighlighter(project, text2); + if (highlighter1 == null) highlighter1 = DiffUtil.initEmptyEditorHighlighter(text1); + if (highlighter2 == null) highlighter2 = DiffUtil.initEmptyEditorHighlighter(text2); return new UnifiedEditorHighlighter(myDocument, highlighter1, highlighter2, ranges, textLength); } diff --git a/platform/diff-impl/src/com/intellij/diff/util/DiffUtil.java b/platform/diff-impl/src/com/intellij/diff/util/DiffUtil.java index d5fedbcf2c95..1d14498c31bd 100644 --- a/platform/diff-impl/src/com/intellij/diff/util/DiffUtil.java +++ b/platform/diff-impl/src/com/intellij/diff/util/DiffUtil.java @@ -107,7 +107,7 @@ public class DiffUtil { } @NotNull - public static EditorHighlighter initEmptyEditorHighlighter(@Nullable Project project, @NotNull CharSequence text) { + public static EditorHighlighter initEmptyEditorHighlighter(@NotNull CharSequence text) { EditorHighlighter highlighter = createEmptyEditorHighlighter(); highlighter.setText(text); return highlighter; @@ -216,10 +216,6 @@ public class DiffUtil { scrollToCaret(editor, animated); } - public static void scrollToPoint(@Nullable Editor editor, @NotNull Point point) { - scrollToPoint(editor, point, false); - } - public static void scrollToPoint(@Nullable Editor editor, @NotNull Point point, boolean animated) { if (editor == null) return; if (!animated) editor.getScrollingModel().disableAnimation(); @@ -876,14 +872,6 @@ public class DiffUtil { return holder; } - public static UserDataHolderBase createUserDataHolder(@NotNull Key key1, @Nullable T value1, - @NotNull Key key2, @Nullable T value2) { - UserDataHolderBase holder = new UserDataHolderBase(); - holder.putUserData(key1, value1); - holder.putUserData(key2, value2); - return holder; - } - public static boolean isUserDataFlagSet(@NotNull Key key, UserDataHolder... holders) { for (UserDataHolder holder : holders) { if (holder == null) continue; @@ -1039,9 +1027,5 @@ public class DiffUtil { this(ignorePolicy.getComparisonPolicy(), highlightPolicy.isFineFragments(), highlightPolicy.isShouldSquash(), ignorePolicy.isShouldTrimChunks()); } - - public DiffConfig() { - this(IgnorePolicy.DEFAULT, HighlightPolicy.BY_LINE); - } } } From c255d2a6e21c963c83b5c5917435e85447c4d80d Mon Sep 17 00:00:00 2001 From: Sergey Ignatov Date: Fri, 3 Jul 2015 10:06:18 +0300 Subject: [PATCH 06/39] left diff editor: don't translate the check icon --- .../editor/impl/EditorMarkupModelImpl.java | 17 +++-------------- 1 file changed, 3 insertions(+), 14 deletions(-) diff --git a/platform/platform-impl/src/com/intellij/openapi/editor/impl/EditorMarkupModelImpl.java b/platform/platform-impl/src/com/intellij/openapi/editor/impl/EditorMarkupModelImpl.java index 7be120563745..a9224b91e6c2 100644 --- a/platform/platform-impl/src/com/intellij/openapi/editor/impl/EditorMarkupModelImpl.java +++ b/platform/platform-impl/src/com/intellij/openapi/editor/impl/EditorMarkupModelImpl.java @@ -501,20 +501,9 @@ public class EditorMarkupModelImpl extends MarkupModelImpl implements EditorMark } if (myErrorStripeRenderer != null) { - if (isMirrored() && g instanceof Graphics2D) { - Graphics2D g2d = (Graphics2D)g; - AffineTransform old = g2d.getTransform(); - AffineTransform tx = AffineTransform.getScaleInstance(-1, 1); - tx.translate(-getErrorIconWidth(), 0); - g2d.transform(tx); - myErrorStripeRenderer.paint(this, g2d, new Rectangle(0, 0, getErrorIconWidth(), getErrorIconHeight())); - g2d.setTransform(old); - } - else { - int x = getThinGap() + myMinMarkHeight; - final Rectangle b = new Rectangle(x, 0, getErrorIconWidth(), getErrorIconHeight()); - myErrorStripeRenderer.paint(this, g, b); - } + int x = isMirrored() ? 0 : (getThinGap() + myMinMarkHeight); + final Rectangle b = new Rectangle(x, 0, getErrorIconWidth(), getErrorIconHeight()); + myErrorStripeRenderer.paint(this, g, b); } } finally { From 6d823993c28e3fbe1a0aacab4f4aaf8ee5f063f2 Mon Sep 17 00:00:00 2001 From: peter Date: Thu, 2 Jul 2015 08:51:43 +0200 Subject: [PATCH 07/39] remove unused CharArray --- .../openapi/editor/impl/CharArray.java | 705 ------------------ .../openapi/editor/impl/CharArrayTest.java | 243 ------ 2 files changed, 948 deletions(-) delete mode 100644 platform/core-impl/src/com/intellij/openapi/editor/impl/CharArray.java delete mode 100644 platform/platform-tests/testSrc/com/intellij/openapi/editor/impl/CharArrayTest.java diff --git a/platform/core-impl/src/com/intellij/openapi/editor/impl/CharArray.java b/platform/core-impl/src/com/intellij/openapi/editor/impl/CharArray.java deleted file mode 100644 index 2fcd086a2924..000000000000 --- a/platform/core-impl/src/com/intellij/openapi/editor/impl/CharArray.java +++ /dev/null @@ -1,705 +0,0 @@ -/* - * 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.openapi.editor.impl; - -import com.intellij.diagnostic.Dumpable; -import com.intellij.openapi.application.ApplicationManager; -import com.intellij.openapi.application.impl.ApplicationInfoImpl; -import com.intellij.openapi.diagnostic.Logger; -import com.intellij.openapi.editor.event.DocumentEvent; -import com.intellij.openapi.util.text.StringUtil; -import com.intellij.util.LocalTimeCounter; -import com.intellij.util.text.CharArrayCharSequence; -import com.intellij.util.text.CharArrayUtil; -import com.intellij.util.text.CharSequenceBackedByArray; -import org.jetbrains.annotations.NonNls; -import org.jetbrains.annotations.NotNull; -import org.jetbrains.annotations.Nullable; - -import java.lang.ref.Reference; -import java.lang.ref.SoftReference; -import java.util.ArrayList; -import java.util.Arrays; -import java.util.List; - -/** - * @author cdr - */ -abstract class CharArray implements CharSequenceBackedByArray, Dumpable { - private static final boolean CHECK_DOCUMENT_CONSISTENCY = ApplicationManager.getApplication() != null && ApplicationManager.getApplication().isUnitTestMode(); - private static final Logger LOG = Logger.getInstance("#" + CharArray.class.getName()); - - @SuppressWarnings("UseOfArchaicSystemPropertyAccessors") - private static final boolean DISABLE_DEFERRED_PROCESSING = Boolean.getBoolean("idea.document.deny.deferred.changes"); - - @SuppressWarnings("UseOfArchaicSystemPropertyAccessors") - private static final boolean DEBUG_DEFERRED_PROCESSING = LOG.isDebugEnabled() || Boolean.getBoolean("idea.document.debug.bulk.processing"); - /** - * We can't exclude possibility of situation when 'defer changes' state is {@link #setDeferredChangeMode(boolean) entered} - * but not exited, hence, we want to perform automatic flushing if necessary in order to avoid memory leaks. This constant holds - * a value that defines that 'automatic flushing' criteria, i.e. every time number of stored deferred changes exceeds this value, - * they are automatically flushed. - */ - private static final int MAX_DEFERRED_CHANGES_NUMBER = 10000; - - private final TextChangesStorage myDeferredChangesStorage; - - private volatile int myStart; // start offset in myArray (used as an optimization when call substring()) - private volatile int myCount; - - private volatile CharSequence myOriginalSequence; - private volatile char[] myArray; - private volatile Reference myStringRef; // buffers String value - for not to generate it every time - private volatile int myBufferSize; - private volatile int myDeferredShift; - private volatile boolean myDeferredChangeMode; - private volatile boolean myHasDeferredChanges; - // this lock is for mutual exclusion during read action access - // (some fields are changed in read action too) - private final Object lock = new String("myOriginalSequence"); - - // We had a problems with bulk document text processing, hence, debug facilities were introduced. The fields group below work with them. - // The main idea is to hold all history of bulk processing iteration in order to be able to retrieve it from client and reproduce the - // problem. - - private final boolean myDebug = isDebug(); - - boolean isDebug() { - return DEBUG_DEFERRED_PROCESSING || CHECK_DOCUMENT_CONSISTENCY && !ApplicationInfoImpl.isInPerformanceTest(); - } - - /** - * Duplicate instance of the current char array that is used during debug processing as follows - apply every text change - * from the bulk changes group to this instance immediately in order to be able to check if the current 'deferred change-aware' - * instance functionally behaves at the same way as 'straightforward' one. - */ - private CharArray myDebugArray; - - /** - * Holds deferred changes create during the current bulk processing iteration. - */ - private List myDebugDeferredChanges; - - /** - * Document text on bulk processing start. - */ - private String myDebugTextOnBatchUpdateStart; - - // bufferSize == 0 means unbounded - CharArray(final int bufferSize, @NotNull char[] data, int length) { - myBufferSize = bufferSize; - myDeferredChangesStorage = new TextChangesStorage(); - myArray = Arrays.copyOf(data, length); - myCount = length; - - if (myDebug) { - myDebugArray = new CharArray(bufferSize, data, length) { - @NotNull - @Override - protected DocumentEvent beforeChangedUpdate(int offset, - CharSequence oldString, - CharSequence newString, - boolean wholeTextReplaced) { - return CharArray.this.beforeChangedUpdate(offset, oldString, newString, wholeTextReplaced); - } - - @Override - protected void afterChangedUpdate(@NotNull DocumentEvent event, long newModificationStamp) { - } - - @Override - protected void assertWriteAccess() { - } - - @Override - protected void assertReadAccess() { - } - - @Override - boolean isDebug() { - return false; - } - }; - myDebugDeferredChanges = new ArrayList(); - } - assertConsistency(); - } - - public void setBufferSize(int bufferSize) { - assert bufferSize >= 0 : bufferSize; - myBufferSize = bufferSize; - assertConsistency(); - } - - private DocumentEvent startChange(int offset, - @Nullable CharSequence oldString, - @Nullable CharSequence newString, - boolean wholeTextReplaced) { - assert myStart == 0; // can't change substring - assertWriteAccess(); - assertConsistency(); - - return beforeChangedUpdate(offset, oldString, newString, wholeTextReplaced); - } - - @NotNull - protected abstract DocumentEvent beforeChangedUpdate(int offset, - @Nullable CharSequence oldString, - @Nullable CharSequence newString, - boolean wholeTextReplaced); - protected abstract void afterChangedUpdate(@NotNull DocumentEvent event, long newModificationStamp); - - protected abstract void assertWriteAccess(); - protected abstract void assertReadAccess(); - - private void setText(@NotNull CharSequence chars) { - assertConsistency(); - myOriginalSequence = chars.toString(); - myArray = null; - myStringRef = null; - myCount = chars.length(); - assert myStart == 0; // can't change substring - myDeferredChangesStorage.clear(); - myHasDeferredChanges = false; - trimToSize(); - - if (myDebug) { - myDebugArray.setText(chars); - myDebugDeferredChanges.clear(); - } - assertConsistency(); - } - - private void assertConsistency() { - if (isDeferredChangeMode()) { - assert myOriginalSequence == null; - } - CharSequence originalSequence = myOriginalSequence; - int origLen = originalSequence == null ? -1 : originalSequence.length(); - String string = com.intellij.reference.SoftReference.dereference(myStringRef); - int stringLen = string == null ? -1 : string.length(); - assert origLen == stringLen || origLen==-1 || stringLen==-1; - - int count = myCount + myDeferredShift; - assert count == origLen || origLen==-1; - assert count == stringLen || stringLen==-1; - - if (!myDebug) return; - final CharSequence seqFromCharArray; - - if (myArray != null) { - assert myCount <= myArray.length; - seqFromCharArray = new CharArrayCharSequence(myArray, myStart, myCount); - } - else { - seqFromCharArray = null; - } - - if (seqFromCharArray != null && originalSequence != null) { - assert StringUtil.equals(seqFromCharArray, originalSequence); - } - if (!isDeferredChangeMode() && seqFromCharArray != null && string != null) { - assert StringUtil.equals(seqFromCharArray, string); - } - if (originalSequence != null && string != null) { - assert string.equals(originalSequence.toString()); - } - - myDebugArray.assertConsistency(); - - CharSequence str = com.intellij.reference.SoftReference.dereference(myStringRef); - if (str == null) { - if (myHasDeferredChanges) { - str = doSubString(0, myCount + myDeferredShift).toString(); - } - else if (myOriginalSequence != null) { - str = myOriginalSequence.toString(); - } - else { - str = seqFromCharArray; - } - } - assert count == str.length(); - if (isDeferredChangeMode()) { - String expected = myDebugArray.toString(); - checkStrings("toString()", expected, str); - } - } - - public void replace(int startOffset, - int endOffset, - @NotNull CharSequence toDelete, - @NotNull CharSequence newString, - long newModificationStamp, - boolean wholeTextReplaced) { - final DocumentEvent event = startChange(startOffset, toDelete, newString, wholeTextReplaced); - - startOffset += myStart; - endOffset += myStart; - doReplace(startOffset, endOffset, newString); - afterChangedUpdate(event, newModificationStamp); - assertConsistency(); - } - - private void doReplace(int startOffset, int endOffset, @NotNull CharSequence newString) { - prepareForModification(); - - if (isDeferredChangeMode()) { - storeChange(new TextChangeImpl(newString, startOffset, endOffset)); - if (myDebug) { - myDebugArray.doReplace(startOffset, endOffset, newString); - } - } - else { - int newLength = newString.length(); - int oldLength = endOffset - startOffset; - - CharArrayUtil.getChars(newString, myArray, startOffset, Math.min(newLength, oldLength)); - myStringRef = null; - - if (newLength > oldLength) { - doInsert(newString.subSequence(oldLength, newLength), endOffset); - } - else if (newLength < oldLength) { - doRemove(startOffset + newLength, startOffset + oldLength); - } - } - } - - public void remove(int startIndex, int endIndex, @NotNull CharSequence toDelete) { - DocumentEvent event = startChange(startIndex, toDelete, null, false); - startIndex += myStart; - endIndex += myStart; - doRemove(startIndex, endIndex); - afterChangedUpdate(event, LocalTimeCounter.currentTime()); - assertConsistency(); - } - - private void doRemove(int startIndex, int endIndex) { - if (startIndex == endIndex) { - return; - } - prepareForModification(); - - if (isDeferredChangeMode()) { - storeChange(new TextChangeImpl("", startIndex, endIndex)); - if (myDebug) { - myDebugArray.doRemove(startIndex, endIndex); - } - } - else { - if (endIndex < myCount) { - System.arraycopy(myArray, endIndex, myArray, startIndex, myCount - endIndex); - myStringRef = null; - } - myCount -= endIndex - startIndex; - } - } - - public void insert(@NotNull CharSequence s, int startIndex) { - DocumentEvent event = startChange(startIndex, null, s, false); - startIndex += myStart; - doInsert(s, startIndex); - - afterChangedUpdate(event, LocalTimeCounter.currentTime()); - trimToSize(); - assertConsistency(); - } - - private void doInsert(@NotNull CharSequence s, final int startIndex) { - prepareForModification(); - - if (isDeferredChangeMode()) { - storeChange(new TextChangeImpl(s, startIndex)); - if (myDebug) { - myDebugArray.doInsert(s, startIndex); - } - } - else { - int insertLength = s.length(); - myArray = resizeArray(myArray, myCount + insertLength); - if (startIndex < myCount) { - System.arraycopy(myArray, startIndex, myArray, startIndex + insertLength, myCount - startIndex); - } - - CharArrayUtil.getChars(s, myArray, startIndex); - myCount += insertLength; - myStringRef = null; - } - } - - /** - * Stores given change at collection of deferred changes (merging it with others if necessary) and updates current object - * state ({@link #length() length} etc). - * - * @param change new change to store - */ - private void storeChange(@NotNull TextChangeImpl change) { - if (!change.isWithinBounds(length())) { - LOG.error( - "Invalid change attempt detected - given change bounds are not within the current char array. Change: " + - change.getText().length()+":" + change.getStart()+"-" + change.getEnd(), dumpState()); - return; - } - if (myDeferredChangesStorage.size() >= MAX_DEFERRED_CHANGES_NUMBER) { - flushDeferredChanged(); - } - myDeferredChangesStorage.store(change); - myHasDeferredChanges = true; - myDeferredShift += change.getDiff(); - - if (myDebug) { - myDebugDeferredChanges.add(change); - } - } - - private void prepareForModification() { - if (myOriginalSequence != null) { - myArray = new char[myOriginalSequence.length()]; - CharArrayUtil.getChars(myOriginalSequence, myArray, 0); - myCount = myArray.length; - myOriginalSequence = null; - myStart = 0; - } - myStringRef = null; - - assertConsistency(); - } - - @NotNull - public CharSequence getCharArray() { - assertConsistency(); - CharSequence originalSequence = myOriginalSequence; - return originalSequence == null ? this : originalSequence; - } - - @Override - @NotNull - public String toString() { - assertConsistency(); - String str = com.intellij.reference.SoftReference.dereference(myStringRef); - if (str == null) { - if (myHasDeferredChanges) { - str = substring(0, length()).toString(); - } - else { - str = myOriginalSequence == null ? new String(myArray, myStart, myCount) : myOriginalSequence.toString(); - } - myStringRef = new SoftReference(str); - } - return str; - } - - @Override - public final int length() { - final int result = myCount + myDeferredShift; - if (myDebug && isDeferredChangeMode()) { - int expected = myDebugArray.length(); - if (expected != result) { - dumpDebugInfo("Incorrect length() processing. Expected: '" + expected + "', actual: '" + result + "'"); - } - } - return result; - } - - @Override - public final char charAt(int i) { - if (i < 0 || i >= length()) { - throw new IndexOutOfBoundsException("Wrong offset: " + i + "; count:" + length()); - } - i += myStart; - final char result; - if (!myHasDeferredChanges) { - if (myOriginalSequence != null) { - result = myOriginalSequence.charAt(i); - } - else { - result = myArray[i]; - } - } - else { - result = myDeferredChangesStorage.charAt(myArray, i); - } - - if (myDebug && isDeferredChangeMode()) { - char expected = myDebugArray.charAt(i); - if (expected != result) { - dumpDebugInfo("Incorrect charAt() processing for index " + i + ". Expected: '" + expected + "', actual: '" + result + "'"); - } - } - return result; - } - - @Override - @NotNull - public CharSequence subSequence(final int start, final int end) { - assertReadAccess(); - assertConsistency(); - if (start == 0 && end == length()) return this; - if (myOriginalSequence != null) { - return myOriginalSequence.subSequence(start, end); - } - flushDeferredChanged(); - return new CharArrayCharSequence(myArray, start, end); - } - - @Override - @NotNull - public char[] getChars() { - assertReadAccess(); - assertConsistency(); - char[] array = myArray; - CharSequence originalSequence = myOriginalSequence; - if (myHasDeferredChanges || originalSequence != null && array == null) { - // slow track - synchronized (lock) { - flushDeferredChanged(); - array = myArray; - originalSequence = myOriginalSequence; - if (originalSequence != null && array == null) { - myArray = array = CharArrayUtil.fromSequence(originalSequence); - myStringRef = null; - } - } - assertConsistency(); - } - return array; - } - - @Override - public void getChars(@NotNull final char[] dst, final int dstOffset) { - assertReadAccess(); - assertConsistency(); - flushDeferredChanged(); - if (myOriginalSequence == null) { - System.arraycopy(myArray, myStart, dst, dstOffset, length()); - } - else { - CharArrayUtil.getChars(myOriginalSequence, dst, dstOffset); - } - - if (myDebug && isDeferredChangeMode()) { - char[] expected = new char[dst.length]; - myDebugArray.getChars(expected, dstOffset); - for (int i = dstOffset, j = myStart; i < dst.length && j < myArray.length; i++, j++) { - if (expected[i] != myArray[j]) { - dumpDebugInfo("getChars(char[], int). Given array of length " + dst.length + ", offset " + dstOffset + ". Found char '" + myArray[j] + - "' at index " + i + ", expected to find '" + expected[i] + "'"); - break; - } - } - } - } - - @NotNull - public CharSequence substring(final int start, final int end) { - assertReadAccess(); - final CharSequence result = doSubString(start, end); - - assertConsistency(); - return result; - } - - private CharSequence doSubString(int start, int end) { - if (start == end) return ""; - final CharSequence result; - if (myOriginalSequence == null) { - result = myDeferredChangesStorage.substring(myArray, start + myStart, end + myStart); - } - else { - result = myOriginalSequence.subSequence(start, end); - } - return result; - } - - @NotNull - private static char[] resizeArray(@NotNull char[] array, int newSize) { - if (newSize < array.length) { - return array; - } - - int newArraySize = array.length; - if (newArraySize == 0) { - newArraySize = 16; - } - while (newArraySize <= newSize) { - newArraySize = newArraySize * 12 / 10 + 1; - } - char[] newArray = new char[newArraySize]; - System.arraycopy(array, 0, newArray, 0, array.length); - return newArray; - } - - private void trimToSize() { - if (myBufferSize != 0 && length() > myBufferSize) { - flushDeferredChanged(); - - // make a copy - int endIndex = myCount - myBufferSize; - String toDelete = getCharArray().subSequence(0, endIndex).toString(); - remove(0, endIndex, toDelete); - } - } - - /** - * @return true if this object is in the defer changes mode, see {@link #setDeferredChangeMode(boolean)}; - */ - public boolean isDeferredChangeMode() { - return myDeferredChangeMode; - } - - public boolean hasDeferredChanges() { - return myHasDeferredChanges; - } - - /** - * There is a possible case that client of this class wants to perform great number of modifications in a short amount of time - * (e.g. end-user performs formatting of the document backed by the object of the current class). It may result in significant - * performance degradation is the changes are performed one by one (every time the change is applied tail content is shifted to - * the left or right). So, we may want to optimize that by avoiding actual array modification until information about - * all target changes is provided and perform array data moves only after that. - *

- * This method allows to define that 'defer changes' mode usages, i.e. expected usage pattern is as follows: - *

-   * 
    - *
  1. - * Client of this class enters 'defer changes' mode (calls this method with 'true' argument). - * That means that all subsequent changes will not actually modify backed array data and will be stored separately; - *
  2. - *
  3. - * Number of target changes are applied to the current object via standard API - * ({@link #insert(CharSequence, int) insert}, - * {@link #remove(int, int, CharSequence) remove} and - * {@link #replace(int, int, java.lang.CharSequence, java.lang.CharSequence, long, boolean)}); - *
  4. - *
  5. - * Client of this class indicates that 'massive change time' is over by calling this method with 'false' - * argument. That flushes all deferred changes (if any) to the backed data array and makes every subsequent change to - * be immediate flushed to the backed array; - *
  6. - *
- *
- *

- * Note: we can't exclude possibility that 'defer changes' mode is started but inadvertently not ended - * (due to programming error, unexpected exception etc). Hence, this class is free to automatically end - * 'defer changes' mode when necessary in order to avoid memory leak with infinite deferred changes storing. - * - * @param deferredChangeMode flag that defines if 'defer changes' mode should be used by the current object - */ - public void setDeferredChangeMode(boolean deferredChangeMode) { - if (!DISABLE_DEFERRED_PROCESSING) { - if (deferredChangeMode) { - if (myDebug) { - myDebugArray.setText(myDebugTextOnBatchUpdateStart = toString()); - myDebugDeferredChanges.clear(); - } - prepareForModification(); - } - else { - flushDeferredChanged(); - } - myDeferredChangeMode = deferredChangeMode; - } - assertConsistency(); - } - - private void flushDeferredChanged() { - List changes = myDeferredChangesStorage.getChanges(); - if (changes.isEmpty()) { - return; - } - - synchronized (lock) { - char[] beforeMerge = null; - if (myDebug) { - beforeMerge = new char[myArray.length]; - System.arraycopy(myArray, 0, beforeMerge, 0, myArray.length); - } - - BulkChangesMerger changesMerger = BulkChangesMerger.INSTANCE; - final boolean inPlace; - if (myArray.length < length()) { - myArray = changesMerger.mergeToCharArray(myArray, myCount, changes); - inPlace = false; - } - else { - changesMerger.mergeInPlace(myArray, myCount, changes); - inPlace = true; - } - - myCount += myDeferredShift; - myDeferredShift = 0; - myDeferredChangesStorage.clear(); - myHasDeferredChanges = false; - myDeferredChangeMode = false; - myStringRef = null; - - if (myDebug) { - for (int i = 0, max = length(); i < max; i++) { - if (myArray[i] != myDebugArray.myArray[i]) { - dumpDebugInfo("flushDeferredChanged(). Index " + i + ", expected: '" + myDebugArray.myArray[i]+"', actual '" + - myArray[i]+"'. Text before merge: '" + Arrays.toString(beforeMerge)+"', merge inplace: "+inPlace); - break; - } - } - } - } - assertConsistency(); - } - - @Override - @NonNls - @NotNull - public String dumpState() { - return "deferred changes mode: " + isDeferredChangeMode()+", length: " + length()+" (data array length: " + myCount+ - ", deferred shift: " + myDeferredShift+"); view offsets: [" + myStart+"; "+myCount+"]; deferred changes: "+myDeferredChangesStorage; - } - - private void checkStrings(@NonNls @NotNull String operation, @NotNull String expected, @NotNull CharSequence actual) { - if (StringUtil.equals(expected, actual)) { - return; - } - for (int i = 0, max = Math.min(expected.length(), actual.length()); i < max; i++) { - if (actual.charAt(i) != expected.charAt(i)) { - dumpDebugInfo( - "Incorrect " + - operation+" processing. Expected length: " + - expected.length()+", actual length: " + - actual.length()+". Unmatched symbol at " + - i+" - expected: '" + - expected.charAt(i)+"', " + - "actual: '" + - actual.charAt(i)+"', expected document: '" + - expected+"', actual document: '" + - actual+"'" - ); - return; - } - } - dumpDebugInfo("Incorrect " + operation+" processing. Expected length: " + expected.length()+", actual length: " + - actual.length()+", expected: '" + expected+"', actual: '" + actual+"'"); - } - - private void dumpDebugInfo(@NonNls @NotNull String problem) { - LOG.error( - "Incorrect CharArray processing detected: " + problem + - ". Start: " + myStart - + ", count: " + myCount + ", text on batch update start: " + - myDebugTextOnBatchUpdateStart + ", deferred changes history: " + - myDebugDeferredChanges + ", current deferred changes: " + myDeferredChangesStorage - ); - } -} diff --git a/platform/platform-tests/testSrc/com/intellij/openapi/editor/impl/CharArrayTest.java b/platform/platform-tests/testSrc/com/intellij/openapi/editor/impl/CharArrayTest.java deleted file mode 100644 index 20357ba9d1e5..000000000000 --- a/platform/platform-tests/testSrc/com/intellij/openapi/editor/impl/CharArrayTest.java +++ /dev/null @@ -1,243 +0,0 @@ -/* - * Copyright 2000-2011 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.openapi.editor.impl; - -import com.intellij.openapi.editor.event.DocumentEvent; -import com.intellij.openapi.editor.impl.event.DocumentEventImpl; -import com.intellij.openapi.util.Pair; -import com.intellij.util.LocalTimeCounter; -import com.intellij.util.containers.Stack; -import com.intellij.util.text.CharSequenceBackedByArray; -import org.jetbrains.annotations.NonNls; -import org.jetbrains.annotations.NotNull; -import org.jmock.Expectations; -import org.jmock.Mockery; -import org.jmock.api.Invocation; -import org.jmock.integration.junit4.JUnit4Mockery; -import org.jmock.lib.action.CustomAction; -import org.jmock.lib.legacy.ClassImposteriser; -import org.junit.After; -import org.junit.Before; -import org.junit.Rule; -import org.junit.Test; -import org.junit.rules.TestWatcher; -import org.junit.runner.Description; - -import java.lang.annotation.ElementType; -import java.lang.annotation.Retention; -import java.lang.annotation.RetentionPolicy; -import java.lang.annotation.Target; - -import static org.junit.Assert.*; - -/** - * @author Denis Zhdanov - * @since 03/01/2011 - */ -public class CharArrayTest { - @Rule - public TestWatcher configReader = new TestWatcher() { - @Override - protected void starting(Description description) { - Config config = description.getAnnotation(Config.class); - if (config != null) { - myConfig = config; - } - } - }; - - private CharArray myArray; - private Config myConfig; - private Mockery myMockery; - private DocumentImpl myDocument; - - @Before - public void setUp() { - myMockery = new JUnit4Mockery() {{ - setImposteriser(ClassImposteriser.INSTANCE); - }}; - myDocument = myMockery.mock(DocumentImpl.class); - - myMockery.checking(new Expectations() {{ - allowing(myDocument).getTextLength(); will(new CustomAction("getTextLength") { - @Override - public Object invoke(Invocation invocation) throws Throwable { - return myArray.length(); - } - }); - }}); - - init(10); - if (myConfig != null) { - myArray.insert(myConfig.text(), 0); - myArray.setDeferredChangeMode(myConfig.deferred()); - } - } - - @After - public void checkExpectations() { - myMockery.assertIsSatisfied(); - } - - @Config(text = "1234", deferred = true) - @Test - public void deferredReplace() { - replace(1, 3, "abc"); - assertTrue(myArray.hasDeferredChanges()); - checkText("1abc4"); - - replace(2, 3, "XY"); - checkText("1aXYc4"); - - replace(3, 6, "ABC"); - checkText("1aXABC"); - - myArray.setDeferredChangeMode(false); - checkText("1aXABC"); - } - - @Config(text = "01234567", deferred = true) - @Test - public void subSequenceWithDeferredChangeBeforeIt() { - replace(0, 2, "abc"); - CharSequenceBackedByArray subsSequence = (CharSequenceBackedByArray)myArray.subSequence(5, 6); - assertArrayEquals("4".toCharArray(), subsSequence.getChars()); - } - - @Config(text = "01234567", deferred = true) - @Test - public void subSequenceWithDeferredChangeIntersectingFromLeft() { - replace(0, 2, "abc"); - CharSequenceBackedByArray subsSequence = (CharSequenceBackedByArray)myArray.subSequence(2, 4); - assertArrayEquals("c2".toCharArray(), subsSequence.getChars()); - } - - @Config(text = "01234567", deferred = true) - @Test - public void subSequenceWithDeferredChangeIntersectingFromRight() { - replace(4, 6, "abc"); - CharSequenceBackedByArray subsSequence = (CharSequenceBackedByArray)myArray.subSequence(3, 5); - assertArrayEquals("3a".toCharArray(), subsSequence.getChars()); - } - - @Config(text = "01234567", deferred = true) - @Test - public void subSequenceWithDeferredChangeAfterIt() { - replace(6, 8, "abc"); - CharSequenceBackedByArray subsSequence = (CharSequenceBackedByArray)myArray.subSequence(1, 2); - assertArrayEquals("1".toCharArray(), subsSequence.getChars()); - } - - private void init(int size) { - myArray = new CharArray(size, new char[0], 0) { - @NotNull - @Override - protected DocumentEvent beforeChangedUpdate(int offset, CharSequence oldString, CharSequence newString, - boolean wholeTextReplaced) { - return new DocumentEventImpl(myDocument, offset, oldString, newString, LocalTimeCounter.currentTime(), wholeTextReplaced); - } - - @Override - protected void afterChangedUpdate(@NotNull DocumentEvent event, long newModificationStamp) { - } - - @Override - protected void assertWriteAccess() { - } - - @Override - protected void assertReadAccess() { - } - }; - } - - private void checkText(@NonNls @NotNull String expected) { - // Test as a whole. - assertEquals(expected, myArray.toString()); - assertEquals(expected.length(), myArray.length()); - - // Test 'charAt()'. - for (int i = 0; i < expected.length(); i++) { - if (expected.charAt(i) != myArray.charAt(i)) { - fail(String.format( - "Detected incorrect 'charAt()' processing for deferred changes. Text: '%1$s'. Expected to get symbol '%2$c' " - + "(numeric value %2$d) at index %3$d but actual symbol is '%4$c' (numeric value %4$d)", - expected, (int)expected.charAt(i), i, (int)myArray.charAt(i))); - } - assertEquals(expected.charAt(i), myArray.charAt(i)); - } - - // Test 'substring()'. - for (int start = 0; start < myArray.length() - 1; start++) { - for (int end = start; end < myArray.length(); end++) { - if (!expected.substring(start, end).equals(myArray.substring(start, end).toString())) { - fail(String.format( - "Detected incorrect 'substring()' processing for deferred changes. Text: '%s', expected to get substring '%s' for " - + "interval [%d; %d) but got '%s'", expected, expected.substring(start, end), start, end, myArray.substring(start, end) - )); - } - } - } - - // Test subSequence(). - checkSubSequence(expected, myArray, new Stack>()); - } - - private void checkSubSequence(@NotNull String expected, @NotNull CharSequence actual, - @NotNull Stack> history) { - assertEquals(expected.length(), actual.length()); - for (int i = 0; i < expected.length(); i++) { - char expectedChar = expected.charAt(i); - char actualChar = actual.charAt(i); - if (expectedChar != actualChar) { - fail(String.format( - "Detected incorrect charAt() processing for result of subSequence() with deferred changes. Original text: '%s', " - + "actual subSequence text: '%s', index: %d, expected symbol: '%c', actual symbol: '%c', subSequence history: %s", - myArray.toString(), expected, i, expectedChar, actualChar, history - )); - } - } - if (!expected.equals(actual.toString())) { - fail(String.format( - "Detected incorrect toString() processing for result of subSequence() with deferred changes. Original text: '%s', " - + "expected subSequence text: '%s', actual subSequence text: '%s', subSequence history: %s", - myArray.toString(), expected, actual.toString(), history - )); - } - assertEquals(expected, actual.toString()); - for (int start = 0; start < expected.length(); start++) { - for (int end = start; end < expected.length(); end++) { - history.push(new Pair(start, end)); - checkSubSequence(expected.substring(start, end), actual.subSequence(start, end), history); - history.pop(); - } - } - } - - private void replace(int startOffset, int endOffset, @NonNls String newText) { - myArray.replace( - startOffset, endOffset, myArray.substring(startOffset, endOffset), newText, LocalTimeCounter.currentTime(), - startOffset == 0 && endOffset == myArray.length() - ); - } - - @Target(ElementType.METHOD) - @Retention(RetentionPolicy.RUNTIME) - private @interface Config { - String text() default ""; - boolean deferred() default false; - } -} From 3a1e4cccc18a4369c198e39cd03f6eaf505fc29e Mon Sep 17 00:00:00 2001 From: peter Date: Fri, 3 Jul 2015 10:28:45 +0200 Subject: [PATCH 08/39] fold CoreCommandProcessor lines in console stack traces --- plugins/devkit/resources/META-INF/plugin.xml | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/plugins/devkit/resources/META-INF/plugin.xml b/plugins/devkit/resources/META-INF/plugin.xml index 60dac946e590..45c0350bb308 100644 --- a/plugins/devkit/resources/META-INF/plugin.xml +++ b/plugins/devkit/resources/META-INF/plugin.xml @@ -142,7 +142,7 @@ - + From e5e2b196d7e5a7c9e442c80917290cb006c976c5 Mon Sep 17 00:00:00 2001 From: Vladimir Krivosheev Date: Fri, 3 Jul 2015 10:07:15 +0200 Subject: [PATCH 09/39] IDEA-CR-3419 move kt file according to code style --- .../testSrc/BinaryRequestHandlerTest.kt | 2 +- .../built-in-server/testSrc/RestApiTest.kt | 2 +- .../com/intellij/options/SchemeManagerTest.kt | 21 ++++++++++++++++--- .../intellij/testFramework}/FixtureRule.kt | 3 +-- .../testFramework}/TemporaryDirectory.kt | 2 +- .../intellij/testFramework}/matchers.kt | 2 +- 6 files changed, 23 insertions(+), 9 deletions(-) rename platform/testFramework/testSrc/{ => com/intellij/testFramework}/FixtureRule.kt (93%) rename platform/testFramework/testSrc/{ => com/intellij/testFramework}/TemporaryDirectory.kt (96%) rename platform/testFramework/testSrc/{ => com/intellij/testFramework}/matchers.kt (97%) diff --git a/platform/built-in-server/testSrc/BinaryRequestHandlerTest.kt b/platform/built-in-server/testSrc/BinaryRequestHandlerTest.kt index 1d3b65cc977f..dbce08860f58 100644 --- a/platform/built-in-server/testSrc/BinaryRequestHandlerTest.kt +++ b/platform/built-in-server/testSrc/BinaryRequestHandlerTest.kt @@ -1,5 +1,6 @@ package org.jetbrains.ide +import com.intellij.testFramework.FixtureRule import com.intellij.util.Consumer import com.intellij.util.concurrency.Semaphore import com.intellij.util.net.NetUtils @@ -17,7 +18,6 @@ import org.jetbrains.io.ChannelExceptionHandler import org.jetbrains.io.Decoder import org.jetbrains.io.MessageDecoder import org.jetbrains.io.NettyUtil -import org.jetbrains.testFramework.FixtureRule import org.junit.Rule import org.junit.Test import org.junit.rules.RuleChain diff --git a/platform/built-in-server/testSrc/RestApiTest.kt b/platform/built-in-server/testSrc/RestApiTest.kt index b4716ebfac5e..223cc0121693 100644 --- a/platform/built-in-server/testSrc/RestApiTest.kt +++ b/platform/built-in-server/testSrc/RestApiTest.kt @@ -2,10 +2,10 @@ package org.jetbrains.ide import com.google.gson.stream.JsonWriter import com.intellij.openapi.vfs.CharsetToolkit +import com.intellij.testFramework.FixtureRule import io.netty.handler.codec.http.HttpResponseStatus import org.hamcrest.CoreMatchers.equalTo import org.jetbrains.ide.TestManager.TestDescriptor -import org.jetbrains.testFramework.FixtureRule import org.junit.Assert.assertThat import org.junit.Rule import org.junit.Test diff --git a/platform/platform-tests/testSrc/com/intellij/options/SchemeManagerTest.kt b/platform/platform-tests/testSrc/com/intellij/options/SchemeManagerTest.kt index 2cb9d57572d9..fffcb55dda35 100644 --- a/platform/platform-tests/testSrc/com/intellij/options/SchemeManagerTest.kt +++ b/platform/platform-tests/testSrc/com/intellij/options/SchemeManagerTest.kt @@ -1,3 +1,18 @@ +/* + * Copyright 2000-2015 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.options import com.intellij.openapi.application.invokeAndWaitIfNeed @@ -9,7 +24,10 @@ import com.intellij.openapi.util.JDOMUtil import com.intellij.openapi.util.io.BufferExposingByteArrayOutputStream import com.intellij.openapi.util.io.FileUtil import com.intellij.openapi.util.text.StringUtil +import com.intellij.testFramework.FixtureRule import com.intellij.testFramework.PlatformTestUtil +import com.intellij.testFramework.TemporaryDirectory +import com.intellij.testFramework.exists import com.intellij.util.SmartList import com.intellij.util.lang.CompoundRuntimeException import com.intellij.util.xmlb.SkipDefaultValuesSerializationFilters @@ -25,9 +43,6 @@ import org.hamcrest.CoreMatchers.sameInstance import org.hamcrest.MatcherAssert.assertThat import org.hamcrest.collection.IsMapContaining.hasKey import org.jdom.Element -import org.jetbrains.testFramework.FixtureRule -import org.jetbrains.testFramework.TemporaryDirectory -import org.jetbrains.testFramework.exists import org.junit.Rule import org.junit.Test import java.io.File diff --git a/platform/testFramework/testSrc/FixtureRule.kt b/platform/testFramework/testSrc/com/intellij/testFramework/FixtureRule.kt similarity index 93% rename from platform/testFramework/testSrc/FixtureRule.kt rename to platform/testFramework/testSrc/com/intellij/testFramework/FixtureRule.kt index 06506fa0c744..b28101e05f4a 100644 --- a/platform/testFramework/testSrc/FixtureRule.kt +++ b/platform/testFramework/testSrc/com/intellij/testFramework/FixtureRule.kt @@ -13,10 +13,9 @@ * See the License for the specific language governing permissions and * limitations under the License. */ -package org.jetbrains.testFramework +package com.intellij.testFramework import com.intellij.openapi.application.invokeAndWaitIfNeed -import com.intellij.testFramework.UsefulTestCase import com.intellij.testFramework.fixtures.IdeaTestFixtureFactory import org.junit.rules.ExternalResource diff --git a/platform/testFramework/testSrc/TemporaryDirectory.kt b/platform/testFramework/testSrc/com/intellij/testFramework/TemporaryDirectory.kt similarity index 96% rename from platform/testFramework/testSrc/TemporaryDirectory.kt rename to platform/testFramework/testSrc/com/intellij/testFramework/TemporaryDirectory.kt index d49ca2587174..bddbac49783e 100644 --- a/platform/testFramework/testSrc/TemporaryDirectory.kt +++ b/platform/testFramework/testSrc/com/intellij/testFramework/TemporaryDirectory.kt @@ -13,7 +13,7 @@ * See the License for the specific language governing permissions and * limitations under the License. */ -package org.jetbrains.testFramework +package com.intellij.testFramework import com.intellij.openapi.util.io.FileUtil import com.intellij.openapi.util.io.FileUtilRt diff --git a/platform/testFramework/testSrc/matchers.kt b/platform/testFramework/testSrc/com/intellij/testFramework/matchers.kt similarity index 97% rename from platform/testFramework/testSrc/matchers.kt rename to platform/testFramework/testSrc/com/intellij/testFramework/matchers.kt index 7f2fb364bba4..88dba511bd03 100644 --- a/platform/testFramework/testSrc/matchers.kt +++ b/platform/testFramework/testSrc/com/intellij/testFramework/matchers.kt @@ -13,7 +13,7 @@ * See the License for the specific language governing permissions and * limitations under the License. */ -package org.jetbrains.testFramework +package com.intellij.testFramework import org.hamcrest.Description import org.hamcrest.Factory From 3e7118d7241f79fee387c755a529af9b478306d2 Mon Sep 17 00:00:00 2001 From: "Maxim.Mossienko" Date: Fri, 3 Jul 2015 11:13:34 +0200 Subject: [PATCH 10/39] more compact test after review IDEA-CR-3505 --- .../com/intellij/find/FindManagerTest.java | 20 +------------------ 1 file changed, 1 insertion(+), 19 deletions(-) diff --git a/java/java-tests/testSrc/com/intellij/find/FindManagerTest.java b/java/java-tests/testSrc/com/intellij/find/FindManagerTest.java index 3f467403c061..4cf9e14247f8 100644 --- a/java/java-tests/testSrc/com/intellij/find/FindManagerTest.java +++ b/java/java-tests/testSrc/com/intellij/find/FindManagerTest.java @@ -462,25 +462,7 @@ public class FindManagerTest extends DaemonAnalyzerTestCase { } public void testReplaceWithRegExp() { - FindModel findModel = new FindModel(); - findModel.setStringToFind("(? Date: Fri, 3 Jul 2015 11:22:46 +0200 Subject: [PATCH 11/39] node.js: node js interpreter field: do not delete the value in the text field when user clicks the combo box button --- .../ui/TextFieldWithHistoryWithBrowseButton.java | 10 ++++++++++ 1 file changed, 10 insertions(+) diff --git a/platform/platform-api/src/com/intellij/ui/TextFieldWithHistoryWithBrowseButton.java b/platform/platform-api/src/com/intellij/ui/TextFieldWithHistoryWithBrowseButton.java index e16e421a46a9..72f378172589 100644 --- a/platform/platform-api/src/com/intellij/ui/TextFieldWithHistoryWithBrowseButton.java +++ b/platform/platform-api/src/com/intellij/ui/TextFieldWithHistoryWithBrowseButton.java @@ -22,10 +22,14 @@ import com.intellij.openapi.ui.ComponentWithBrowseButton; import com.intellij.openapi.ui.TextComponentAccessor; import org.jetbrains.annotations.Nullable; +import javax.swing.*; + /** * User: anna */ public class TextFieldWithHistoryWithBrowseButton extends ComponentWithBrowseButton { + private String myText; + public TextFieldWithHistoryWithBrowseButton() { super(new TextFieldWithHistory(), null); } @@ -54,4 +58,10 @@ public class TextFieldWithHistoryWithBrowseButton extends ComponentWithBrowseBut public String getText() { return getChildComponent().getText(); } + + public void setText(String text) { + final ComboBoxModel model = getChildComponent().getModel(); + model.setSelectedItem(text); + myText = text; + } } From a233749cce823d941e2fed160fad28cb8a72a85a Mon Sep 17 00:00:00 2001 From: Alexey Kudravtsev Date: Thu, 2 Jul 2015 14:48:21 +0300 Subject: [PATCH 12/39] optimisation --- .../core-api/src/com/intellij/psi/stubs/PsiFileStubImpl.java | 5 +++-- 1 file changed, 3 insertions(+), 2 deletions(-) diff --git a/platform/core-api/src/com/intellij/psi/stubs/PsiFileStubImpl.java b/platform/core-api/src/com/intellij/psi/stubs/PsiFileStubImpl.java index 60ba5f21a0d2..a8bf86a79722 100644 --- a/platform/core-api/src/com/intellij/psi/stubs/PsiFileStubImpl.java +++ b/platform/core-api/src/com/intellij/psi/stubs/PsiFileStubImpl.java @@ -1,5 +1,5 @@ /* - * Copyright 2000-2009 JetBrains s.r.o. + * Copyright 2000-2015 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. @@ -70,7 +70,8 @@ public class PsiFileStubImpl extends StubBase implements P @NotNull @Override public PsiFileStub[] getStubRoots() { - return myStubRoots != null ? myStubRoots : new PsiFileStub[]{this}; + PsiFileStub[] roots = myStubRoots; + return roots == null ? new PsiFileStub[]{this} : roots; } public void setStubRoots(@NotNull PsiFileStub[] roots) { From ed54b852c52feb64892c056da3ad32190f3493a1 Mon Sep 17 00:00:00 2001 From: Alexey Kudravtsev Date: Thu, 2 Jul 2015 15:09:34 +0300 Subject: [PATCH 13/39] notnull --- .../fileTypes/impl/IgnoredPatternSet.java | 9 ++++---- .../openapi/fileTypes/FileTypeRegistry.java | 6 ++--- .../intellij/core/CoreFileTypeRegistry.java | 6 ++--- .../EnforcedPlainTextFileTypeFactory.java | 20 +++++------------ .../EnforcedPlainTextFileTypeManager.java | 8 +++---- .../exclude/PersistentFileSetManager.java | 19 ++++++++-------- .../ProjectPlainTextFileTypeManager.java | 5 +++-- .../fileTypes/MockFileTypeManager.java | 7 +++--- .../openapi/fileTypes/ex/FileTypeChooser.java | 4 ++-- .../fileTypes/impl/FileTypeManagerImpl.java | 22 ++++++++++--------- .../intellij/mock/MockFileTypeManager.java | 6 ++--- 11 files changed, 54 insertions(+), 58 deletions(-) diff --git a/jps/model-impl/src/com/intellij/openapi/fileTypes/impl/IgnoredPatternSet.java b/jps/model-impl/src/com/intellij/openapi/fileTypes/impl/IgnoredPatternSet.java index cdd652fa7220..35d300e0436e 100644 --- a/jps/model-impl/src/com/intellij/openapi/fileTypes/impl/IgnoredPatternSet.java +++ b/jps/model-impl/src/com/intellij/openapi/fileTypes/impl/IgnoredPatternSet.java @@ -1,5 +1,5 @@ /* - * Copyright 2000-2014 JetBrains s.r.o. + * Copyright 2000-2015 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. @@ -31,6 +31,7 @@ public class IgnoredPatternSet { private final Set myMasks = new LinkedHashSet(); private final FileTypeAssocTable myIgnorePatterns = new FileTypeAssocTable().copy(); + @NotNull Set getIgnoreMasks() { return Collections.unmodifiableSet(myMasks); } @@ -41,9 +42,7 @@ public class IgnoredPatternSet { StringTokenizer tokenizer = new StringTokenizer(list, ";"); while (tokenizer.hasMoreTokens()) { String ignoredFile = tokenizer.nextToken(); - if (ignoredFile != null) { - addIgnoreMask(ignoredFile); - } + addIgnoreMask(ignoredFile); } } @@ -64,7 +63,7 @@ public class IgnoredPatternSet { return fileName.endsWith(FileUtil.ASYNC_DELETE_EXTENSION); } - public void clearPatterns() { + void clearPatterns() { myMasks.clear(); myIgnorePatterns.removeAllAssociations(Boolean.TRUE); } diff --git a/platform/core-api/src/com/intellij/openapi/fileTypes/FileTypeRegistry.java b/platform/core-api/src/com/intellij/openapi/fileTypes/FileTypeRegistry.java index 2fd9e8b1a5e1..970ecb8c4a34 100644 --- a/platform/core-api/src/com/intellij/openapi/fileTypes/FileTypeRegistry.java +++ b/platform/core-api/src/com/intellij/openapi/fileTypes/FileTypeRegistry.java @@ -1,5 +1,5 @@ /* - * Copyright 2000-2014 JetBrains s.r.o. + * Copyright 2000-2015 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. @@ -29,7 +29,7 @@ import org.jetbrains.annotations.Nullable; public abstract class FileTypeRegistry { public static Getter ourInstanceGetter; - public abstract boolean isFileIgnored(@NonNls @NotNull VirtualFile file); + public abstract boolean isFileIgnored(@NotNull VirtualFile file); public static FileTypeRegistry getInstance() { return ourInstanceGetter.get(); @@ -86,7 +86,7 @@ public abstract class FileTypeRegistry { * Finds a file type with the specified name. */ @Nullable - public abstract FileType findFileTypeByName(String fileTypeName); + public abstract FileType findFileTypeByName(@NotNull String fileTypeName); /** * Pluggable file type detector by content diff --git a/platform/core-impl/src/com/intellij/core/CoreFileTypeRegistry.java b/platform/core-impl/src/com/intellij/core/CoreFileTypeRegistry.java index ee06fa4209bd..2eeaf228873c 100644 --- a/platform/core-impl/src/com/intellij/core/CoreFileTypeRegistry.java +++ b/platform/core-impl/src/com/intellij/core/CoreFileTypeRegistry.java @@ -1,5 +1,5 @@ /* - * Copyright 2000-2011 JetBrains s.r.o. + * Copyright 2000-2015 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. @@ -43,7 +43,7 @@ public class CoreFileTypeRegistry extends FileTypeRegistry { } @Override - public boolean isFileIgnored(@NonNls @NotNull VirtualFile file) { + public boolean isFileIgnored(@NotNull VirtualFile file) { return false; } @@ -93,7 +93,7 @@ public class CoreFileTypeRegistry extends FileTypeRegistry { @Nullable @Override - public FileType findFileTypeByName(String fileTypeName) { + public FileType findFileTypeByName(@NotNull String fileTypeName) { for (FileType type : myAllFileTypes) { if (type.getName().equals(fileTypeName)) { return type; diff --git a/platform/lang-impl/src/com/intellij/openapi/file/exclude/EnforcedPlainTextFileTypeFactory.java b/platform/lang-impl/src/com/intellij/openapi/file/exclude/EnforcedPlainTextFileTypeFactory.java index d70b45f60f2a..aba2c1698f3b 100644 --- a/platform/lang-impl/src/com/intellij/openapi/file/exclude/EnforcedPlainTextFileTypeFactory.java +++ b/platform/lang-impl/src/com/intellij/openapi/file/exclude/EnforcedPlainTextFileTypeFactory.java @@ -1,5 +1,5 @@ /* - * Copyright 2000-2014 JetBrains s.r.o. + * Copyright 2000-2015 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. @@ -31,7 +31,6 @@ import javax.swing.*; * @author Rustam Vishnyakov */ public class EnforcedPlainTextFileTypeFactory extends FileTypeFactory { - public static final LayeredIcon ENFORCED_PLAIN_TEXT_ICON = new LayeredIcon(2); public static final String ENFORCED_PLAIN_TEXT = "Enforced Plain Text"; @@ -40,15 +39,10 @@ public class EnforcedPlainTextFileTypeFactory extends FileTypeFactory { ENFORCED_PLAIN_TEXT_ICON.setIcon(PlatformIcons.EXCLUDED_FROM_COMPILE_ICON, 1); } - private final FileTypeIdentifiableByVirtualFile myFileType; - - - public EnforcedPlainTextFileTypeFactory() { - - - myFileType = new FileTypeIdentifiableByVirtualFile() { + public EnforcedPlainTextFileTypeFactory() { + myFileType = new FileTypeIdentifiableByVirtualFile() { @Override public boolean isMyFileType(@NotNull VirtualFile file) { return isMarkedAsPlainText(file); @@ -95,14 +89,12 @@ public class EnforcedPlainTextFileTypeFactory extends FileTypeFactory { } @Override - public void createFileTypes(final @NotNull FileTypeConsumer consumer) { + public void createFileTypes(@NotNull final FileTypeConsumer consumer) { consumer.consume(myFileType, ""); } - private static boolean isMarkedAsPlainText(VirtualFile file) { + private static boolean isMarkedAsPlainText(@NotNull VirtualFile file) { EnforcedPlainTextFileTypeManager typeManager = EnforcedPlainTextFileTypeManager.getInstance(); - if (typeManager == null) return false; - return typeManager.isMarkedAsPlainText(file); + return typeManager != null && typeManager.isMarkedAsPlainText(file); } - } diff --git a/platform/lang-impl/src/com/intellij/openapi/file/exclude/EnforcedPlainTextFileTypeManager.java b/platform/lang-impl/src/com/intellij/openapi/file/exclude/EnforcedPlainTextFileTypeManager.java index da2d83a54928..50fbbb20c0b7 100644 --- a/platform/lang-impl/src/com/intellij/openapi/file/exclude/EnforcedPlainTextFileTypeManager.java +++ b/platform/lang-impl/src/com/intellij/openapi/file/exclude/EnforcedPlainTextFileTypeManager.java @@ -48,7 +48,7 @@ public class EnforcedPlainTextFileTypeManager implements ProjectManagerListener ProjectManager.getInstance().addProjectManagerListener(this); } - public boolean isMarkedAsPlainText(VirtualFile file) { + public boolean isMarkedAsPlainText(@NotNull VirtualFile file) { if (!(file instanceof VirtualFileWithId) || file.isDirectory()) return false; if (!mySetsInitialized) { synchronized (LOCK) { @@ -77,15 +77,15 @@ public class EnforcedPlainTextFileTypeManager implements ProjectManagerListener return !originalType.isBinary() && originalType != FileTypes.PLAIN_TEXT && originalType != StdFileTypes.JAVA; } - public void markAsPlainText(@NotNull Project project, VirtualFile... files) { + public void markAsPlainText(@NotNull Project project, @NotNull VirtualFile... files) { setPlainTextStatus(project, true, files); } - public void resetOriginalFileType(@NotNull Project project, VirtualFile... files) { + public void resetOriginalFileType(@NotNull Project project, @NotNull VirtualFile... files) { setPlainTextStatus(project, false, files); } - private void setPlainTextStatus(@NotNull final Project project, final boolean isAdded, final VirtualFile... files) { + private void setPlainTextStatus(@NotNull final Project project, final boolean isAdded, @NotNull final VirtualFile... files) { ApplicationManager.getApplication().runWriteAction(new Runnable() { @Override public void run() { diff --git a/platform/lang-impl/src/com/intellij/openapi/file/exclude/PersistentFileSetManager.java b/platform/lang-impl/src/com/intellij/openapi/file/exclude/PersistentFileSetManager.java index 67b19d6fa54f..93ccdb77813b 100644 --- a/platform/lang-impl/src/com/intellij/openapi/file/exclude/PersistentFileSetManager.java +++ b/platform/lang-impl/src/com/intellij/openapi/file/exclude/PersistentFileSetManager.java @@ -1,5 +1,5 @@ /* - * Copyright 2000-2011 JetBrains s.r.o. + * Copyright 2000-2015 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. @@ -20,7 +20,7 @@ import com.intellij.openapi.vfs.VfsUtilCore; import com.intellij.openapi.vfs.VirtualFile; import com.intellij.openapi.vfs.VirtualFileManager; import com.intellij.openapi.vfs.VirtualFileWithId; -import com.intellij.util.containers.HashSet; +import gnu.trove.THashSet; import org.jdom.Attribute; import org.jdom.Element; import org.jetbrains.annotations.NotNull; @@ -30,23 +30,23 @@ import java.util.*; /** * @author Rustam Vishnyakov */ -public class PersistentFileSetManager implements PersistentStateComponent { +class PersistentFileSetManager implements PersistentStateComponent { private static final String FILE_ELEMENT = "file"; private static final String PATH_ATTR = "url"; - private final Set myFiles = new HashSet(); + private final Set myFiles = new THashSet(); - protected boolean addFile(VirtualFile file) { + protected boolean addFile(@NotNull VirtualFile file) { if (!(file instanceof VirtualFileWithId) || file.isDirectory()) return false; myFiles.add(file); return true; } - protected boolean containsFile(VirtualFile file) { + protected boolean containsFile(@NotNull VirtualFile file) { return myFiles.contains(file); } - protected boolean removeFile(VirtualFile file) { + protected boolean removeFile(@NotNull VirtualFile file) { if (!myFiles.contains(file)) return false; myFiles.remove(file); return true; @@ -56,8 +56,9 @@ public class PersistentFileSetManager implements PersistentStateComponent getFiles() { return myFiles; } - - public Collection getSortedFiles() { + + @NotNull + private Collection getSortedFiles() { List sortedFiles = new ArrayList(); sortedFiles.addAll(myFiles); Collections.sort(sortedFiles, new Comparator() { diff --git a/platform/lang-impl/src/com/intellij/openapi/file/exclude/ProjectPlainTextFileTypeManager.java b/platform/lang-impl/src/com/intellij/openapi/file/exclude/ProjectPlainTextFileTypeManager.java index 7c5ad135b1a2..ba3a9d7365d8 100644 --- a/platform/lang-impl/src/com/intellij/openapi/file/exclude/ProjectPlainTextFileTypeManager.java +++ b/platform/lang-impl/src/com/intellij/openapi/file/exclude/ProjectPlainTextFileTypeManager.java @@ -1,5 +1,5 @@ /* - * Copyright 2000-2012 JetBrains s.r.o. + * Copyright 2000-2015 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. @@ -22,6 +22,7 @@ import com.intellij.openapi.components.StoragePathMacros; import com.intellij.openapi.project.Project; import com.intellij.openapi.roots.ProjectFileIndex; import com.intellij.openapi.vfs.VirtualFile; +import org.jetbrains.annotations.NotNull; /** * @author Rustam Vishnyakov @@ -34,7 +35,7 @@ public class ProjectPlainTextFileTypeManager extends PersistentFileSetManager { myIndex = projectFileIndex; } - public boolean hasProjectContaining(VirtualFile file) { + boolean hasProjectContaining(@NotNull VirtualFile file) { return myIndex.isInContent(file); } diff --git a/platform/platform-api/src/com/intellij/openapi/fileTypes/MockFileTypeManager.java b/platform/platform-api/src/com/intellij/openapi/fileTypes/MockFileTypeManager.java index c65b7255a19b..af66caca2db0 100644 --- a/platform/platform-api/src/com/intellij/openapi/fileTypes/MockFileTypeManager.java +++ b/platform/platform-api/src/com/intellij/openapi/fileTypes/MockFileTypeManager.java @@ -1,5 +1,5 @@ /* - * Copyright 2000-2013 JetBrains s.r.o. + * Copyright 2000-2015 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. @@ -65,7 +65,7 @@ public class MockFileTypeManager extends FileTypeManager { } @Override - public boolean isFileIgnored(@NonNls @NotNull VirtualFile file) { + public boolean isFileIgnored(@NotNull VirtualFile file) { return false; } @@ -123,6 +123,7 @@ public class MockFileTypeManager extends FileTypeManager { return MockLanguageFileType.INSTANCE; } + @Override public boolean isFileOfType(@NotNull VirtualFile file, @NotNull FileType type) { return false; } @@ -135,7 +136,7 @@ public class MockFileTypeManager extends FileTypeManager { @Nullable @Override - public FileType findFileTypeByName(String fileTypeName) { + public FileType findFileTypeByName(@NotNull String fileTypeName) { return null; } } diff --git a/platform/platform-impl/src/com/intellij/openapi/fileTypes/ex/FileTypeChooser.java b/platform/platform-impl/src/com/intellij/openapi/fileTypes/ex/FileTypeChooser.java index ad05f9dcb205..6118ebab35fd 100644 --- a/platform/platform-impl/src/com/intellij/openapi/fileTypes/ex/FileTypeChooser.java +++ b/platform/platform-impl/src/com/intellij/openapi/fileTypes/ex/FileTypeChooser.java @@ -1,5 +1,5 @@ /* - * Copyright 2000-2014 JetBrains s.r.o. + * Copyright 2000-2015 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. @@ -144,7 +144,7 @@ public class FileTypeChooser extends DialogWrapper { } FileType type = file.getFileType(); if (type == FileTypes.UNKNOWN) { - type = getKnownFileTypeOrAssociate(file.getName()); + type = getKnownFileTypeOrAssociate(file.getName()); } return type; } diff --git a/platform/platform-impl/src/com/intellij/openapi/fileTypes/impl/FileTypeManagerImpl.java b/platform/platform-impl/src/com/intellij/openapi/fileTypes/impl/FileTypeManagerImpl.java index cb8b5eec6d28..42e28358916d 100644 --- a/platform/platform-impl/src/com/intellij/openapi/fileTypes/impl/FileTypeManagerImpl.java +++ b/platform/platform-impl/src/com/intellij/openapi/fileTypes/impl/FileTypeManagerImpl.java @@ -594,7 +594,7 @@ public class FileTypeManagerImpl extends FileTypeManagerEx implements Persistent } @Override - public FileType findFileTypeByName(String fileTypeName) { + public FileType findFileTypeByName(@NotNull String fileTypeName) { FileType type = getStdFileType(fileTypeName); // TODO: Abstract file types are not std one, so need to be restored specially, // currently there are 6 of them and restoration does not happen very often so just iteration is enough @@ -738,7 +738,7 @@ public class FileTypeManagerImpl extends FileTypeManagerEx implements Persistent }); } - private void unregisterFileTypeWithoutNotification(FileType fileType) { + private void unregisterFileTypeWithoutNotification(@NotNull FileType fileType) { myPatternsTable.removeAllAssociations(fileType); mySchemesManager.removeScheme(fileType); if (fileType instanceof FileTypeIdentifiableByVirtualFile) { @@ -793,14 +793,14 @@ public class FileTypeManagerImpl extends FileTypeManagerEx implements Persistent } @Override - public boolean isFileIgnored(@NonNls @NotNull VirtualFile file) { + public boolean isFileIgnored(@NotNull VirtualFile file) { return myIgnoredFileCache.isFileIgnored(file); } @Override - @SuppressWarnings({"deprecation"}) @NotNull public String[] getAssociatedExtensions(@NotNull FileType type) { + //noinspection deprecation return myPatternsTable.getAssociatedExtensions(type); } @@ -1033,7 +1033,7 @@ public class FileTypeManagerImpl extends FileTypeManagerEx implements Persistent FileNameMatcher[] unresolvedMappingKeys = myUnresolvedMappings.keySet().toArray(new FileNameMatcher[myUnresolvedMappings.size()]); Arrays.sort(unresolvedMappingKeys, new Comparator() { @Override - public int compare(FileNameMatcher o1, FileNameMatcher o2) { + public int compare(@NotNull FileNameMatcher o1, @NotNull FileNameMatcher o2) { return o1.getPresentableString().compareTo(o2.getPresentableString()); } }); @@ -1080,7 +1080,7 @@ public class FileTypeManagerImpl extends FileTypeManagerEx implements Persistent } } - private boolean isApproved(FileNameMatcher matcher) { + private boolean isApproved(@NotNull FileNameMatcher matcher) { Pair pair = myRemovedMappings.get(matcher); return pair != null && pair.getSecond(); } @@ -1234,7 +1234,7 @@ public class FileTypeManagerImpl extends FileTypeManagerEx implements Persistent } } - private static boolean shouldSave(FileType fileType) { + private static boolean shouldSave(@NotNull FileType fileType) { return fileType != FileTypes.UNKNOWN && !fileType.isReadOnly(); } @@ -1248,6 +1248,7 @@ public class FileTypeManagerImpl extends FileTypeManagerEx implements Persistent return getFileTypeComponentName(); } + @NotNull public static String getFileTypeComponentName() { return PlatformUtils.isIdeaCommunity() ? "CommunityFileTypes" : "FileTypeManager"; } @@ -1274,7 +1275,7 @@ public class FileTypeManagerImpl extends FileTypeManagerEx implements Persistent fireFileTypesChanged(); } - public void associate(FileType fileType, FileNameMatcher matcher, boolean fireChange) { + public void associate(@NotNull FileType fileType, @NotNull FileNameMatcher matcher, boolean fireChange) { if (!myPatternsTable.isAssociatedWith(fileType, matcher)) { if (fireChange) { fireBeforeFileTypesChanged(); @@ -1286,7 +1287,7 @@ public class FileTypeManagerImpl extends FileTypeManagerEx implements Persistent } } - public void removeAssociation(FileType fileType, FileNameMatcher matcher, boolean fireChange) { + public void removeAssociation(@NotNull FileType fileType, @NotNull FileNameMatcher matcher, boolean fireChange) { if (myPatternsTable.isAssociatedWith(fileType, matcher)) { if (fireChange) { fireBeforeFileTypesChanged(); @@ -1311,7 +1312,7 @@ public class FileTypeManagerImpl extends FileTypeManagerEx implements Persistent return FileTypeChooser.getKnownFileTypeOrAssociate(file, project); } - private void registerReDetectedMappings(StandardFileType pair) { + private void registerReDetectedMappings(@NotNull StandardFileType pair) { FileType fileType = pair.fileType; if (fileType == PlainTextFileType.INSTANCE) return; for (FileNameMatcher matcher : pair.matchers) { @@ -1333,6 +1334,7 @@ public class FileTypeManagerImpl extends FileTypeManagerEx implements Persistent } } + @NotNull Map> getRemovedMappings() { return myRemovedMappings; } diff --git a/platform/testFramework/src/com/intellij/mock/MockFileTypeManager.java b/platform/testFramework/src/com/intellij/mock/MockFileTypeManager.java index 034cc3f92e2a..673dd6a5378f 100644 --- a/platform/testFramework/src/com/intellij/mock/MockFileTypeManager.java +++ b/platform/testFramework/src/com/intellij/mock/MockFileTypeManager.java @@ -1,5 +1,5 @@ /* - * Copyright 2000-2014 JetBrains s.r.o. + * Copyright 2000-2015 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. @@ -106,7 +106,7 @@ public class MockFileTypeManager extends FileTypeManagerEx { } @Override - public boolean isFileIgnored(@NonNls @NotNull VirtualFile file) { + public boolean isFileIgnored(@NotNull VirtualFile file) { return false; } @@ -191,7 +191,7 @@ public class MockFileTypeManager extends FileTypeManagerEx { @Nullable @Override - public FileType findFileTypeByName(String fileTypeName) { + public FileType findFileTypeByName(@NotNull String fileTypeName) { return null; } } From 329b75b620877156968a4d6074ca325f8027cd86 Mon Sep 17 00:00:00 2001 From: Alexey Kudravtsev Date: Thu, 2 Jul 2015 15:10:13 +0300 Subject: [PATCH 14/39] optimisation: access myExactFileNameMappings only if it's not empty --- .../fileTypes/impl/FileTypeAssocTable.java | 76 +++++++------------ 1 file changed, 26 insertions(+), 50 deletions(-) diff --git a/jps/model-impl/src/com/intellij/openapi/fileTypes/impl/FileTypeAssocTable.java b/jps/model-impl/src/com/intellij/openapi/fileTypes/impl/FileTypeAssocTable.java index ad29218f28c4..3dad90d211ac 100644 --- a/jps/model-impl/src/com/intellij/openapi/fileTypes/impl/FileTypeAssocTable.java +++ b/jps/model-impl/src/com/intellij/openapi/fileTypes/impl/FileTypeAssocTable.java @@ -37,29 +37,14 @@ public class FileTypeAssocTable { private final Map myExtensionMappings; private final Map myExactFileNameMappings; private final Map myExactFileNameAnyCaseMappings; - private boolean myHasAnyCaseExactMappings; private final List> myMatchingMappings; - private FileTypeAssocTable(Map extensionMappings, Map exactFileNameMappings, Map exactFileNameAnyCaseMappings, List> matchingMappings) { + private FileTypeAssocTable(@NotNull Map extensionMappings, @NotNull Map exactFileNameMappings, @NotNull Map exactFileNameAnyCaseMappings, List> matchingMappings) { myExtensionMappings = new THashMap(extensionMappings, CharSequenceHashingStrategy.CASE_INSENSITIVE); myExactFileNameMappings = new THashMap(exactFileNameMappings, CharSequenceHashingStrategy.CASE_SENSITIVE); - - myExactFileNameAnyCaseMappings = new THashMap(exactFileNameAnyCaseMappings, CharSequenceHashingStrategy.CASE_INSENSITIVE) { - @Override - public T remove(Object key) { - T removed = super.remove(key); - myHasAnyCaseExactMappings = size() > 0; - return removed; - } + myExactFileNameAnyCaseMappings = new THashMap(exactFileNameAnyCaseMappings, CharSequenceHashingStrategy.CASE_INSENSITIVE); - @Override - public T put(CharSequence key, T value) { - T result = super.put(key, value); - myHasAnyCaseExactMappings = true; - return result; - } - }; myMatchingMappings = new ArrayList>(matchingMappings); } @@ -67,7 +52,7 @@ public class FileTypeAssocTable { this(Collections.emptyMap(), Collections.emptyMap(), Collections.emptyMap(), Collections.>emptyList()); } - public boolean isAssociatedWith(T type, FileNameMatcher matcher) { + public boolean isAssociatedWith(@NotNull T type, @NotNull FileNameMatcher matcher) { if (matcher instanceof ExtensionFileNameMatcher || matcher instanceof ExactFileNameMatcher) { return findAssociatedFileType(matcher) == type; } @@ -86,17 +71,15 @@ public class FileTypeAssocTable { else if (matcher instanceof ExactFileNameMatcher) { final ExactFileNameMatcher exactFileNameMatcher = (ExactFileNameMatcher)matcher; - if (exactFileNameMatcher.isIgnoreCase()) { - myExactFileNameAnyCaseMappings.put(exactFileNameMatcher.getFileName(), type); - } else { - myExactFileNameMappings.put(exactFileNameMatcher.getFileName(), type); - } - } else { + Map mapToUse = exactFileNameMatcher.isIgnoreCase() ? myExactFileNameAnyCaseMappings : myExactFileNameMappings; + mapToUse.put(exactFileNameMatcher.getFileName(), type); + } + else { myMatchingMappings.add(Pair.create(matcher, type)); } } - public boolean removeAssociation(FileNameMatcher matcher, T type) { + boolean removeAssociation(@NotNull FileNameMatcher matcher, @NotNull T type) { if (matcher instanceof ExtensionFileNameMatcher) { String extension = ((ExtensionFileNameMatcher)matcher).getExtension(); if (myExtensionMappings.get(extension) == type) { @@ -108,14 +91,9 @@ public class FileTypeAssocTable { if (matcher instanceof ExactFileNameMatcher) { final ExactFileNameMatcher exactFileNameMatcher = (ExactFileNameMatcher)matcher; - final Map mapToUse; String fileName = exactFileNameMatcher.getFileName(); - if (exactFileNameMatcher.isIgnoreCase()) { - mapToUse = myExactFileNameAnyCaseMappings; - } else { - mapToUse = myExactFileNameMappings; - } + final Map mapToUse = exactFileNameMatcher.isIgnoreCase() ? myExactFileNameAnyCaseMappings : myExactFileNameMappings; if(mapToUse.get(fileName) == type) { mapToUse.remove(fileName); return true; @@ -134,7 +112,7 @@ public class FileTypeAssocTable { return false; } - public boolean removeAllAssociations(T type) { + boolean removeAllAssociations(@NotNull T type) { boolean changed = removeAssociationsFromMap(myExtensionMappings, type, false); changed = removeAssociationsFromMap(myExactFileNameAnyCaseMappings, type, changed); @@ -151,7 +129,7 @@ public class FileTypeAssocTable { return changed; } - private boolean removeAssociationsFromMap(Map extensionMappings, T type, boolean changed) { + private boolean removeAssociationsFromMap(@NotNull Map extensionMappings, @NotNull T type, boolean changed) { Set exts = extensionMappings.keySet(); CharSequence[] extsStrings = exts.toArray(new CharSequence[exts.size()]); for (CharSequence s : extsStrings) { @@ -165,16 +143,18 @@ public class FileTypeAssocTable { @Nullable public T findAssociatedFileType(@NotNull @NonNls CharSequence fileName) { - T t = myExactFileNameMappings.get(fileName); - if (t != null) return t; + if (!myExactFileNameMappings.isEmpty()) { + T t = myExactFileNameMappings.get(fileName); + if (t != null) return t; + } - if (myHasAnyCaseExactMappings) { // even hash lookup with case insensitive hasher is costly for isIgnored checks during compile - t = myExactFileNameAnyCaseMappings.get(fileName); + if (!myExactFileNameAnyCaseMappings.isEmpty()) { // even hash lookup with case insensitive hasher is costly for isIgnored checks during compile + T t = myExactFileNameAnyCaseMappings.get(fileName); if (t != null) return t; } //noinspection ForLoopReplaceableByForEach - for (int i = 0, n = myMatchingMappings.size(); i < n; i++) { + for (int i = 0; i < myMatchingMappings.size(); i++) { final Pair mapping = myMatchingMappings.get(i); if (FileNameMatcherEx.acceptsCharSequence(mapping.getFirst(), fileName)) return mapping.getSecond(); } @@ -183,7 +163,7 @@ public class FileTypeAssocTable { } @Nullable - public T findAssociatedFileType(final FileNameMatcher matcher) { + public T findAssociatedFileType(@NotNull FileNameMatcher matcher) { if (matcher instanceof ExtensionFileNameMatcher) { return myExtensionMappings.get(((ExtensionFileNameMatcher)matcher).getExtension()); } @@ -191,11 +171,8 @@ public class FileTypeAssocTable { if (matcher instanceof ExactFileNameMatcher) { final ExactFileNameMatcher exactFileNameMatcher = (ExactFileNameMatcher)matcher; - if (exactFileNameMatcher.isIgnoreCase()) { - return myExactFileNameAnyCaseMappings.get(exactFileNameMatcher.getFileName()); - } else { - return myExactFileNameMappings.get(exactFileNameMatcher.getFileName()); - } + Map mapToUse = exactFileNameMatcher.isIgnoreCase() ? myExactFileNameAnyCaseMappings : myExactFileNameMappings; + return mapToUse.get(exactFileNameMatcher.getFileName()); } for (Pair mapping : myMatchingMappings) { @@ -207,13 +184,13 @@ public class FileTypeAssocTable { @Deprecated @NotNull - public String[] getAssociatedExtensions(T type) { + public String[] getAssociatedExtensions(@NotNull T type) { Map extMap = myExtensionMappings; List exts = new ArrayList(); - for (CharSequence ext : extMap.keySet()) { - if (extMap.get(ext) == type) { - exts.add(ext.toString()); + for (Map.Entry entry : extMap.entrySet()) { + if (entry.getValue() == type) { + exts.add(entry.getKey().toString()); } } return ArrayUtil.toStringArray(exts); @@ -284,8 +261,7 @@ public class FileTypeAssocTable { } public int hashCode() { - int result; - result = myExtensionMappings.hashCode(); + int result = myExtensionMappings.hashCode(); result = 31 * result + myMatchingMappings.hashCode(); result = 31 * result + myExactFileNameMappings.hashCode(); result = 31 * result + myExactFileNameAnyCaseMappings.hashCode(); From d447dcb94d43c1b3cccaf9404a04cbb111fff1c2 Mon Sep 17 00:00:00 2001 From: Alexey Kudravtsev Date: Thu, 2 Jul 2015 15:12:27 +0300 Subject: [PATCH 15/39] optimisation: double check locking in calcStubTree() --- .../intellij/psi/impl/source/PsiFileImpl.java | 16 ++++++++++------ 1 file changed, 10 insertions(+), 6 deletions(-) diff --git a/platform/core-impl/src/com/intellij/psi/impl/source/PsiFileImpl.java b/platform/core-impl/src/com/intellij/psi/impl/source/PsiFileImpl.java index f6e67bf8202b..d09441aa7540 100644 --- a/platform/core-impl/src/com/intellij/psi/impl/source/PsiFileImpl.java +++ b/platform/core-impl/src/com/intellij/psi/impl/source/PsiFileImpl.java @@ -1,5 +1,5 @@ /* - * Copyright 2000-2014 JetBrains s.r.o. + * Copyright 2000-2015 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. @@ -68,7 +68,7 @@ public abstract class PsiFileImpl extends ElementBase implements PsiFileEx, PsiF protected IElementType myContentElementType; private long myModificationStamp; - protected PsiFile myOriginalFile = null; + protected PsiFile myOriginalFile; private final FileViewProvider myViewProvider; private volatile Reference myStub; private boolean myInvalidated; @@ -555,7 +555,7 @@ public abstract class PsiFileImpl extends ElementBase implements PsiFileEx, PsiF } private static final Comparator FILE_BY_LANGUAGE_ID = new Comparator() { @Override - public int compare(PsiFile o1, PsiFile o2) { + public int compare(@NotNull PsiFile o1, @NotNull PsiFile o2) { return o1.getLanguage().getID().compareTo(o2.getLanguage().getID()); } }; @@ -944,14 +944,18 @@ public abstract class PsiFileImpl extends ElementBase implements PsiFileEx, PsiF return this == another; } - private static final Key> STUB_TREE_IN_PARSED_TREE = Key.create("STUB_TREE_IN_PARSED_TREE"); + private static final Key> STUB_TREE_IN_PARSED_TREE = Key.create("STUB_TREE_IN_PARSED_TREE"); private final Object myStubFromTreeLock = new Object(); + @NotNull public StubTree calcStubTree() { FileElement fileElement = calcTreeElement(); + StubTree tree = SoftReference.dereference(fileElement.getUserData(STUB_TREE_IN_PARSED_TREE)); + if (tree != null) { + return tree; + } synchronized (myStubFromTreeLock) { - SoftReference ref = fileElement.getUserData(STUB_TREE_IN_PARSED_TREE); - StubTree tree = SoftReference.dereference(ref); + tree = SoftReference.dereference(fileElement.getUserData(STUB_TREE_IN_PARSED_TREE)); if (tree == null) { ApplicationManager.getApplication().assertReadAccessAllowed(); From 498526c4748a831c03be317ab6200629e42fc8a3 Mon Sep 17 00:00:00 2001 From: Alexey Kudravtsev Date: Thu, 2 Jul 2015 17:17:22 +0300 Subject: [PATCH 16/39] removed equals() because we can't make it symmetric --- .../src/com/intellij/util/text/ByteArrayCharSequence.java | 6 ------ 1 file changed, 6 deletions(-) diff --git a/platform/util/src/com/intellij/util/text/ByteArrayCharSequence.java b/platform/util/src/com/intellij/util/text/ByteArrayCharSequence.java index c417c3628075..8baeb95a4295 100644 --- a/platform/util/src/com/intellij/util/text/ByteArrayCharSequence.java +++ b/platform/util/src/com/intellij/util/text/ByteArrayCharSequence.java @@ -15,7 +15,6 @@ */ package com.intellij.util.text; -import com.intellij.openapi.util.text.StringUtil; import org.jetbrains.annotations.NotNull; public class ByteArrayCharSequence implements CharSequence { @@ -40,11 +39,6 @@ public class ByteArrayCharSequence implements CharSequence { return h; } - @Override - public boolean equals(Object obj) { - return obj instanceof CharSequence && StringUtil.equals(this, (CharSequence)obj); - } - @Override public final int length() { return myChars.length; From ed75bf2f4a227b4526f62013a1ac848609103716 Mon Sep 17 00:00:00 2001 From: Alexey Kudravtsev Date: Fri, 3 Jul 2015 12:44:30 +0300 Subject: [PATCH 17/39] test performance: disable listening of every document change --- .../intellij/openapi/vcs/changes/ChangeListManagerImpl.java | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/platform/vcs-impl/src/com/intellij/openapi/vcs/changes/ChangeListManagerImpl.java b/platform/vcs-impl/src/com/intellij/openapi/vcs/changes/ChangeListManagerImpl.java index fa4c6b6601a7..4158ca1ec747 100644 --- a/platform/vcs-impl/src/com/intellij/openapi/vcs/changes/ChangeListManagerImpl.java +++ b/platform/vcs-impl/src/com/intellij/openapi/vcs/changes/ChangeListManagerImpl.java @@ -279,9 +279,9 @@ public class ChangeListManagerImpl extends ChangeListManagerEx implements Projec vcsManager.addVcsListener(myVcsListener); } }); - } - myConflictTracker.startTracking(); + myConflictTracker.startTracking(); + } } private void broadcastStateAfterLoad() { From 6b9ef95f6cddbdc60436bcd8e2047f7f1d13010b Mon Sep 17 00:00:00 2001 From: Alexey Kudravtsev Date: Fri, 3 Jul 2015 12:50:56 +0300 Subject: [PATCH 18/39] optimisation: obtain all parents within one lock --- .../vfs/newvfs/persistent/FSRecords.java | 26 ++++++++ .../newvfs/persistent/PersistentFSImpl.java | 62 +++++-------------- 2 files changed, 40 insertions(+), 48 deletions(-) diff --git a/platform/platform-impl/src/com/intellij/openapi/vfs/newvfs/persistent/FSRecords.java b/platform/platform-impl/src/com/intellij/openapi/vfs/newvfs/persistent/FSRecords.java index 363a3180b02a..b7cd888afbc5 100644 --- a/platform/platform-impl/src/com/intellij/openapi/vfs/newvfs/persistent/FSRecords.java +++ b/platform/platform-impl/src/com/intellij/openapi/vfs/newvfs/persistent/FSRecords.java @@ -1053,6 +1053,32 @@ public class FSRecords implements Forceable { } } + // returns id, parent(id), parent(parent(id)), ... rootId + @NotNull + public static TIntArrayList getParents(int id) { + TIntArrayList result = new TIntArrayList(10); + r.lock(); + try { + int parentId; + do { + result.add(id); + parentId = getRecordInt(id, PARENT_OFFSET); + if (parentId == id || result.size() % 128 == 0 && result.contains(parentId)) { + LOG.error("Cyclic parent child relations in the database. id = " + parentId); + return result; + } + id = parentId; + } while (parentId != 0); + } + catch (Throwable e) { + throw DbConnection.handleError(e); + } + finally { + r.unlock(); + } + return result; + } + public static void setParent(int id, int parent) { if (id == parent) { LOG.error("Cyclic parent/child relations"); diff --git a/platform/platform-impl/src/com/intellij/openapi/vfs/newvfs/persistent/PersistentFSImpl.java b/platform/platform-impl/src/com/intellij/openapi/vfs/newvfs/persistent/PersistentFSImpl.java index f79f148eff55..a67ed2e8290d 100644 --- a/platform/platform-impl/src/com/intellij/openapi/vfs/newvfs/persistent/PersistentFSImpl.java +++ b/platform/platform-impl/src/com/intellij/openapi/vfs/newvfs/persistent/PersistentFSImpl.java @@ -61,7 +61,7 @@ public class PersistentFSImpl extends PersistentFS implements ApplicationCompone private final ReadWriteLock myRootsLock = new ReentrantReadWriteLock(); private final Map myRoots = ContainerUtil.newTroveMap(FileUtil.PATH_HASHING_STRATEGY); - private final TIntObjectHashMap myRootsById = new TIntObjectHashMap(); + private final ConcurrentIntObjectMap myRootsById = ContainerUtil.createConcurrentIntObjectMap(); private final ConcurrentIntObjectMap myIdToDirCache = ContainerUtil.createConcurrentIntObjectMap(); private final Object myInputLock = new Object(); @@ -199,7 +199,7 @@ public class PersistentFSImpl extends PersistentFS implements ApplicationCompone return nameIds.toArray(new FSRecords.NameId[nameIds.size()]); } - public static void setChildrenCached(int id) { + private static void setChildrenCached(int id) { int flags = FSRecords.getFlags(id); FSRecords.setFlags(id, flags | CHILDREN_CACHED_FLAG, true); } @@ -311,11 +311,6 @@ public class PersistentFSImpl extends PersistentFS implements ApplicationCompone return isDirectory(getFileAttributes(getFileId(file))); } - private static int getParent(final int id) { - assert id > 0; - return FSRecords.getParent(id); - } - private static boolean namesEqual(@NotNull VirtualFileSystem fs, @NotNull CharSequence n1, CharSequence n2) { return Comparing.equal(n1, n2, fs.isCaseSensitive()); } @@ -912,9 +907,8 @@ public class PersistentFSImpl extends PersistentFS implements ApplicationCompone return null; } - boolean mark = false; - myRootsLock.writeLock().lock(); + boolean mark = false; try { VirtualFileSystemEntry root = myRoots.get(rootUrl); if (root != null) return root; @@ -962,59 +956,31 @@ public class PersistentFSImpl extends PersistentFS implements ApplicationCompone myIdToDirCache.clear(); } - private static final int DEPTH_LIMIT = 75; - @Override @Nullable public NewVirtualFile findFileById(final int id) { - return findFileById(id, false, null, 0); + return findFileById(id, false); } @Override public NewVirtualFile findFileByIdIfCached(final int id) { - return findFileById(id, true, null, 0); + return findFileById(id, true); } @Nullable - private VirtualFileSystemEntry findFileById(int id, boolean cachedOnly, TIntArrayList visited, int mask) { + private VirtualFileSystemEntry findFileById(int id, boolean cachedOnly) { VirtualFileSystemEntry cached = myIdToDirCache.get(id); if (cached != null) return cached; - if (visited != null && (visited.size() >= DEPTH_LIMIT || (mask & id) == id && visited.contains(id))) { - @NonNls String sb = "Dead loop detected in persistent FS (id=" + id + " cached-only=" + cachedOnly + "):"; - for (int i = 0; i < visited.size(); i++) { - int _id = visited.get(i); - sb += "\n " + _id + " '" + getName(_id) + "' " + - String.format("%02x", getFileAttributes(_id)) + ' ' + myIdToDirCache.containsKey(_id); - } - LOG.error(sb); - return null; - } - - int parentId = getParent(id); - if (parentId >= id) { - if (visited == null) visited = new TIntArrayList(DEPTH_LIMIT); - } - if (visited != null) visited.add(id); - - VirtualFileSystemEntry result; - if (parentId == 0) { - myRootsLock.readLock().lock(); - try { - result = myRootsById.get(id); - } - finally { - myRootsLock.readLock().unlock(); - } - } - else { - VirtualFileSystemEntry parentFile = findFileById(parentId, cachedOnly, visited, mask | id); - if (parentFile instanceof VirtualDirectoryImpl) { - result = ((VirtualDirectoryImpl)parentFile).findChildById(id, cachedOnly); - } - else { - result = null; + TIntArrayList parents = FSRecords.getParents(id); + int rootId = parents.get(parents.size() - 1); + VirtualFileSystemEntry result = myRootsById.get(rootId); + for (int i=parents.size() - 2; i>=0; i--) { + if (result == null) { + break; } + int parentId = parents.get(i); + result = ((VirtualDirectoryImpl)result).findChildById(parentId, cachedOnly); } if (result != null && result.isDirectory()) { From 2d6a711bc66f83aa186a46a58007b315872aab0a Mon Sep 17 00:00:00 2001 From: Rustam Vishnyakov Date: Fri, 3 Jul 2015 12:50:23 +0300 Subject: [PATCH 19/39] Per language wrap on typing reverted --- ...JavaLanguageCodeStyleSettingsProvider.java | 1 - .../psi/codeStyle/CodeStyleSettings.java | 36 --------- .../CodeStyleSettingsCustomizable.java | 1 - .../codeStyle/CommonCodeStyleSettings.java | 18 ----- .../options/GeneralCodeStylePanel.java | 3 - .../OptionTableWithPreviewPanel.java | 76 ------------------- .../options/codeStyle/RightMarginForm.form | 14 +--- .../options/codeStyle/RightMarginForm.java | 44 ++--------- .../codeStyle/WrappingAndBracesPanel.java | 19 ----- .../editorActions/AutoHardWrapHandler.java | 3 +- .../source/codeStyle/CodeStyleFacadeImpl.java | 7 -- .../intellij/codeStyle/CodeStyleFacade.java | 9 --- .../openapi/editor/impl/SettingsImpl.java | 2 +- .../src/messages/ApplicationBundle.properties | 1 - .../com/jetbrains/python/PyWrapTest.java | 12 +-- .../HtmlLanguageCodeStyleSettings.java | 1 - .../XmlLanguageCodeStyleSettingsProvider.java | 1 - .../com/intellij/editor/XmlEditorTest.java | 4 +- 18 files changed, 19 insertions(+), 233 deletions(-) diff --git a/java/java-impl/src/com/intellij/ide/JavaLanguageCodeStyleSettingsProvider.java b/java/java-impl/src/com/intellij/ide/JavaLanguageCodeStyleSettingsProvider.java index ae858bb077f0..78c2b78ff8d6 100644 --- a/java/java-impl/src/com/intellij/ide/JavaLanguageCodeStyleSettingsProvider.java +++ b/java/java-impl/src/com/intellij/ide/JavaLanguageCodeStyleSettingsProvider.java @@ -72,7 +72,6 @@ public class JavaLanguageCodeStyleSettingsProvider extends LanguageCodeStyleSett } else if (settingsType == SettingsType.WRAPPING_AND_BRACES_SETTINGS) { consumer.showStandardOptions("RIGHT_MARGIN", - "WRAP_ON_TYPING", "KEEP_CONTROL_STATEMENT_IN_ONE_LINE", "LINE_COMMENT_AT_FIRST_COLUMN", "BLOCK_COMMENT_AT_FIRST_COLUMN", diff --git a/platform/lang-api/src/com/intellij/psi/codeStyle/CodeStyleSettings.java b/platform/lang-api/src/com/intellij/psi/codeStyle/CodeStyleSettings.java index 8bf85e2b3e12..2b2b110514a6 100644 --- a/platform/lang-api/src/com/intellij/psi/codeStyle/CodeStyleSettings.java +++ b/platform/lang-api/src/com/intellij/psi/codeStyle/CodeStyleSettings.java @@ -266,11 +266,6 @@ public class CodeStyleSettings extends CommonCodeStyleSettings implements Clonea */ @Deprecated public int RIGHT_MARGIN = 120; - /** - * @deprecated Use isWrapOnTyping(Language) instead or setWrapOnTyping(Language,boolean) for testing purposes. - * @see #isWrapOnTyping(Language) - * @see #setWrapOnTyping(Language, boolean) - */ public boolean WRAP_WHEN_TYPING_REACHES_RIGHT_MARGIN = false; @@ -962,35 +957,4 @@ public class CodeStyleSettings extends CommonCodeStyleSettings implements Clonea public void setDefaultRightMargin(int rightMargin) { RIGHT_MARGIN = rightMargin; } - - /** - * Defines whether or not wrapping should occur when typing reaches right margin. - * @param language The language to check the option for or null for a global option. - * @return True if wrapping on right margin is enabled. - */ - public boolean isWrapOnTyping(@Nullable Language language) { - if (language != null) { - CommonCodeStyleSettings langSettings = getCommonSettings(language); - if (langSettings != null) { - if (langSettings.WRAP_ON_TYPING != WrapOnTyping.UNDEFINED.intValue) { - return langSettings.WRAP_ON_TYPING == WrapOnTyping.WRAP.intValue; - } - } - } - //noinspection deprecation - return WRAP_WHEN_TYPING_REACHES_RIGHT_MARGIN; - } - - @TestOnly - public void setWrapOnTyping(@Nullable Language language, boolean wrapOnTyping) { - if (language != null) { - CommonCodeStyleSettings langSettings = getCommonSettings(language); - if (langSettings != null) { - langSettings.WRAP_ON_TYPING = wrapOnTyping ? WrapOnTyping.WRAP.intValue : WrapOnTyping.NO_WRAP.intValue; - return; - } - } - //noinspection deprecation - WRAP_WHEN_TYPING_REACHES_RIGHT_MARGIN = wrapOnTyping; - } } diff --git a/platform/lang-api/src/com/intellij/psi/codeStyle/CodeStyleSettingsCustomizable.java b/platform/lang-api/src/com/intellij/psi/codeStyle/CodeStyleSettingsCustomizable.java index ce71e8e4a5c7..5ddf99d92b58 100644 --- a/platform/lang-api/src/com/intellij/psi/codeStyle/CodeStyleSettingsCustomizable.java +++ b/platform/lang-api/src/com/intellij/psi/codeStyle/CodeStyleSettingsCustomizable.java @@ -113,7 +113,6 @@ public interface CodeStyleSettingsCustomizable { enum WrappingOrBraceOption { RIGHT_MARGIN, - WRAP_ON_TYPING, KEEP_CONTROL_STATEMENT_IN_ONE_LINE, LINE_COMMENT_AT_FIRST_COLUMN, BLOCK_COMMENT_AT_FIRST_COLUMN, diff --git a/platform/lang-api/src/com/intellij/psi/codeStyle/CommonCodeStyleSettings.java b/platform/lang-api/src/com/intellij/psi/codeStyle/CommonCodeStyleSettings.java index 29ce4da8cd81..6c01003b365d 100644 --- a/platform/lang-api/src/com/intellij/psi/codeStyle/CommonCodeStyleSettings.java +++ b/platform/lang-api/src/com/intellij/psi/codeStyle/CommonCodeStyleSettings.java @@ -890,24 +890,6 @@ public class CommonCodeStyleSettings { public int FORCE_REARRANGE_MODE = REARRANGE_ACCORDIND_TO_DIALOG; - public enum WrapOnTyping { - UNDEFINED (-1), - NO_WRAP (0), - WRAP (1); - - public int intValue; - - WrapOnTyping(int i) { - this.intValue = i; - } - } - - /** - * Defines if wrapping should occur when typing reaches right margin. Do not refer to this field directly, use - * CodeStyleSettings.isWrapOnTyping(Language) method instead. - * @see CodeStyleSettings#isWrapOnTyping(Language) - */ - public int WRAP_ON_TYPING = WrapOnTyping.UNDEFINED.intValue; //-------------------------Indent options------------------------------------------------- public static class IndentOptions implements JDOMExternalizable, Cloneable { diff --git a/platform/lang-impl/src/com/intellij/application/options/GeneralCodeStylePanel.java b/platform/lang-impl/src/com/intellij/application/options/GeneralCodeStylePanel.java index 8722ac1fb895..c49104a10dda 100644 --- a/platform/lang-impl/src/com/intellij/application/options/GeneralCodeStylePanel.java +++ b/platform/lang-impl/src/com/intellij/application/options/GeneralCodeStylePanel.java @@ -158,7 +158,6 @@ public class GeneralCodeStylePanel extends CodeStyleAbstractPanel { settings.LINE_SEPARATOR = getSelectedLineSeparator(); settings.setDefaultRightMargin(((Number) myRightMarginSpinner.getValue()).intValue()); - //noinspection deprecation settings.WRAP_WHEN_TYPING_REACHES_RIGHT_MARGIN = myCbWrapWhenTypingReachesRightMargin.isSelected(); myIndentOptionsEditor.setEnabled(true); myIndentOptionsEditor.apply(settings, settings.OTHER_INDENT_OPTIONS); @@ -224,7 +223,6 @@ public class GeneralCodeStylePanel extends CodeStyleAbstractPanel { return true; } - //noinspection deprecation if (settings.WRAP_WHEN_TYPING_REACHES_RIGHT_MARGIN ^ myCbWrapWhenTypingReachesRightMargin.isSelected()) { return true; } @@ -281,7 +279,6 @@ public class GeneralCodeStylePanel extends CodeStyleAbstractPanel { } myRightMarginSpinner.setValue(settings.getDefaultRightMargin()); - //noinspection deprecation myCbWrapWhenTypingReachesRightMargin.setSelected(settings.WRAP_WHEN_TYPING_REACHES_RIGHT_MARGIN); myIndentOptionsEditor.reset(settings, settings.OTHER_INDENT_OPTIONS); myIndentOptionsEditor.setEnabled(true); diff --git a/platform/lang-impl/src/com/intellij/application/options/codeStyle/OptionTableWithPreviewPanel.java b/platform/lang-impl/src/com/intellij/application/options/codeStyle/OptionTableWithPreviewPanel.java index 8f9794b3793a..10fd6fc2d65c 100644 --- a/platform/lang-impl/src/com/intellij/application/options/codeStyle/OptionTableWithPreviewPanel.java +++ b/platform/lang-impl/src/com/intellij/application/options/codeStyle/OptionTableWithPreviewPanel.java @@ -31,7 +31,6 @@ import com.intellij.ui.treeStructure.treetable.TreeTableModel; import com.intellij.util.containers.ContainerUtil; import com.intellij.util.ui.AbstractTableCellEditor; import com.intellij.util.ui.ColumnInfo; -import com.intellij.util.ui.ThreeStateCheckBox; import com.intellij.util.ui.UIUtil; import gnu.trove.THashMap; import gnu.trove.THashSet; @@ -352,11 +351,6 @@ public abstract class OptionTableWithPreviewPanel extends CustomizableLanguageCo myOptions.add(new BooleanOption(null, fieldName, title, groupName, null, null)); } - protected void addOption( - @NotNull String filedName, @NotNull String title, @Nullable String groupName, int undefinedValue, int falseValue, int trueValue) { - myOptions.add(new TriStateOption(null, filedName, title, groupName, null, null, undefinedValue, falseValue, trueValue)); - } - protected void addOption(@NotNull String fieldName, @NotNull String title, @Nullable String groupName, @NotNull String[] options, @NotNull int[] values) { myOptions.add(new SelectionOption(null, fieldName, title, groupName, null, null, options, values)); @@ -437,61 +431,6 @@ public abstract class OptionTableWithPreviewPanel extends CustomizableLanguageCo } } - - private class TriStateOption extends Option { - - private int myUndefinedValue; - private int myFalseValue; - private int myTrueValue; - - public TriStateOption(@Nullable Class clazz, - @NotNull String fieldName, - @NotNull String title, - @Nullable String groupName, - @Nullable OptionAnchor anchor, - @Nullable String anchorFiledName, - int undefinedValue, - int falseValue, - int trueValue) { - super(clazz, fieldName, title, groupName, anchor, anchorFiledName); - myUndefinedValue = undefinedValue; - myFalseValue = falseValue; - myTrueValue = trueValue; - } - - @Override - public Object getValue(CodeStyleSettings settings) { - try { - int value = field.getInt(getSettings(settings)); - return getState(value); - } - catch (IllegalAccessException e) { - return null; - } - } - - @Override - public void setValue(Object value, CodeStyleSettings settings) { - try { - int intValue = - ThreeStateCheckBox.State.DONT_CARE.equals(value) ? myUndefinedValue : - ThreeStateCheckBox.State.SELECTED.equals(value) ? myTrueValue : myFalseValue; - field.setInt(getSettings(settings), intValue); - } - catch (IllegalAccessException ignored) { - } - } - - public ThreeStateCheckBox.State getState(Object value) { - if (value instanceof Integer) { - if (value.equals(myTrueValue)) return ThreeStateCheckBox.State.SELECTED; - if (value.equals(myFalseValue)) return ThreeStateCheckBox.State.NOT_SELECTED; - } - return ThreeStateCheckBox.State.DONT_CARE; - } - } - - private class SelectionOption extends Option { @NotNull final String[] options; @NotNull final int[] values; @@ -746,7 +685,6 @@ public abstract class OptionTableWithPreviewPanel extends CustomizableLanguageCo private final JCheckBox myCheckBox = new JBCheckBox(); private final JPanel myEmptyLabel = new JPanel(); private final JLabel myIntLabel = new JLabel(); - private final ThreeStateCheckBox myTriStateCheckBox = new ThreeStateCheckBox(); @NotNull @Override @@ -787,10 +725,6 @@ public abstract class OptionTableWithPreviewPanel extends CustomizableLanguageCo myIntLabel.setText(value.toString()); return myIntLabel; } - else if (value instanceof ThreeStateCheckBox.State) { - myTriStateCheckBox.setState((ThreeStateCheckBox.State)value); - return myTriStateCheckBox; - } myCheckBox.putClientProperty("JComponent.sizeVariant", "small"); myComboBox.putClientProperty("JComponent.sizeVariant", "small"); @@ -849,7 +783,6 @@ public abstract class OptionTableWithPreviewPanel extends CustomizableLanguageCo private final JCheckBox myBooleanEditor = new JBCheckBox(); private JBComboBoxTableCellEditorComponent myOptionsEditor = new JBComboBoxTableCellEditorComponent(); private MyIntOptionEditor myIntOptionsEditor = new MyIntOptionEditor(); - private ThreeStateCheckBox myTriStateOptionsEditor = new ThreeStateCheckBox(); private Component myCurrentEditor = null; private MyTreeNode myCurrentNode = null; @@ -865,7 +798,6 @@ public abstract class OptionTableWithPreviewPanel extends CustomizableLanguageCo }; myBooleanEditor.addActionListener(itemChoosen); myOptionsEditor.addActionListener(itemChoosen); - myTriStateOptionsEditor.addActionListener(itemChoosen); myBooleanEditor.putClientProperty("JComponent.sizeVariant", "small"); myOptionsEditor.putClientProperty("JComponent.sizeVariant", "small"); } @@ -887,9 +819,6 @@ public abstract class OptionTableWithPreviewPanel extends CustomizableLanguageCo else if (myCurrentEditor == myIntOptionsEditor) { return myIntOptionsEditor.getPresentableValue(); } - else if (myCurrentEditor == myTriStateOptionsEditor) { - return myTriStateOptionsEditor.getState(); - } return null; } @@ -917,11 +846,6 @@ public abstract class OptionTableWithPreviewPanel extends CustomizableLanguageCo myIntOptionsEditor.setDefaultValue(intOption.getDefaultValue()); myIntOptionsEditor.setDefaultValueText(intOption.getDefaultValueText()); } - else if (node.getKey() instanceof TriStateOption) { - TriStateOption triStateOption = (TriStateOption)node.getKey(); - myCurrentEditor = myTriStateOptionsEditor; - myTriStateOptionsEditor.setState(triStateOption.getState(node.getValue())); - } else { myCurrentEditor = myOptionsEditor; myOptionsEditor.setCell(table, row, column); diff --git a/platform/lang-impl/src/com/intellij/application/options/codeStyle/RightMarginForm.form b/platform/lang-impl/src/com/intellij/application/options/codeStyle/RightMarginForm.form index e43ff8a64b7e..6a888eae4be0 100644 --- a/platform/lang-impl/src/com/intellij/application/options/codeStyle/RightMarginForm.form +++ b/platform/lang-impl/src/com/intellij/application/options/codeStyle/RightMarginForm.form @@ -1,7 +1,7 @@

- - + + @@ -18,7 +18,7 @@ - + @@ -39,14 +39,6 @@ - - - - - - - - diff --git a/platform/lang-impl/src/com/intellij/application/options/codeStyle/RightMarginForm.java b/platform/lang-impl/src/com/intellij/application/options/codeStyle/RightMarginForm.java index 24fc397b5562..0759052ee623 100644 --- a/platform/lang-impl/src/com/intellij/application/options/codeStyle/RightMarginForm.java +++ b/platform/lang-impl/src/com/intellij/application/options/codeStyle/RightMarginForm.java @@ -16,10 +16,8 @@ package com.intellij.application.options.codeStyle; import com.intellij.lang.Language; -import com.intellij.openapi.application.ApplicationBundle; import com.intellij.psi.codeStyle.CodeStyleSettings; import com.intellij.psi.codeStyle.CommonCodeStyleSettings; -import com.intellij.util.ui.ThreeStateCheckBox; import org.jetbrains.annotations.NotNull; import javax.swing.*; @@ -45,7 +43,6 @@ public class RightMarginForm { private JTextField myRightMarginField; private JCheckBox myDefaultGeneralCheckBox; private JPanel myTopPanel; - private JCheckBox myWrapOnTypingCheckBox; private final Language myLanguage; private final int myDefaultRightMargin; @@ -80,22 +77,6 @@ public class RightMarginForm { myRightMarginField.setEnabled(false); } } - if (langSettings != settings) { - if (CommonCodeStyleSettings.WrapOnTyping.WRAP.intValue == langSettings.WRAP_ON_TYPING) { - ((ThreeStateCheckBox)myWrapOnTypingCheckBox).setState(ThreeStateCheckBox.State.SELECTED); - } - else if (CommonCodeStyleSettings.WrapOnTyping.NO_WRAP.intValue == langSettings.WRAP_ON_TYPING) { - ((ThreeStateCheckBox)myWrapOnTypingCheckBox).setState(ThreeStateCheckBox.State.NOT_SELECTED); - } - else { - ((ThreeStateCheckBox)myWrapOnTypingCheckBox).setState(ThreeStateCheckBox.State.DONT_CARE); - } - } - else { - ((ThreeStateCheckBox)myWrapOnTypingCheckBox) - .setState(settings.isWrapOnTyping(myLanguage) ? ThreeStateCheckBox.State.SELECTED : ThreeStateCheckBox.State.NOT_SELECTED); - myWrapOnTypingCheckBox.setEnabled(false); - } } public void apply(@NotNull CodeStyleSettings settings) { @@ -107,26 +88,17 @@ public class RightMarginForm { else { langSettings.RIGHT_MARGIN = getFieldRightMargin(settings.getDefaultRightMargin()); } - langSettings.WRAP_ON_TYPING = getWrapOnTypingIntValue(); } } public boolean isModified(@NotNull CodeStyleSettings settings) { CommonCodeStyleSettings langSettings = settings.getCommonSettings(myLanguage); - boolean isRightMarginChanged = - myDefaultGeneralCheckBox.isSelected() ? - langSettings.RIGHT_MARGIN >= 0 : - langSettings.RIGHT_MARGIN != getFieldRightMargin(settings.getDefaultRightMargin()); - return isRightMarginChanged || getWrapOnTypingIntValue() != langSettings.WRAP_ON_TYPING; - } - - private int getWrapOnTypingIntValue() { - ThreeStateCheckBox.State state = ((ThreeStateCheckBox)myWrapOnTypingCheckBox).getState(); - return - ThreeStateCheckBox.State.SELECTED.equals(state) ? CommonCodeStyleSettings.WrapOnTyping.WRAP.intValue : - ThreeStateCheckBox.State.NOT_SELECTED.equals(state) ? CommonCodeStyleSettings.WrapOnTyping.NO_WRAP.intValue : - CommonCodeStyleSettings.WrapOnTyping.UNDEFINED.intValue; - + if (myDefaultGeneralCheckBox.isSelected()) { + return langSettings.RIGHT_MARGIN >= 0; + } + else { + return langSettings.RIGHT_MARGIN != getFieldRightMargin(settings.getDefaultRightMargin()); + } } private int getFieldRightMargin(int fallBackValue) { @@ -145,8 +117,4 @@ public class RightMarginForm { public JPanel getTopPanel() { return myTopPanel; } - - private void createUIComponents() { - myWrapOnTypingCheckBox = new ThreeStateCheckBox(ApplicationBundle.message("wrapping.wrap.on.typing")); - } } diff --git a/platform/lang-impl/src/com/intellij/application/options/codeStyle/WrappingAndBracesPanel.java b/platform/lang-impl/src/com/intellij/application/options/codeStyle/WrappingAndBracesPanel.java index 5f92c35e61b6..098bd5b5f7aa 100644 --- a/platform/lang-impl/src/com/intellij/application/options/codeStyle/WrappingAndBracesPanel.java +++ b/platform/lang-impl/src/com/intellij/application/options/codeStyle/WrappingAndBracesPanel.java @@ -17,7 +17,6 @@ package com.intellij.application.options.codeStyle; import com.intellij.openapi.application.ApplicationBundle; import com.intellij.psi.codeStyle.CodeStyleSettings; -import com.intellij.psi.codeStyle.CommonCodeStyleSettings; import com.intellij.psi.codeStyle.LanguageCodeStyleSettingsProvider; import com.intellij.util.containers.ContainerUtil; import com.intellij.util.containers.MultiMap; @@ -59,27 +58,9 @@ public class WrappingAndBracesPanel extends OptionTableWithPreviewPanel { } } - @Override - protected void addOption(@NotNull String fieldName, - @NotNull String title, - @Nullable String groupName, - int minValue, - int maxValue, - int defaultValue, - String defaultValueText) { - super.addOption(fieldName, title, groupName, minValue, maxValue, defaultValue, defaultValueText); - if (groupName != null) { - myGroupToFields.putValue(groupName, fieldName); - } - } - @Override protected void initTables() { addOption("RIGHT_MARGIN", ApplicationBundle.message("editbox.right.margin.columns"), null, 0, 999, -1, ApplicationBundle.message("settings.code.style.default.general")); - addOption("WRAP_ON_TYPING", ApplicationBundle.message("wrapping.wrap.on.typing"), null, - CommonCodeStyleSettings.WrapOnTyping.UNDEFINED.intValue, - CommonCodeStyleSettings.WrapOnTyping.NO_WRAP.intValue, - CommonCodeStyleSettings.WrapOnTyping.WRAP.intValue); addOption("KEEP_LINE_BREAKS", ApplicationBundle.message("wrapping.keep.line.breaks"), WRAPPING_KEEP); addOption("KEEP_FIRST_COLUMN_COMMENT", ApplicationBundle.message("wrapping.keep.comment.at.first.column"), WRAPPING_KEEP); diff --git a/platform/lang-impl/src/com/intellij/codeInsight/editorActions/AutoHardWrapHandler.java b/platform/lang-impl/src/com/intellij/codeInsight/editorActions/AutoHardWrapHandler.java index 04916af5377f..6184c6741236 100644 --- a/platform/lang-impl/src/com/intellij/codeInsight/editorActions/AutoHardWrapHandler.java +++ b/platform/lang-impl/src/com/intellij/codeInsight/editorActions/AutoHardWrapHandler.java @@ -17,7 +17,6 @@ package com.intellij.codeInsight.editorActions; import com.intellij.codeInsight.template.TemplateManager; import com.intellij.formatting.FormatConstants; -import com.intellij.lang.Language; import com.intellij.openapi.util.text.StringUtil; import com.intellij.psi.formatter.WhiteSpaceFormattingStrategy; import com.intellij.ide.DataManager; @@ -48,7 +47,7 @@ public class AutoHardWrapHandler { /** * This key is used as a flag that indicates if 'auto wrap line on typing' activity is performed now. * - * @see CodeStyleSettings#isWrapOnTyping(Language) + * @see CodeStyleSettings#WRAP_WHEN_TYPING_REACHES_RIGHT_MARGIN */ public static final Key AUTO_WRAP_LINE_IN_PROGRESS_KEY = new Key("AUTO_WRAP_LINE_IN_PROGRESS"); diff --git a/platform/lang-impl/src/com/intellij/psi/impl/source/codeStyle/CodeStyleFacadeImpl.java b/platform/lang-impl/src/com/intellij/psi/impl/source/codeStyle/CodeStyleFacadeImpl.java index ea56724d4d17..81eda35222dd 100644 --- a/platform/lang-impl/src/com/intellij/psi/impl/source/codeStyle/CodeStyleFacadeImpl.java +++ b/platform/lang-impl/src/com/intellij/psi/impl/source/codeStyle/CodeStyleFacadeImpl.java @@ -74,17 +74,10 @@ public class CodeStyleFacadeImpl extends CodeStyleFacade { } @Override - @Deprecated public boolean isWrapWhenTypingReachesRightMargin() { - //noinspection deprecation return CodeStyleSettingsManager.getSettings(myProject).WRAP_WHEN_TYPING_REACHES_RIGHT_MARGIN; } - @Override - public boolean isWrapOnTyping(@Nullable Language language) { - return CodeStyleSettingsManager.getSettings(myProject).isWrapOnTyping(language); - } - @Override public int getTabSize(final FileType fileType) { return CodeStyleSettingsManager.getSettings(myProject).getTabSize(fileType); diff --git a/platform/platform-api/src/com/intellij/codeStyle/CodeStyleFacade.java b/platform/platform-api/src/com/intellij/codeStyle/CodeStyleFacade.java index c3c4c36ac0ad..0bc7ed42febb 100644 --- a/platform/platform-api/src/com/intellij/codeStyle/CodeStyleFacade.java +++ b/platform/platform-api/src/com/intellij/codeStyle/CodeStyleFacade.java @@ -56,17 +56,8 @@ public abstract class CodeStyleFacade { public abstract int getRightMargin(Language language); - /** - * @return True if wrap on typing is enabled - * @deprecated Use isWrapOnTyping(language) instead - */ public abstract boolean isWrapWhenTypingReachesRightMargin(); - @SuppressWarnings("deprecation") - public boolean isWrapOnTyping(@Nullable Language language) { - return isWrapWhenTypingReachesRightMargin(); - } - public abstract int getTabSize(final FileType fileType); public abstract boolean useTabCharacter(final FileType fileType); diff --git a/platform/platform-impl/src/com/intellij/openapi/editor/impl/SettingsImpl.java b/platform/platform-impl/src/com/intellij/openapi/editor/impl/SettingsImpl.java index 3ab014cb4344..ed14e128a804 100644 --- a/platform/platform-impl/src/com/intellij/openapi/editor/impl/SettingsImpl.java +++ b/platform/platform-impl/src/com/intellij/openapi/editor/impl/SettingsImpl.java @@ -213,7 +213,7 @@ public class SettingsImpl implements EditorSettings { public boolean isWrapWhenTypingReachesRightMargin(Project project) { return myWrapWhenTypingReachesRightMargin != null ? myWrapWhenTypingReachesRightMargin.booleanValue() : - CodeStyleFacade.getInstance(project).isWrapOnTyping(myLanguage); + CodeStyleFacade.getInstance(project).isWrapWhenTypingReachesRightMargin(); } @Override diff --git a/platform/platform-resources-en/src/messages/ApplicationBundle.properties b/platform/platform-resources-en/src/messages/ApplicationBundle.properties index 4acd697bb0f6..bd6fdca56f44 100644 --- a/platform/platform-resources-en/src/messages/ApplicationBundle.properties +++ b/platform/platform-resources-en/src/messages/ApplicationBundle.properties @@ -223,7 +223,6 @@ wrapping.long.lines=Ensure right margin is not exceeded wrapping.comments=Comments wrapping.comments.wrap.at.right.margin=Wrap at right margin wrapping.annotation.parameters=Annotation parameters -wrapping.wrap.on.typing=Wrap on typing checkbox.align.multiline.chained.methods=Chained methods checkbox.align.multiline.method.parameters=Method parameters diff --git a/python/testSrc/com/jetbrains/python/PyWrapTest.java b/python/testSrc/com/jetbrains/python/PyWrapTest.java index eac94f185dfa..4146391ea5d8 100644 --- a/python/testSrc/com/jetbrains/python/PyWrapTest.java +++ b/python/testSrc/com/jetbrains/python/PyWrapTest.java @@ -32,9 +32,9 @@ public class PyWrapTest extends PyTestCase { super.setUp(); final CodeStyleSettings settings = CodeStyleSettingsManager.getInstance(myFixture.getProject()).getCurrentSettings(); final CommonCodeStyleSettings pythonSettings = settings.getCommonSettings(PythonLanguage.getInstance()); - myOldWrap = settings.isWrapOnTyping(PythonLanguage.getInstance()); + myOldWrap = settings.WRAP_WHEN_TYPING_REACHES_RIGHT_MARGIN; myOldMargin = pythonSettings.RIGHT_MARGIN; - settings.setWrapOnTyping(PythonLanguage.getInstance(), true); + settings.WRAP_WHEN_TYPING_REACHES_RIGHT_MARGIN = true; pythonSettings.RIGHT_MARGIN = 80; } @@ -42,7 +42,7 @@ public class PyWrapTest extends PyTestCase { protected void tearDown() throws Exception { final CodeStyleSettings settings = CodeStyleSettingsManager.getInstance(myFixture.getProject()).getCurrentSettings(); final CommonCodeStyleSettings pythonSettings = settings.getCommonSettings(PythonLanguage.getInstance()); - settings.setWrapOnTyping(PythonLanguage.getInstance(), myOldWrap); + settings.WRAP_WHEN_TYPING_REACHES_RIGHT_MARGIN = myOldWrap; pythonSettings.RIGHT_MARGIN = myOldMargin; super.tearDown(); } @@ -76,9 +76,9 @@ public class PyWrapTest extends PyTestCase { final CodeStyleSettings settings = CodeStyleSettingsManager.getInstance(myFixture.getProject()).getCurrentSettings(); final CommonCodeStyleSettings pythonSettings = settings.getCommonSettings(PythonLanguage.getInstance()); int oldValue = pythonSettings.RIGHT_MARGIN; - boolean oldMarginValue = settings.isWrapOnTyping(PythonLanguage.getInstance()); + boolean oldMarginValue = settings.WRAP_WHEN_TYPING_REACHES_RIGHT_MARGIN; pythonSettings.RIGHT_MARGIN = 100; - settings.setWrapOnTyping(PythonLanguage.getInstance(), true); + settings.WRAP_WHEN_TYPING_REACHES_RIGHT_MARGIN = true; try { final String testName = "wrap/" + getTestName(true); myFixture.configureByFile(testName + ".py"); @@ -89,7 +89,7 @@ public class PyWrapTest extends PyTestCase { } finally { pythonSettings.RIGHT_MARGIN = oldValue; - settings.setWrapOnTyping(PythonLanguage.getInstance(), oldMarginValue); + settings.WRAP_WHEN_TYPING_REACHES_RIGHT_MARGIN = oldMarginValue; } } diff --git a/xml/impl/src/com/intellij/application/options/HtmlLanguageCodeStyleSettings.java b/xml/impl/src/com/intellij/application/options/HtmlLanguageCodeStyleSettings.java index 29f8d8359ce6..f84b325df90d 100644 --- a/xml/impl/src/com/intellij/application/options/HtmlLanguageCodeStyleSettings.java +++ b/xml/impl/src/com/intellij/application/options/HtmlLanguageCodeStyleSettings.java @@ -42,7 +42,6 @@ public class HtmlLanguageCodeStyleSettings extends LanguageCodeStyleSettingsProv @NotNull SettingsType settingsType) { if (settingsType == SettingsType.WRAPPING_AND_BRACES_SETTINGS) { consumer.showStandardOptions("RIGHT_MARGIN"); - consumer.showStandardOptions("WRAP_ON_TYPING"); } } diff --git a/xml/impl/src/com/intellij/application/options/XmlLanguageCodeStyleSettingsProvider.java b/xml/impl/src/com/intellij/application/options/XmlLanguageCodeStyleSettingsProvider.java index b75beb28eb5b..89311331d59b 100644 --- a/xml/impl/src/com/intellij/application/options/XmlLanguageCodeStyleSettingsProvider.java +++ b/xml/impl/src/com/intellij/application/options/XmlLanguageCodeStyleSettingsProvider.java @@ -46,7 +46,6 @@ public class XmlLanguageCodeStyleSettingsProvider extends LanguageCodeStyleSetti @NotNull SettingsType settingsType) { if (settingsType == SettingsType.WRAPPING_AND_BRACES_SETTINGS) { consumer.showStandardOptions("RIGHT_MARGIN"); - consumer.showStandardOptions("WRAP_ON_TYPING"); } } diff --git a/xml/tests/src/com/intellij/editor/XmlEditorTest.java b/xml/tests/src/com/intellij/editor/XmlEditorTest.java index 1067217f23a5..ae6ad3c47416 100644 --- a/xml/tests/src/com/intellij/editor/XmlEditorTest.java +++ b/xml/tests/src/com/intellij/editor/XmlEditorTest.java @@ -55,7 +55,7 @@ public class XmlEditorTest extends LightCodeInsightTestCase { ""); CodeStyleSettings clone = CodeStyleSettingsManager.getInstance(getProject()).getCurrentSettings().clone(); - clone.setWrapOnTyping(null, true); + clone.WRAP_WHEN_TYPING_REACHES_RIGHT_MARGIN = true; try { CodeStyleSettingsManager.getInstance(getProject()).setTemporarySettings(clone); EditorTestUtil.performTypingAction(getEditor(), 'x'); @@ -77,7 +77,7 @@ public class XmlEditorTest extends LightCodeInsightTestCase { ""); CodeStyleSettings clone = CodeStyleSettingsManager.getInstance(getProject()).getCurrentSettings().clone(); - clone.setWrapOnTyping(null, true); + clone.WRAP_WHEN_TYPING_REACHES_RIGHT_MARGIN = true; try { CodeStyleSettingsManager.getInstance(getProject()).setTemporarySettings(clone); EditorTestUtil.performTypingAction(getEditor(), '?'); From b60534b90f4b31cdfb7429598d2d7fd6845134df Mon Sep 17 00:00:00 2001 From: Dmitry Batrak Date: Fri, 3 Jul 2015 13:10:58 +0300 Subject: [PATCH 20/39] IDEA-76396, IDEA-91965 precise mouse/trackpad scrolling in editor on Mac - disable by default for now, as it doesn't work as desired anyway --- platform/util/resources/misc/registry.properties | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/platform/util/resources/misc/registry.properties b/platform/util/resources/misc/registry.properties index 90573c8892e3..ddbd89d3f954 100644 --- a/platform/util/resources/misc/registry.properties +++ b/platform/util/resources/misc/registry.properties @@ -144,7 +144,7 @@ editor.soft.wrap.force.limit.description=If document contains lines longer than editor.navigation.history.stack.size=25 editor.navigation.history.stack.size.description=Stack size limit for back/forward and last/next edit location navigation -editor.mac.smooth.scrolling=true +editor.mac.smooth.scrolling=false editor.mac.smooth.scrolling.description=Enable precise (with sub-line resolution) scrolling on Mac with mouse or trackpad ide.showIndexRebuildMessage=false From d619da839dc5217fed8bdc5db06841fe6795c812 Mon Sep 17 00:00:00 2001 From: Yaroslav Lepenkin Date: Fri, 3 Jul 2015 12:13:26 +0300 Subject: [PATCH 21/39] revert 28a13b77d1b4d98bddcf68d6f7cff321c7c641e9 due to performance problems - skip read only blocks while building formatting model (IDEA-142200, should fix adjustLineIndent performance problem) --- .../src/com/intellij/formatting/InitialInfoBuilder.java | 6 +++++- 1 file changed, 5 insertions(+), 1 deletion(-) diff --git a/platform/lang-impl/src/com/intellij/formatting/InitialInfoBuilder.java b/platform/lang-impl/src/com/intellij/formatting/InitialInfoBuilder.java index 880570ba5128..85c8235d1f02 100644 --- a/platform/lang-impl/src/com/intellij/formatting/InitialInfoBuilder.java +++ b/platform/lang-impl/src/com/intellij/formatting/InitialInfoBuilder.java @@ -203,6 +203,9 @@ class InitialInfoBuilder { if (rootBlock instanceof ReadOnlyBlockInformationProvider) { myReadOnlyBlockInformationProvider = (ReadOnlyBlockInformationProvider)rootBlock; } + if (!isInsideFormattingRanges && !myCollectAlignmentsInsideFormattingRange) { + return processSimpleBlock(rootBlock, parent, true, index, parentBlock); + } final List subBlocks = rootBlock.getSubBlocks(); if (subBlocks.isEmpty() || myReadOnlyBlockInformationProvider != null @@ -237,10 +240,11 @@ class InitialInfoBuilder { } boolean blocksMayBeOfInterest = false; - if (myPositionOfInterest != -1) { + if (myPositionOfInterest != -1 && rootBlock.getTextRange().contains(myPositionOfInterest)) { myResult.put(wrappedRootBlock, rootBlock); blocksMayBeOfInterest = true; } + final boolean blocksAreReadOnly = rootBlock instanceof ReadOnlyBlockContainer || blocksMayBeOfInterest; State state = new State(rootBlock, wrappedRootBlock, currentWrapParent, blocksAreReadOnly, rootBlockIsRightBlock); From f2a9508864674d4c08b9a0154d1e8117e28fd0fa Mon Sep 17 00:00:00 2001 From: Oleg Sukhodolsky Date: Fri, 3 Jul 2015 13:18:04 +0300 Subject: [PATCH 22/39] Helper.getFile()'s implementation requires read action --- .../intellij/execution/console/LanguageConsoleImpl.java | 8 +++++++- 1 file changed, 7 insertions(+), 1 deletion(-) diff --git a/platform/lang-impl/src/com/intellij/execution/console/LanguageConsoleImpl.java b/platform/lang-impl/src/com/intellij/execution/console/LanguageConsoleImpl.java index aa456b42b1ed..b32acf196396 100644 --- a/platform/lang-impl/src/com/intellij/execution/console/LanguageConsoleImpl.java +++ b/platform/lang-impl/src/com/intellij/execution/console/LanguageConsoleImpl.java @@ -43,6 +43,7 @@ import com.intellij.openapi.fileEditor.impl.FileEditorManagerImpl; import com.intellij.openapi.fileTypes.SyntaxHighlighter; import com.intellij.openapi.project.Project; import com.intellij.openapi.util.Comparing; +import com.intellij.openapi.util.Computable; import com.intellij.openapi.util.Disposer; import com.intellij.openapi.util.TextRange; import com.intellij.openapi.vfs.VirtualFile; @@ -550,7 +551,12 @@ public class LanguageConsoleImpl extends ConsoleViewImpl implements LanguageCons @NotNull public PsiFile getFile() { - return PsiUtilCore.getPsiFile(project, virtualFile); + return ApplicationManager.getApplication().runReadAction(new Computable() { + @Override + public PsiFile compute() { + return PsiUtilCore.getPsiFile(project, virtualFile); + } + }); } @NotNull From 2112782407dd1f2b08c48f96203bf8b3c718c0a1 Mon Sep 17 00:00:00 2001 From: Dmitry Trofimov Date: Fri, 3 Jul 2015 12:45:02 +0200 Subject: [PATCH 23/39] Profiler: use binary serialization in case of JSON (PY-16319). --- python/helpers/profiler/load_pstat.py | 17 ++++++++++++----- python/helpers/profiler/prof_io.py | 6 +++--- 2 files changed, 15 insertions(+), 8 deletions(-) diff --git a/python/helpers/profiler/load_pstat.py b/python/helpers/profiler/load_pstat.py index 53e95560d95c..a7d3755195ac 100644 --- a/python/helpers/profiler/load_pstat.py +++ b/python/helpers/profiler/load_pstat.py @@ -4,7 +4,7 @@ import pstats from prof_util import statsToResponse from _prof_imports import TSerialization -from _prof_imports import TJSONProtocol +from _prof_imports import TBinaryProtocol from _prof_imports import ProfilerResponse from _prof_imports import IS_PY3K @@ -19,13 +19,20 @@ if __name__ == '__main__': statsToResponse(stats.stats, m) - data = TSerialization.serialize(m, TJSONProtocol.TJSONProtocolFactory()) + data = TSerialization.serialize(m, TBinaryProtocol.TBinaryProtocolFactory()) + # setup stdout to write binary data to it if IS_PY3K: - data = data.decode("utf-8") + out = sys.stdout.buffer + elif sys.platform == 'win32': + import os, msvcrt + msvcrt.setmode(sys.stdout.fileno(), os.O_BINARY) + out = sys.stdout + else: + out = sys.stdout - sys.stdout.write(data) - sys.stdout.flush() + out.write(data) + out.flush() diff --git a/python/helpers/profiler/prof_io.py b/python/helpers/profiler/prof_io.py index e9f2a60ce7e0..25ca60e3ae73 100644 --- a/python/helpers/profiler/prof_io.py +++ b/python/helpers/profiler/prof_io.py @@ -1,7 +1,7 @@ import traceback from _prof_imports import TSerialization -from _prof_imports import TJSONProtocol +from _prof_imports import TBinaryProtocol from _prof_imports import ProfilerRequest from _prof_imports import IS_PY3K @@ -15,7 +15,7 @@ def send_message(sock, message): to a socket, prepended by its length packed in 4 bytes (big endian). """ - s = TSerialization.serialize(message, TJSONProtocol.TJSONProtocolFactory()) + s = TSerialization.serialize(message, TBinaryProtocol.TBinaryProtocolFactory()) packed_len = struct.pack('>L', len(s)) sock.sendall(packed_len + s) @@ -29,7 +29,7 @@ def get_message(sock, msgtype): msg_buf = socket_read_n(sock, msg_len) msg = msgtype() - TSerialization.deserialize(msg, msg_buf, TJSONProtocol.TJSONProtocolFactory()) + TSerialization.deserialize(msg, msg_buf, TBinaryProtocol.TBinaryProtocolFactory()) return msg From c47233a435005b8b09017cc9d372c012a9527eb9 Mon Sep 17 00:00:00 2001 From: Mikhail Golubev Date: Wed, 1 Jul 2015 13:41:30 +0300 Subject: [PATCH 24/39] Move several related methods for navigating PSI and AST trees from PyUtil to PyPsiUtil --- .../jetbrains/python/psi/impl/PyPsiUtils.java | 116 +++++++++++++++++- .../codeInsight/PyMethodNameTypedHandler.java | 3 +- .../fixers/PyArgumentListFixer.java | 6 +- .../smartEnter/fixers/PyClassFixer.java | 4 +- .../PyConditionalStatementPartFixer.java | 10 +- .../smartEnter/fixers/PyExceptFixer.java | 6 +- .../smartEnter/fixers/PyForPartFixer.java | 8 +- .../smartEnter/fixers/PyFunctionFixer.java | 4 +- .../fixers/PyMissingBracesFixer.java | 5 +- .../fixers/PyParameterListFixer.java | 6 +- .../PyUnconditionalStatementPartFixer.java | 5 +- .../smartEnter/fixers/PyWithFixer.java | 8 +- .../intentions/PySplitIfIntention.java | 9 +- .../python/documentation/DocStringUtil.java | 4 +- .../src/com/jetbrains/python/psi/PyUtil.java | 71 ----------- .../python/psi/impl/PyArgumentListImpl.java | 4 +- .../impl/PyAugAssignmentStatementImpl.java | 5 +- .../psi/impl/PyElementGeneratorImpl.java | 2 +- .../python/psi/impl/PyParameterListImpl.java | 2 +- 19 files changed, 159 insertions(+), 119 deletions(-) diff --git a/python/psi-api/src/com/jetbrains/python/psi/impl/PyPsiUtils.java b/python/psi-api/src/com/jetbrains/python/psi/impl/PyPsiUtils.java index 3167ffeeff22..b825956e0b7f 100644 --- a/python/psi-api/src/com/jetbrains/python/psi/impl/PyPsiUtils.java +++ b/python/psi-api/src/com/jetbrains/python/psi/impl/PyPsiUtils.java @@ -23,6 +23,7 @@ import com.intellij.openapi.util.text.StringUtil; import com.intellij.psi.*; import com.intellij.psi.stubs.StubElement; import com.intellij.psi.tree.IElementType; +import com.intellij.psi.tree.TokenSet; import com.intellij.psi.util.PsiTreeUtil; import com.intellij.psi.util.QualifiedName; import com.intellij.util.containers.ContainerUtil; @@ -58,7 +59,6 @@ public class PyPsiUtils { /** * Finds the closest comma after the element skipping any whitespaces in-between. - * @param element */ @Nullable public static PsiElement getPrevComma(@NotNull PsiElement element) { @@ -66,13 +66,36 @@ public class PyPsiUtils { return prevNode != null && prevNode.getNode().getElementType() == PyTokenTypes.COMMA ? prevNode : null; } + /** + * Finds first non-whitespace sibling before given PSI element. + */ @Nullable - public static PsiElement getPrevNonWhitespaceSibling(@NotNull PsiElement element) { + public static PsiElement getPrevNonWhitespaceSibling(@Nullable PsiElement element) { return PsiTreeUtil.skipSiblingsBackward(element, PsiWhiteSpace.class); } /** - * Finds the closest comma before the element skipping any whitespaces in-between. + * Find first non-whitespace sibling before given AST node. + */ + @Nullable + public static ASTNode getPrevNonWhitespaceSibling(@NotNull ASTNode node) { + return skipSiblingsBackward(node, TokenSet.create(TokenType.WHITE_SPACE)); + } + + /** + * Find first sibling that is neither comment, nor whitespace before given element or this element itself. + */ + @Nullable + public static PsiElement getFirstNonCommentBefore(@Nullable PsiElement start) { + PsiElement seeker = start; + while (seeker instanceof PsiWhiteSpace || seeker instanceof PsiComment) { + seeker = seeker.getPrevSibling(); + } + return seeker; + } + + /** + * Finds the closest comma after the element skipping any whitespaces in-between. */ @Nullable public static PsiElement getNextComma(@NotNull PsiElement element) { @@ -80,11 +103,32 @@ public class PyPsiUtils { return nextNode != null && nextNode.getNode().getElementType() == PyTokenTypes.COMMA ? nextNode : null; } + /** + * Finds first non-whitespace sibling after given PSI element. + */ @Nullable - public static PsiElement getNextNonWhitespaceSibling(@NotNull PsiElement element) { + public static PsiElement getNextNonWhitespaceSibling(@Nullable PsiElement element) { return PsiTreeUtil.skipSiblingsForward(element, PsiWhiteSpace.class); } + /** + * Find first non-whitespace sibling after given AST node. + */ + @Nullable + public static ASTNode getNextNonWhitespaceSibling(@NotNull ASTNode after) { + return skipSiblingsForward(after, TokenSet.create(TokenType.WHITE_SPACE)); + } + + /** + * Find first sibling that is neither comment, nor whitespace after given element or this element itself. + */ + @Nullable + public static PsiElement getFirstNonCommentAfter(@Nullable PsiElement start) { + PsiElement seeker = start; + while (seeker instanceof PsiWhiteSpace || seeker instanceof PsiComment) seeker = seeker.getNextSibling(); + return seeker; + } + /** * Finds the closest comma looking for the next comma first and then for the preceding one. */ @@ -94,6 +138,70 @@ public class PyPsiUtils { return nextComma != null ? nextComma : getPrevComma(element); } + /** + * Works similarly to {@link PsiTreeUtil#skipSiblingsForward(PsiElement, Class[])}, but for AST nodes. + */ + @Nullable + public static ASTNode skipSiblingsForward(@Nullable ASTNode node, @NotNull TokenSet types) { + if (node == null) { + return null; + } + for (ASTNode next = node.getTreeNext(); next != null; next = next.getTreeNext()) { + if (!types.contains(next.getElementType())) { + return next; + } + } + return null; + } + + /** + * Works similarly to {@link PsiTreeUtil#skipSiblingsBackward(PsiElement, Class[])}, but for AST nodes. + */ + @Nullable + public static ASTNode skipSiblingsBackward(@Nullable ASTNode node, @NotNull TokenSet types) { + if (node == null) { + return null; + } + for (ASTNode prev = node.getTreePrev(); prev != null; prev = prev.getTreePrev()) { + if (!types.contains(prev.getElementType())) { + return prev; + } + } + return null; + } + + /** + * Returns first child psi element with specified element type or {@code null} if no such element exists. + * Semantically it's the same as {@code getChildByFilter(element, TokenSet.create(type), 0)}. + * + * @param element tree parent node + * @param type element type expected + * @return child element described + */ + @Nullable + public static PsiElement getFirstChildOfType(@NotNull final PsiElement element, @NotNull PyElementType type) { + final ASTNode child = element.getNode().findChildByType(type); + return child != null ? child.getPsi() : null; + } + + /** + * Returns child element in the psi tree + * + * @param filter Types of expected child + * @param number number + * @param element tree parent node + * @return PsiElement - child psiElement + */ + @Nullable + public static PsiElement getChildByFilter(@NotNull PsiElement element, @NotNull TokenSet filter, int number) { + final ASTNode node = element.getNode(); + if (node != null) { + final ASTNode[] children = node.getChildren(filter); + return (0 <= number && number < children.length) ? children[number].getPsi() : null; + } + return null; + } + public static void addBeforeInParent(@NotNull final PsiElement anchor, @NotNull final PsiElement... newElements) { final ASTNode anchorNode = anchor.getNode(); LOG.assertTrue(anchorNode != null); diff --git a/python/src/com/jetbrains/python/codeInsight/PyMethodNameTypedHandler.java b/python/src/com/jetbrains/python/codeInsight/PyMethodNameTypedHandler.java index d2b01b388544..0d394c21bad3 100644 --- a/python/src/com/jetbrains/python/codeInsight/PyMethodNameTypedHandler.java +++ b/python/src/com/jetbrains/python/codeInsight/PyMethodNameTypedHandler.java @@ -31,6 +31,7 @@ import com.jetbrains.python.PyTokenTypes; import com.jetbrains.python.PythonFileType; import com.jetbrains.python.psi.PyFunction; import com.jetbrains.python.psi.PyUtil; +import com.jetbrains.python.psi.impl.PyPsiUtils; /** * Adds appropriate first parameter to a freshly-typed method declaration. @@ -55,7 +56,7 @@ public class PyMethodNameTypedHandler extends TypedHandlerDelegate { final ASTNode token_node = token.getNode(); if (token_node != null && token_node.getElementType() == PyTokenTypes.IDENTIFIER) { - PsiElement maybe_def = PyUtil.getFirstNonCommentBefore(token.getPrevSibling()); + PsiElement maybe_def = PyPsiUtils.getFirstNonCommentBefore(token.getPrevSibling()); if (maybe_def != null) { ASTNode def_node = maybe_def.getNode(); if (def_node != null && def_node.getElementType() == PyTokenTypes.DEF_KEYWORD) { diff --git a/python/src/com/jetbrains/python/codeInsight/editorActions/smartEnter/fixers/PyArgumentListFixer.java b/python/src/com/jetbrains/python/codeInsight/editorActions/smartEnter/fixers/PyArgumentListFixer.java index eb6a2ac58af3..8d3e022be183 100644 --- a/python/src/com/jetbrains/python/codeInsight/editorActions/smartEnter/fixers/PyArgumentListFixer.java +++ b/python/src/com/jetbrains/python/codeInsight/editorActions/smartEnter/fixers/PyArgumentListFixer.java @@ -24,7 +24,7 @@ import com.jetbrains.python.codeInsight.editorActions.smartEnter.PySmartEnterPro import com.jetbrains.python.psi.PyArgumentList; import com.jetbrains.python.psi.PyClass; import com.jetbrains.python.psi.PyDecorator; -import com.jetbrains.python.psi.PyUtil; +import com.jetbrains.python.psi.impl.PyPsiUtils; import org.jetbrains.annotations.NotNull; /** @@ -37,9 +37,9 @@ public class PyArgumentListFixer extends PyFixer { @Override public void doApply(@NotNull Editor editor, @NotNull PySmartEnterProcessor processor, @NotNull PyArgumentList arguments) throws IncorrectOperationException { - final PsiElement rBrace = PyUtil.getChildByFilter(arguments, PyTokenTypes.CLOSE_BRACES, 0); + final PsiElement rBrace = PyPsiUtils.getChildByFilter(arguments, PyTokenTypes.CLOSE_BRACES, 0); if (arguments.getParent() instanceof PyClass || arguments.getParent() instanceof PyDecorator) { - final PsiElement lBrace = PyUtil.getChildByFilter(arguments, PyTokenTypes.OPEN_BRACES, 0); + final PsiElement lBrace = PyPsiUtils.getChildByFilter(arguments, PyTokenTypes.OPEN_BRACES, 0); if (lBrace != null && rBrace == null) { final Document document = editor.getDocument(); document.insertString(arguments.getTextRange().getEndOffset(), ")"); diff --git a/python/src/com/jetbrains/python/codeInsight/editorActions/smartEnter/fixers/PyClassFixer.java b/python/src/com/jetbrains/python/codeInsight/editorActions/smartEnter/fixers/PyClassFixer.java index f75bfef2e671..b49915c23c2f 100644 --- a/python/src/com/jetbrains/python/codeInsight/editorActions/smartEnter/fixers/PyClassFixer.java +++ b/python/src/com/jetbrains/python/codeInsight/editorActions/smartEnter/fixers/PyClassFixer.java @@ -23,7 +23,7 @@ import com.jetbrains.python.PyTokenTypes; import com.jetbrains.python.codeInsight.editorActions.smartEnter.PySmartEnterProcessor; import com.jetbrains.python.psi.PyArgumentList; import com.jetbrains.python.psi.PyClass; -import com.jetbrains.python.psi.PyUtil; +import com.jetbrains.python.psi.impl.PyPsiUtils; import org.jetbrains.annotations.NotNull; import static com.jetbrains.python.psi.PyUtil.sure; @@ -40,7 +40,7 @@ public class PyClassFixer extends PyFixer { } public void doApply(@NotNull Editor editor, @NotNull PySmartEnterProcessor processor, @NotNull PyClass pyClass) throws IncorrectOperationException { - final PsiElement colon = PyUtil.getFirstChildOfType(pyClass, PyTokenTypes.COLON); + final PsiElement colon = PyPsiUtils.getFirstChildOfType(pyClass, PyTokenTypes.COLON); if (colon == null) { final PyArgumentList argList = PsiTreeUtil.getChildOfType(pyClass, PyArgumentList.class); final int colonOffset = sure(argList).getTextRange().getEndOffset(); diff --git a/python/src/com/jetbrains/python/codeInsight/editorActions/smartEnter/fixers/PyConditionalStatementPartFixer.java b/python/src/com/jetbrains/python/codeInsight/editorActions/smartEnter/fixers/PyConditionalStatementPartFixer.java index c2688a8a6358..aa2393ad38be 100644 --- a/python/src/com/jetbrains/python/codeInsight/editorActions/smartEnter/fixers/PyConditionalStatementPartFixer.java +++ b/python/src/com/jetbrains/python/codeInsight/editorActions/smartEnter/fixers/PyConditionalStatementPartFixer.java @@ -24,7 +24,7 @@ import com.jetbrains.python.PyTokenTypes; import com.jetbrains.python.codeInsight.editorActions.smartEnter.PySmartEnterProcessor; import com.jetbrains.python.psi.PyConditionalStatementPart; import com.jetbrains.python.psi.PyExpression; -import com.jetbrains.python.psi.PyUtil; +import com.jetbrains.python.psi.impl.PyPsiUtils; import org.jetbrains.annotations.NotNull; import static com.jetbrains.python.psi.PyUtil.sure; @@ -45,18 +45,18 @@ public class PyConditionalStatementPartFixer extends PyFixer { @Override public void doApply(@NotNull Editor editor, @NotNull PySmartEnterProcessor processor, @NotNull PyExceptPart exceptPart) throws IncorrectOperationException { - final PsiElement colon = PyUtil.getFirstChildOfType(exceptPart, PyTokenTypes.COLON); + final PsiElement colon = PyPsiUtils.getFirstChildOfType(exceptPart, PyTokenTypes.COLON); if (colon == null) { - final PsiElement exceptToken = PyUtil.getFirstChildOfType(exceptPart, PyTokenTypes.EXCEPT_KEYWORD); + final PsiElement exceptToken = PyPsiUtils.getFirstChildOfType(exceptPart, PyTokenTypes.EXCEPT_KEYWORD); int offset = sure(exceptToken).getTextRange().getEndOffset(); final PyExpression exceptClass = exceptPart.getExceptClass(); if (exceptClass != null) { diff --git a/python/src/com/jetbrains/python/codeInsight/editorActions/smartEnter/fixers/PyForPartFixer.java b/python/src/com/jetbrains/python/codeInsight/editorActions/smartEnter/fixers/PyForPartFixer.java index 0e9824855da2..244b55d22c77 100644 --- a/python/src/com/jetbrains/python/codeInsight/editorActions/smartEnter/fixers/PyForPartFixer.java +++ b/python/src/com/jetbrains/python/codeInsight/editorActions/smartEnter/fixers/PyForPartFixer.java @@ -21,7 +21,7 @@ import com.intellij.psi.PsiElement; import com.jetbrains.python.PyTokenTypes; import com.jetbrains.python.codeInsight.editorActions.smartEnter.PySmartEnterProcessor; import com.jetbrains.python.psi.PyForPart; -import com.jetbrains.python.psi.PyUtil; +import com.jetbrains.python.psi.impl.PyPsiUtils; import org.jetbrains.annotations.NotNull; import static com.jetbrains.python.psi.PyUtil.sure; @@ -39,16 +39,16 @@ public class PyForPartFixer extends PyFixer { @Override public void doApply(@NotNull Editor editor, @NotNull PySmartEnterProcessor processor, @NotNull PyForPart forPart) { - final PsiElement colon = PyUtil.getFirstChildOfType(forPart, PyTokenTypes.COLON); + final PsiElement colon = PyPsiUtils.getFirstChildOfType(forPart, PyTokenTypes.COLON); final Document document = editor.getDocument(); - final PsiElement forToken = PyUtil.getFirstChildOfType(forPart, PyTokenTypes.FOR_KEYWORD); + final PsiElement forToken = PyPsiUtils.getFirstChildOfType(forPart, PyTokenTypes.FOR_KEYWORD); if (colon == null) { String textToInsert = ":"; PsiElement sourceOrTarget = forPart.getSource(); PsiElement positionToInsert = sourceOrTarget; if (sourceOrTarget == null) { sourceOrTarget = forPart.getTarget(); - final PsiElement inToken = PyUtil.getFirstChildOfType(forPart, PyTokenTypes.IN_KEYWORD); + final PsiElement inToken = PyPsiUtils.getFirstChildOfType(forPart, PyTokenTypes.IN_KEYWORD); if (inToken == null) { if (sourceOrTarget == null) { positionToInsert = sure(forToken); diff --git a/python/src/com/jetbrains/python/codeInsight/editorActions/smartEnter/fixers/PyFunctionFixer.java b/python/src/com/jetbrains/python/codeInsight/editorActions/smartEnter/fixers/PyFunctionFixer.java index db3694755129..4bfead4c551b 100644 --- a/python/src/com/jetbrains/python/codeInsight/editorActions/smartEnter/fixers/PyFunctionFixer.java +++ b/python/src/com/jetbrains/python/codeInsight/editorActions/smartEnter/fixers/PyFunctionFixer.java @@ -22,7 +22,7 @@ import com.jetbrains.python.PyTokenTypes; import com.jetbrains.python.codeInsight.editorActions.smartEnter.PySmartEnterProcessor; import com.jetbrains.python.psi.PyFunction; import com.jetbrains.python.psi.PyParameterList; -import com.jetbrains.python.psi.PyUtil; +import com.jetbrains.python.psi.impl.PyPsiUtils; import org.jetbrains.annotations.NotNull; /** @@ -39,7 +39,7 @@ public class PyFunctionFixer extends PyFixer { @Override public void doApply(@NotNull Editor editor, @NotNull PySmartEnterProcessor processor, @NotNull PyFunction function) throws IncorrectOperationException { - final PsiElement colon = PyUtil.getFirstChildOfType(function, PyTokenTypes.COLON); + final PsiElement colon = PyPsiUtils.getFirstChildOfType(function, PyTokenTypes.COLON); if (!isFakeFunction(function) && colon == null) { final PyParameterList parameterList = function.getParameterList(); if (function.getNameNode() == null) { diff --git a/python/src/com/jetbrains/python/codeInsight/editorActions/smartEnter/fixers/PyMissingBracesFixer.java b/python/src/com/jetbrains/python/codeInsight/editorActions/smartEnter/fixers/PyMissingBracesFixer.java index 32a7de6a8145..ddfed4b6b923 100644 --- a/python/src/com/jetbrains/python/codeInsight/editorActions/smartEnter/fixers/PyMissingBracesFixer.java +++ b/python/src/com/jetbrains/python/codeInsight/editorActions/smartEnter/fixers/PyMissingBracesFixer.java @@ -20,6 +20,7 @@ import com.intellij.psi.PsiElement; import com.intellij.util.IncorrectOperationException; import com.jetbrains.python.codeInsight.editorActions.smartEnter.PySmartEnterProcessor; import com.jetbrains.python.psi.*; +import com.jetbrains.python.psi.impl.PyPsiUtils; import org.jetbrains.annotations.NotNull; /** @@ -37,7 +38,7 @@ public class PyMissingBracesFixer extends PyFixer { public void doApply(@NotNull Editor editor, @NotNull PySmartEnterProcessor processor, @NotNull PyElement psiElement) throws IncorrectOperationException { if (psiElement instanceof PySetLiteralExpression || psiElement instanceof PyDictLiteralExpression) { - final PsiElement lastChild = PyUtil.getFirstNonCommentBefore(psiElement.getLastChild()); + final PsiElement lastChild = PyPsiUtils.getFirstNonCommentBefore(psiElement.getLastChild()); if (lastChild != null && !"}".equals(lastChild.getText())) { editor.getDocument().insertString(lastChild.getTextRange().getEndOffset(), "}"); } @@ -45,7 +46,7 @@ public class PyMissingBracesFixer extends PyFixer { else if (psiElement instanceof PyListLiteralExpression || psiElement instanceof PySliceExpression || psiElement instanceof PySubscriptionExpression) { - final PsiElement lastChild = PyUtil.getFirstNonCommentBefore(psiElement.getLastChild()); + final PsiElement lastChild = PyPsiUtils.getFirstNonCommentBefore(psiElement.getLastChild()); if (lastChild != null && !"]".equals(lastChild.getText())) { editor.getDocument().insertString(lastChild.getTextRange().getEndOffset(), "]"); } diff --git a/python/src/com/jetbrains/python/codeInsight/editorActions/smartEnter/fixers/PyParameterListFixer.java b/python/src/com/jetbrains/python/codeInsight/editorActions/smartEnter/fixers/PyParameterListFixer.java index e4359a43c640..53dd4fab9c9d 100644 --- a/python/src/com/jetbrains/python/codeInsight/editorActions/smartEnter/fixers/PyParameterListFixer.java +++ b/python/src/com/jetbrains/python/codeInsight/editorActions/smartEnter/fixers/PyParameterListFixer.java @@ -23,7 +23,7 @@ import com.jetbrains.python.PyTokenTypes; import com.jetbrains.python.codeInsight.editorActions.smartEnter.PySmartEnterProcessor; import com.jetbrains.python.psi.PyFunction; import com.jetbrains.python.psi.PyParameterList; -import com.jetbrains.python.psi.PyUtil; +import com.jetbrains.python.psi.impl.PyPsiUtils; import org.jetbrains.annotations.NotNull; import static com.jetbrains.python.psi.PyUtil.as; @@ -42,8 +42,8 @@ public class PyParameterListFixer extends PyFixer { @Override public void doApply(@NotNull Editor editor, @NotNull PySmartEnterProcessor processor, @NotNull PyParameterList parameters) throws IncorrectOperationException { - final PsiElement lBrace = PyUtil.getChildByFilter(parameters, PyTokenTypes.OPEN_BRACES, 0); - final PsiElement rBrace = PyUtil.getChildByFilter(parameters, PyTokenTypes.CLOSE_BRACES, 0); + final PsiElement lBrace = PyPsiUtils.getChildByFilter(parameters, PyTokenTypes.OPEN_BRACES, 0); + final PsiElement rBrace = PyPsiUtils.getChildByFilter(parameters, PyTokenTypes.CLOSE_BRACES, 0); final PyFunction pyFunction = as(parameters.getParent(), PyFunction.class); if (pyFunction != null && !PyFunctionFixer.isFakeFunction(pyFunction) && (lBrace == null || rBrace == null)) { final Document document = editor.getDocument(); diff --git a/python/src/com/jetbrains/python/codeInsight/editorActions/smartEnter/fixers/PyUnconditionalStatementPartFixer.java b/python/src/com/jetbrains/python/codeInsight/editorActions/smartEnter/fixers/PyUnconditionalStatementPartFixer.java index 7885ae1e8d15..d01b4d440f16 100644 --- a/python/src/com/jetbrains/python/codeInsight/editorActions/smartEnter/fixers/PyUnconditionalStatementPartFixer.java +++ b/python/src/com/jetbrains/python/codeInsight/editorActions/smartEnter/fixers/PyUnconditionalStatementPartFixer.java @@ -22,6 +22,7 @@ import com.intellij.util.IncorrectOperationException; import com.jetbrains.python.PyTokenTypes; import com.jetbrains.python.codeInsight.editorActions.smartEnter.PySmartEnterProcessor; import com.jetbrains.python.psi.*; +import com.jetbrains.python.psi.impl.PyPsiUtils; import org.jetbrains.annotations.NotNull; import static com.jetbrains.python.psi.PyUtil.sure; @@ -41,10 +42,10 @@ public class PyUnconditionalStatementPartFixer extends PyFixer { public void doApply(@NotNull Editor editor, @NotNull PySmartEnterProcessor processor, @NotNull PyElement psiElement) throws IncorrectOperationException { if (PyUtil.instanceOf(psiElement, PyElsePart.class, PyTryPart.class, PyFinallyPart.class)) { - final PsiElement colon = PyUtil.getFirstChildOfType(psiElement, PyTokenTypes.COLON); + final PsiElement colon = PyPsiUtils.getFirstChildOfType(psiElement, PyTokenTypes.COLON); if (colon == null) { final TokenSet keywords = TokenSet.create(PyTokenTypes.ELSE_KEYWORD, PyTokenTypes.TRY_KEYWORD, PyTokenTypes.FINALLY_KEYWORD); - final PsiElement keywordToken = PyUtil.getChildByFilter(psiElement, keywords, 0); + final PsiElement keywordToken = PyPsiUtils.getChildByFilter(psiElement, keywords, 0); editor.getDocument().insertString(sure(keywordToken).getTextRange().getEndOffset(), ":"); } } diff --git a/python/src/com/jetbrains/python/codeInsight/editorActions/smartEnter/fixers/PyWithFixer.java b/python/src/com/jetbrains/python/codeInsight/editorActions/smartEnter/fixers/PyWithFixer.java index 1b179d9684a5..618f785b9d17 100644 --- a/python/src/com/jetbrains/python/codeInsight/editorActions/smartEnter/fixers/PyWithFixer.java +++ b/python/src/com/jetbrains/python/codeInsight/editorActions/smartEnter/fixers/PyWithFixer.java @@ -23,9 +23,9 @@ import com.intellij.util.IncorrectOperationException; import com.jetbrains.python.PyTokenTypes; import com.jetbrains.python.codeInsight.editorActions.smartEnter.PySmartEnterProcessor; import com.jetbrains.python.psi.PyExpression; -import com.jetbrains.python.psi.PyUtil; import com.jetbrains.python.psi.PyWithItem; import com.jetbrains.python.psi.PyWithStatement; +import com.jetbrains.python.psi.impl.PyPsiUtils; import org.jetbrains.annotations.NotNull; /** @@ -38,8 +38,8 @@ public class PyWithFixer extends PyFixer { @Override public void doApply(@NotNull Editor editor, @NotNull PySmartEnterProcessor processor, @NotNull PyWithStatement withStatement) throws IncorrectOperationException { - final PsiElement colonToken = PyUtil.getFirstChildOfType(withStatement, PyTokenTypes.COLON); - final PsiElement withToken = PyUtil.getFirstChildOfType(withStatement, PyTokenTypes.WITH_KEYWORD); + final PsiElement colonToken = PyPsiUtils.getFirstChildOfType(withStatement, PyTokenTypes.COLON); + final PsiElement withToken = PyPsiUtils.getFirstChildOfType(withStatement, PyTokenTypes.WITH_KEYWORD); final Document document = editor.getDocument(); if (colonToken == null && withToken != null) { int insertAt = withToken.getTextRange().getEndOffset(); @@ -52,7 +52,7 @@ public class PyWithFixer extends PyFixer { else { final PyExpression expression = lastItem.getExpression(); insertAt = expression.getTextRange().getEndOffset(); - final PsiElement asToken = PyUtil.getFirstChildOfType(lastItem, PyTokenTypes.AS_KEYWORD); + final PsiElement asToken = PyPsiUtils.getFirstChildOfType(lastItem, PyTokenTypes.AS_KEYWORD); if (asToken != null) { insertAt = asToken.getTextRange().getEndOffset(); final PyExpression target = lastItem.getTarget(); diff --git a/python/src/com/jetbrains/python/codeInsight/intentions/PySplitIfIntention.java b/python/src/com/jetbrains/python/codeInsight/intentions/PySplitIfIntention.java index 764e352bcf40..4425a8619244 100644 --- a/python/src/com/jetbrains/python/codeInsight/intentions/PySplitIfIntention.java +++ b/python/src/com/jetbrains/python/codeInsight/intentions/PySplitIfIntention.java @@ -26,6 +26,7 @@ import com.intellij.util.IncorrectOperationException; import com.jetbrains.python.PyBundle; import com.jetbrains.python.PyTokenTypes; import com.jetbrains.python.psi.*; +import com.jetbrains.python.psi.impl.PyPsiUtils; import org.jetbrains.annotations.NotNull; /** @@ -54,11 +55,11 @@ public class PySplitIfIntention extends BaseIntentionAction { final IElementType elementType = elementAtOffset.getNode().getElementType(); if (elementType == PyTokenTypes.COLON) { elementAtOffset = elementAtOffset.getPrevSibling(); - elementAtOffset = PyUtil.getFirstNonCommentBefore(elementAtOffset); + elementAtOffset = PyPsiUtils.getFirstNonCommentBefore(elementAtOffset); } else if (elementType == PyTokenTypes.IF_KEYWORD) { elementAtOffset = elementAtOffset.getNextSibling(); - elementAtOffset = PyUtil.getFirstNonCommentAfter(elementAtOffset); + elementAtOffset = PyPsiUtils.getFirstNonCommentAfter(elementAtOffset); } PsiElement element = PsiTreeUtil.getParentOfType(elementAtOffset, PyBinaryExpression.class, false); @@ -87,11 +88,11 @@ public class PySplitIfIntention extends BaseIntentionAction { final IElementType elementType = elementAtOffset.getNode().getElementType(); if (elementType == PyTokenTypes.COLON) { elementAtOffset = elementAtOffset.getPrevSibling(); - elementAtOffset = PyUtil.getFirstNonCommentBefore(elementAtOffset); + elementAtOffset = PyPsiUtils.getFirstNonCommentBefore(elementAtOffset); } else if (elementType == PyTokenTypes.IF_KEYWORD) { elementAtOffset = elementAtOffset.getNextSibling(); - elementAtOffset = PyUtil.getFirstNonCommentAfter(elementAtOffset); + elementAtOffset = PyPsiUtils.getFirstNonCommentAfter(elementAtOffset); } PyBinaryExpression element = PsiTreeUtil.getParentOfType(elementAtOffset, PyBinaryExpression.class, false); diff --git a/python/src/com/jetbrains/python/documentation/DocStringUtil.java b/python/src/com/jetbrains/python/documentation/DocStringUtil.java index e84ca6a0eeae..121e550ee577 100644 --- a/python/src/com/jetbrains/python/documentation/DocStringUtil.java +++ b/python/src/com/jetbrains/python/documentation/DocStringUtil.java @@ -64,8 +64,8 @@ public class DocStringUtil { @Nullable public static PyStringLiteralExpression findDocStringExpression(@Nullable PyElement parent) { if (parent != null) { - PsiElement seeker = PyUtil.getFirstNonCommentAfter(parent.getFirstChild()); - if (seeker instanceof PyExpressionStatement) seeker = PyUtil.getFirstNonCommentAfter(seeker.getFirstChild()); + PsiElement seeker = PyPsiUtils.getFirstNonCommentAfter(parent.getFirstChild()); + if (seeker instanceof PyExpressionStatement) seeker = PyPsiUtils.getFirstNonCommentAfter(seeker.getFirstChild()); if (seeker instanceof PyStringLiteralExpression) return (PyStringLiteralExpression)seeker; } return null; diff --git a/python/src/com/jetbrains/python/psi/PyUtil.java b/python/src/com/jetbrains/python/psi/PyUtil.java index 331c2d16ab70..a78999c025ac 100644 --- a/python/src/com/jetbrains/python/psi/PyUtil.java +++ b/python/src/com/jetbrains/python/psi/PyUtil.java @@ -51,7 +51,6 @@ import com.intellij.psi.codeStyle.CodeStyleSettings; import com.intellij.psi.codeStyle.CodeStyleSettingsManager; import com.intellij.psi.codeStyle.CommonCodeStyleSettings.IndentOptions; import com.intellij.psi.stubs.StubElement; -import com.intellij.psi.tree.TokenSet; import com.intellij.psi.util.PsiTreeUtil; import com.intellij.psi.util.QualifiedName; import com.intellij.ui.awt.RelativePoint; @@ -100,44 +99,6 @@ public class PyUtil { private PyUtil() { } - public static ASTNode getNextNonWhitespace(ASTNode after) { - ASTNode node = after; - do { - node = node.getTreeNext(); - } - while (isWhitespace(node)); - return node; - } - - public static ASTNode getPreviousNonWhitespace(ASTNode after) { - ASTNode node = after; - do { - node = node.getTreePrev(); - } - while (isWhitespace(node)); - return node; - } - - private static boolean isWhitespace(ASTNode node) { - return node != null && node.getElementType().equals(TokenType.WHITE_SPACE); - } - - @Nullable - public static PsiElement getFirstNonCommentAfter(PsiElement start) { - PsiElement seeker = start; - while (seeker instanceof PsiWhiteSpace || seeker instanceof PsiComment) seeker = seeker.getNextSibling(); - return seeker; - } - - @Nullable - public static PsiElement getFirstNonCommentBefore(PsiElement start) { - PsiElement seeker = start; - while (seeker instanceof PsiWhiteSpace || seeker instanceof PsiComment) { - seeker = seeker.getPrevSibling(); - } - return seeker; - } - @NotNull public static T[] getAllChildrenOfType(@NotNull PsiElement element, @NotNull Class aClass) { List result = new SmartList(); @@ -917,38 +878,6 @@ public class PyUtil { } } - /** - * Returns child element in the psi tree - * - * @param filter Types of expected child - * @param number number - * @param element tree parent node - * @return PsiElement - child psiElement - */ - @Nullable - public static PsiElement getChildByFilter(@NotNull final PsiElement element, final @NotNull TokenSet filter, final int number) { - final ASTNode node = element.getNode(); - if (node != null) { - final ASTNode[] children = node.getChildren(filter); - return (0 <= number && number < children.length) ? children[number].getPsi() : null; - } - return null; - } - - /** - * Returns first child psi element with specified element type or {@code null} if no such element exists. - * Semantically it's the same as {@code getChildByFilter(element, TokenSet.create(type), 0)}. - * - * @param element tree parent node - * @param type element type expected - * @return child element described - */ - @Nullable - public static PsiElement getFirstChildOfType(@NotNull final PsiElement element, @NotNull PyElementType type) { - final ASTNode child = element.getNode().findChildByType(type); - return child != null ? child.getPsi() : null; - } - /** * If argument is a PsiDirectory, turn it into a PsiFile that points to __init__.py in that directory. * If there's no __init__.py there, null is returned, there's no point to resolve to a dir which is not a package. diff --git a/python/src/com/jetbrains/python/psi/impl/PyArgumentListImpl.java b/python/src/com/jetbrains/python/psi/impl/PyArgumentListImpl.java index 5d46f6f60a3c..05763cbcaec2 100644 --- a/python/src/com/jetbrains/python/psi/impl/PyArgumentListImpl.java +++ b/python/src/com/jetbrains/python/psi/impl/PyArgumentListImpl.java @@ -157,7 +157,7 @@ public class PyArgumentListImpl extends PyElementImpl implements PyArgumentList } } else { - ASTNode before = PyUtil.getNextNonWhitespace(pars[0]); + ASTNode before = PyPsiUtils.getNextNonWhitespaceSibling(pars[0]); ASTNode anchorBefore; if (before != null && elementPrecedesElementsOfType(before, PythonDialectsTokenSetProvider.INSTANCE.getExpressionTokens())) { ASTNode comma = createComma(); @@ -265,7 +265,7 @@ public class PyArgumentListImpl extends PyElementImpl implements PyArgumentList break; } else if (type == PyTokenTypes.COMMA) { - ASTNode next = PyUtil.getNextNonWhitespace(node); + ASTNode next = PyPsiUtils.getNextNonWhitespaceSibling(node); if (next == null) { addArgumentLastWithoutComma(argument); } diff --git a/python/src/com/jetbrains/python/psi/impl/PyAugAssignmentStatementImpl.java b/python/src/com/jetbrains/python/psi/impl/PyAugAssignmentStatementImpl.java index bcb31b823aea..0237b648a153 100644 --- a/python/src/com/jetbrains/python/psi/impl/PyAugAssignmentStatementImpl.java +++ b/python/src/com/jetbrains/python/psi/impl/PyAugAssignmentStatementImpl.java @@ -19,11 +19,10 @@ import com.intellij.lang.ASTNode; import com.intellij.psi.PsiElement; import com.jetbrains.python.PyTokenTypes; import com.jetbrains.python.PythonDialectsTokenSetProvider; -import com.jetbrains.python.psi.PyUtil; -import org.jetbrains.annotations.NotNull; import com.jetbrains.python.psi.PyAugAssignmentStatement; import com.jetbrains.python.psi.PyElementVisitor; import com.jetbrains.python.psi.PyExpression; +import org.jetbrains.annotations.NotNull; import org.jetbrains.annotations.Nullable; /** @@ -55,6 +54,6 @@ public class PyAugAssignmentStatementImpl extends PyElementImpl implements PyAug @Nullable public PsiElement getOperation() { - return PyUtil.getChildByFilter(this, PyTokenTypes.AUG_ASSIGN_OPERATIONS, 0); + return PyPsiUtils.getChildByFilter(this, PyTokenTypes.AUG_ASSIGN_OPERATIONS, 0); } } diff --git a/python/src/com/jetbrains/python/psi/impl/PyElementGeneratorImpl.java b/python/src/com/jetbrains/python/psi/impl/PyElementGeneratorImpl.java index a1ba0b72a850..b1f36a7874a1 100644 --- a/python/src/com/jetbrains/python/psi/impl/PyElementGeneratorImpl.java +++ b/python/src/com/jetbrains/python/psi/impl/PyElementGeneratorImpl.java @@ -223,7 +223,7 @@ public class PyElementGeneratorImpl extends PyElementGenerator { exprNode.addChild(add); } else { - ASTNode next = PyUtil.getNextNonWhitespace(closingTokens[closingTokens.length - 1]); + ASTNode next = PyPsiUtils.getNextNonWhitespaceSibling(closingTokens[closingTokens.length - 1]); if (next != null) { ASTNode comma = createComma(); exprNode.addChild(comma, next); diff --git a/python/src/com/jetbrains/python/psi/impl/PyParameterListImpl.java b/python/src/com/jetbrains/python/psi/impl/PyParameterListImpl.java index f8e6dd24c7e8..0be3713cc9b7 100644 --- a/python/src/com/jetbrains/python/psi/impl/PyParameterListImpl.java +++ b/python/src/com/jetbrains/python/psi/impl/PyParameterListImpl.java @@ -75,7 +75,7 @@ public class PyParameterListImpl extends PyBaseElementImpl } } } - final ASTNode previous = PyUtil.getPreviousNonWhitespace(beforeWhat); + final ASTNode previous = PyPsiUtils.getPrevNonWhitespaceSibling(beforeWhat); PyUtil.addListNode(this, param, beforeWhat, !isLast || params.length == 0 || previous.getElementType() == PyTokenTypes.COMMA, isLast, beforeWhat.getElementType() != PyTokenTypes.RPAR); From 0b5dd584ea081a58714d6e25d9c228873bef523a Mon Sep 17 00:00:00 2001 From: Mikhail Golubev Date: Wed, 1 Jul 2015 15:06:20 +0300 Subject: [PATCH 25/39] Make non-strict behavior of getNextNonCommentSibling more clear by adding corresponding parameter --- .../jetbrains/python/psi/impl/PyPsiUtils.java | 24 ++++++++++--------- .../codeInsight/PyMethodNameTypedHandler.java | 2 +- .../PyConditionalStatementPartFixer.java | 2 +- .../fixers/PyMissingBracesFixer.java | 4 ++-- .../intentions/PySplitIfIntention.java | 8 +++---- .../python/documentation/DocStringUtil.java | 4 ++-- 6 files changed, 23 insertions(+), 21 deletions(-) diff --git a/python/psi-api/src/com/jetbrains/python/psi/impl/PyPsiUtils.java b/python/psi-api/src/com/jetbrains/python/psi/impl/PyPsiUtils.java index b825956e0b7f..9588f483e782 100644 --- a/python/psi-api/src/com/jetbrains/python/psi/impl/PyPsiUtils.java +++ b/python/psi-api/src/com/jetbrains/python/psi/impl/PyPsiUtils.java @@ -83,15 +83,15 @@ public class PyPsiUtils { } /** - * Find first sibling that is neither comment, nor whitespace before given element or this element itself. + * Find first sibling that is neither comment, nor whitespace before given element. + * @param strict prohibit returning element itself */ @Nullable - public static PsiElement getFirstNonCommentBefore(@Nullable PsiElement start) { - PsiElement seeker = start; - while (seeker instanceof PsiWhiteSpace || seeker instanceof PsiComment) { - seeker = seeker.getPrevSibling(); + public static PsiElement getPrevNonCommentSibling(@Nullable PsiElement start, boolean strict) { + if (!strict && !(start instanceof PsiWhiteSpace || start instanceof PsiComment)) { + return start; } - return seeker; + return PsiTreeUtil.skipSiblingsBackward(start, PsiWhiteSpace.class, PsiComment.class); } /** @@ -120,13 +120,15 @@ public class PyPsiUtils { } /** - * Find first sibling that is neither comment, nor whitespace after given element or this element itself. + * Find first sibling that is neither comment, nor whitespace after given element. + * @param strict prohibit returning element itself */ @Nullable - public static PsiElement getFirstNonCommentAfter(@Nullable PsiElement start) { - PsiElement seeker = start; - while (seeker instanceof PsiWhiteSpace || seeker instanceof PsiComment) seeker = seeker.getNextSibling(); - return seeker; + public static PsiElement getNextNonCommentSibling(@Nullable PsiElement start, boolean strict) { + if (!strict && !(start instanceof PsiWhiteSpace || start instanceof PsiComment)) { + return start; + } + return PsiTreeUtil.skipSiblingsForward(start, PsiWhiteSpace.class, PsiComment.class); } /** diff --git a/python/src/com/jetbrains/python/codeInsight/PyMethodNameTypedHandler.java b/python/src/com/jetbrains/python/codeInsight/PyMethodNameTypedHandler.java index 0d394c21bad3..e28a013e144e 100644 --- a/python/src/com/jetbrains/python/codeInsight/PyMethodNameTypedHandler.java +++ b/python/src/com/jetbrains/python/codeInsight/PyMethodNameTypedHandler.java @@ -56,7 +56,7 @@ public class PyMethodNameTypedHandler extends TypedHandlerDelegate { final ASTNode token_node = token.getNode(); if (token_node != null && token_node.getElementType() == PyTokenTypes.IDENTIFIER) { - PsiElement maybe_def = PyPsiUtils.getFirstNonCommentBefore(token.getPrevSibling()); + PsiElement maybe_def = PyPsiUtils.getPrevNonCommentSibling(token.getPrevSibling(), false); if (maybe_def != null) { ASTNode def_node = maybe_def.getNode(); if (def_node != null && def_node.getElementType() == PyTokenTypes.DEF_KEYWORD) { diff --git a/python/src/com/jetbrains/python/codeInsight/editorActions/smartEnter/fixers/PyConditionalStatementPartFixer.java b/python/src/com/jetbrains/python/codeInsight/editorActions/smartEnter/fixers/PyConditionalStatementPartFixer.java index aa2393ad38be..aad981d704fa 100644 --- a/python/src/com/jetbrains/python/codeInsight/editorActions/smartEnter/fixers/PyConditionalStatementPartFixer.java +++ b/python/src/com/jetbrains/python/codeInsight/editorActions/smartEnter/fixers/PyConditionalStatementPartFixer.java @@ -48,7 +48,7 @@ public class PyConditionalStatementPartFixer extends PyFixer { public void doApply(@NotNull Editor editor, @NotNull PySmartEnterProcessor processor, @NotNull PyElement psiElement) throws IncorrectOperationException { if (psiElement instanceof PySetLiteralExpression || psiElement instanceof PyDictLiteralExpression) { - final PsiElement lastChild = PyPsiUtils.getFirstNonCommentBefore(psiElement.getLastChild()); + final PsiElement lastChild = PyPsiUtils.getPrevNonCommentSibling(psiElement.getLastChild(), false); if (lastChild != null && !"}".equals(lastChild.getText())) { editor.getDocument().insertString(lastChild.getTextRange().getEndOffset(), "}"); } @@ -46,7 +46,7 @@ public class PyMissingBracesFixer extends PyFixer { else if (psiElement instanceof PyListLiteralExpression || psiElement instanceof PySliceExpression || psiElement instanceof PySubscriptionExpression) { - final PsiElement lastChild = PyPsiUtils.getFirstNonCommentBefore(psiElement.getLastChild()); + final PsiElement lastChild = PyPsiUtils.getPrevNonCommentSibling(psiElement.getLastChild(), false); if (lastChild != null && !"]".equals(lastChild.getText())) { editor.getDocument().insertString(lastChild.getTextRange().getEndOffset(), "]"); } diff --git a/python/src/com/jetbrains/python/codeInsight/intentions/PySplitIfIntention.java b/python/src/com/jetbrains/python/codeInsight/intentions/PySplitIfIntention.java index 4425a8619244..4efc1ab0625b 100644 --- a/python/src/com/jetbrains/python/codeInsight/intentions/PySplitIfIntention.java +++ b/python/src/com/jetbrains/python/codeInsight/intentions/PySplitIfIntention.java @@ -55,11 +55,11 @@ public class PySplitIfIntention extends BaseIntentionAction { final IElementType elementType = elementAtOffset.getNode().getElementType(); if (elementType == PyTokenTypes.COLON) { elementAtOffset = elementAtOffset.getPrevSibling(); - elementAtOffset = PyPsiUtils.getFirstNonCommentBefore(elementAtOffset); + elementAtOffset = PyPsiUtils.getPrevNonCommentSibling(elementAtOffset, false); } else if (elementType == PyTokenTypes.IF_KEYWORD) { elementAtOffset = elementAtOffset.getNextSibling(); - elementAtOffset = PyPsiUtils.getFirstNonCommentAfter(elementAtOffset); + elementAtOffset = PyPsiUtils.getNextNonCommentSibling(elementAtOffset, false); } PsiElement element = PsiTreeUtil.getParentOfType(elementAtOffset, PyBinaryExpression.class, false); @@ -88,11 +88,11 @@ public class PySplitIfIntention extends BaseIntentionAction { final IElementType elementType = elementAtOffset.getNode().getElementType(); if (elementType == PyTokenTypes.COLON) { elementAtOffset = elementAtOffset.getPrevSibling(); - elementAtOffset = PyPsiUtils.getFirstNonCommentBefore(elementAtOffset); + elementAtOffset = PyPsiUtils.getPrevNonCommentSibling(elementAtOffset, false); } else if (elementType == PyTokenTypes.IF_KEYWORD) { elementAtOffset = elementAtOffset.getNextSibling(); - elementAtOffset = PyPsiUtils.getFirstNonCommentAfter(elementAtOffset); + elementAtOffset = PyPsiUtils.getNextNonCommentSibling(elementAtOffset, false); } PyBinaryExpression element = PsiTreeUtil.getParentOfType(elementAtOffset, PyBinaryExpression.class, false); diff --git a/python/src/com/jetbrains/python/documentation/DocStringUtil.java b/python/src/com/jetbrains/python/documentation/DocStringUtil.java index 121e550ee577..001d2c5070f0 100644 --- a/python/src/com/jetbrains/python/documentation/DocStringUtil.java +++ b/python/src/com/jetbrains/python/documentation/DocStringUtil.java @@ -64,8 +64,8 @@ public class DocStringUtil { @Nullable public static PyStringLiteralExpression findDocStringExpression(@Nullable PyElement parent) { if (parent != null) { - PsiElement seeker = PyPsiUtils.getFirstNonCommentAfter(parent.getFirstChild()); - if (seeker instanceof PyExpressionStatement) seeker = PyPsiUtils.getFirstNonCommentAfter(seeker.getFirstChild()); + PsiElement seeker = PyPsiUtils.getNextNonCommentSibling(parent.getFirstChild(), false); + if (seeker instanceof PyExpressionStatement) seeker = PyPsiUtils.getNextNonCommentSibling(seeker.getFirstChild(), false); if (seeker instanceof PyStringLiteralExpression) return (PyStringLiteralExpression)seeker; } return null; From 51bd7a6e974a77819ae8088f59f015a71c594f26 Mon Sep 17 00:00:00 2001 From: Mikhail Golubev Date: Wed, 1 Jul 2015 15:16:01 +0300 Subject: [PATCH 26/39] Methods to find significant leaf elements in PyPsiUtil have consistent names --- .../jetbrains/python/psi/impl/PyPsiUtils.java | 48 +++++++++++-------- .../extractmethod/PyExtractMethodHandler.java | 6 +-- 2 files changed, 31 insertions(+), 23 deletions(-) diff --git a/python/psi-api/src/com/jetbrains/python/psi/impl/PyPsiUtils.java b/python/psi-api/src/com/jetbrains/python/psi/impl/PyPsiUtils.java index 9588f483e782..36809880d92b 100644 --- a/python/psi-api/src/com/jetbrains/python/psi/impl/PyPsiUtils.java +++ b/python/psi-api/src/com/jetbrains/python/psi/impl/PyPsiUtils.java @@ -75,7 +75,7 @@ public class PyPsiUtils { } /** - * Find first non-whitespace sibling before given AST node. + * Finds first non-whitespace sibling before given AST node. */ @Nullable public static ASTNode getPrevNonWhitespaceSibling(@NotNull ASTNode node) { @@ -83,7 +83,7 @@ public class PyPsiUtils { } /** - * Find first sibling that is neither comment, nor whitespace before given element. + * Finds first sibling that is neither comment, nor whitespace before given element. * @param strict prohibit returning element itself */ @Nullable @@ -112,7 +112,7 @@ public class PyPsiUtils { } /** - * Find first non-whitespace sibling after given AST node. + * Finds first non-whitespace sibling after given AST node. */ @Nullable public static ASTNode getNextNonWhitespaceSibling(@NotNull ASTNode after) { @@ -120,7 +120,7 @@ public class PyPsiUtils { } /** - * Find first sibling that is neither comment, nor whitespace after given element. + * Finds first sibling that is neither comment, nor whitespace after given element. * @param strict prohibit returning element itself */ @Nullable @@ -131,6 +131,30 @@ public class PyPsiUtils { return PsiTreeUtil.skipSiblingsForward(start, PsiWhiteSpace.class, PsiComment.class); } + /** + * Finds first token after given element that doesn't consist solely of spaces and is not empty (e.g. error marker). + * @param ignoreComments ignore commentaries as well + */ + @Nullable + public static PsiElement getNextSignificantLeaf(@Nullable PsiElement element, boolean ignoreComments) { + while (element != null && StringUtil.isEmptyOrSpaces(element.getText()) || ignoreComments && element instanceof PsiComment) { + element = PsiTreeUtil.nextLeaf(element); + } + return element; + } + + /** + * Finds first token before given element that doesn't consist solely of spaces and is not empty (e.g. error marker). + * @param ignoreComments ignore commentaries as well + */ + @Nullable + public static PsiElement getPrevSignificantLeaf(@Nullable PsiElement element, boolean ignoreComments) { + while (element != null && StringUtil.isEmptyOrSpaces(element.getText()) || ignoreComments && element instanceof PsiComment) { + element = PsiTreeUtil.prevLeaf(element); + } + return element; + } + /** * Finds the closest comma looking for the next comma first and then for the preceding one. */ @@ -436,22 +460,6 @@ public class PyPsiUtils { return result; } - @Nullable - public static PsiElement getSignificantToTheRight(PsiElement element, final boolean ignoreComments) { - while (element != null && StringUtil.isEmptyOrSpaces(element.getText()) || ignoreComments && element instanceof PsiComment) { - element = PsiTreeUtil.nextLeaf(element); - } - return element; - } - - @Nullable - public static PsiElement getSignificantToTheLeft(PsiElement element, final boolean ignoreComments) { - while (element != null && StringUtil.isEmptyOrSpaces(element.getText()) || ignoreComments && element instanceof PsiComment) { - element = PsiTreeUtil.prevLeaf(element); - } - return element; - } - public static int findArgumentIndex(PyCallExpression call, PsiElement argument) { final PyExpression[] args = call.getArguments(); for (int i = 0; i < args.length; i++) { diff --git a/python/src/com/jetbrains/python/refactoring/extractmethod/PyExtractMethodHandler.java b/python/src/com/jetbrains/python/refactoring/extractmethod/PyExtractMethodHandler.java index ac92a559d076..18d4d861e162 100644 --- a/python/src/com/jetbrains/python/refactoring/extractmethod/PyExtractMethodHandler.java +++ b/python/src/com/jetbrains/python/refactoring/extractmethod/PyExtractMethodHandler.java @@ -75,8 +75,8 @@ public class PyExtractMethodHandler implements RefactoringActionHandler { } } // Pass comments and whitespaces - element1 = PyPsiUtils.getSignificantToTheRight(element1, false); - element2 = PyPsiUtils.getSignificantToTheLeft(element2, false); + element1 = PyPsiUtils.getNextSignificantLeaf(element1, false); + element2 = PyPsiUtils.getPrevSignificantLeaf(element2, false); if (element1 == null || element2 == null) { CommonRefactoringUtil.showErrorHint(project, editor, PyBundle.message("refactoring.extract.method.error.bad.selection"), @@ -158,7 +158,7 @@ public class PyExtractMethodHandler implements RefactoringActionHandler { // return elements if they are really first and last elements of statements if (element1 == PsiTreeUtil.getDeepestFirst(statement1) && - element2 == PyPsiUtils.getSignificantToTheLeft(PsiTreeUtil.getDeepestLast(statement2), !(element2 instanceof PsiComment))) { + element2 == PyPsiUtils.getPrevSignificantLeaf(PsiTreeUtil.getDeepestLast(statement2), !(element2 instanceof PsiComment))) { return Couple.of(statement1, statement2); } return null; From ff8fd970287cc9dba49f025ce3c5722dbba7ff80 Mon Sep 17 00:00:00 2001 From: "Vassiliy.Kudryashov" Date: Fri, 3 Jul 2015 14:48:09 +0300 Subject: [PATCH 27/39] IDEA-137539 Minimized editor tab is not bring up to front (remains minimized) when navigate to this file/class --- .../src/com/intellij/openapi/wm/impl/FocusManagerImpl.java | 6 +++++- 1 file changed, 5 insertions(+), 1 deletion(-) diff --git a/platform/platform-impl/src/com/intellij/openapi/wm/impl/FocusManagerImpl.java b/platform/platform-impl/src/com/intellij/openapi/wm/impl/FocusManagerImpl.java index 6d4ce72c0e80..24bac1bb79ff 100644 --- a/platform/platform-impl/src/com/intellij/openapi/wm/impl/FocusManagerImpl.java +++ b/platform/platform-impl/src/com/intellij/openapi/wm/impl/FocusManagerImpl.java @@ -985,7 +985,11 @@ public class FocusManagerImpl extends IdeFocusManager implements Disposable { @Override public void run() { if (ApplicationManager.getApplication().isActive()) { - window.toFront(); + if (window instanceof JFrame && ((JFrame)window).getState() == Frame.ICONIFIED) { + ((JFrame)window).setState(Frame.NORMAL); + } else { + window.toFront(); + } } } }); From 51404269ffa8e84e29aae9989e2a6a033f77f8bc Mon Sep 17 00:00:00 2001 From: Anna Kozlova Date: Thu, 2 Jul 2015 21:00:32 +0300 Subject: [PATCH 28/39] ensure left expression is processed before right in assignments (IDEA-140772) --- .../psi/controlFlow/ControlFlowAnalyzer.java | 13 ++++++++----- .../advHighlighting6/InitializedBeforeUsed.java | 7 +++++++ .../daemon/LightAdvHighlightingJdk6Test.java | 4 ++++ 3 files changed, 19 insertions(+), 5 deletions(-) create mode 100644 java/java-tests/testData/codeInsight/daemonCodeAnalyzer/advHighlighting6/InitializedBeforeUsed.java diff --git a/java/java-psi-impl/src/com/intellij/psi/controlFlow/ControlFlowAnalyzer.java b/java/java-psi-impl/src/com/intellij/psi/controlFlow/ControlFlowAnalyzer.java index b8f810611201..e75e488f83ea 100644 --- a/java/java-psi-impl/src/com/intellij/psi/controlFlow/ControlFlowAnalyzer.java +++ b/java/java-psi-impl/src/com/intellij/psi/controlFlow/ControlFlowAnalyzer.java @@ -1262,13 +1262,12 @@ class ControlFlowAnalyzer extends JavaElementVisitor { myStartStatementStack.pushStatement(expression.getRExpression() == null ? expression : expression.getRExpression(), false); myEndStatementStack.pushStatement(expression.getRExpression() == null ? expression : expression.getRExpression(), false); - PsiExpression rExpr = expression.getRExpression(); - if (rExpr != null) { - rExpr.accept(this); - } - PsiExpression lExpr = PsiUtil.skipParenthesizedExprDown(expression.getLExpression()); if (lExpr instanceof PsiReferenceExpression) { + PsiExpression rExpr = expression.getRExpression(); + if (rExpr != null) { + rExpr.accept(this); + } final PsiReferenceExpression referenceExpression = (PsiReferenceExpression)lExpr; PsiExpression qualifierExpression = referenceExpression.getQualifierExpression(); PsiVariable variable = getUsedVariable(referenceExpression); @@ -1293,6 +1292,10 @@ class ControlFlowAnalyzer extends JavaElementVisitor { } else if (lExpr != null) { lExpr.accept(this); + PsiExpression rExpr = expression.getRExpression(); + if (rExpr != null) { + rExpr.accept(this); + } } myStartStatementStack.popStatement(); diff --git a/java/java-tests/testData/codeInsight/daemonCodeAnalyzer/advHighlighting6/InitializedBeforeUsed.java b/java/java-tests/testData/codeInsight/daemonCodeAnalyzer/advHighlighting6/InitializedBeforeUsed.java new file mode 100644 index 000000000000..5a19cfc08e73 --- /dev/null +++ b/java/java-tests/testData/codeInsight/daemonCodeAnalyzer/advHighlighting6/InitializedBeforeUsed.java @@ -0,0 +1,7 @@ +class Test { + public static void main(String[] args) { + int i; + int[] iA = {10,20}; + iA[i] = i = 30; + } +} \ No newline at end of file diff --git a/java/java-tests/testSrc/com/intellij/codeInsight/daemon/LightAdvHighlightingJdk6Test.java b/java/java-tests/testSrc/com/intellij/codeInsight/daemon/LightAdvHighlightingJdk6Test.java index cf8747722551..bd55b8cab5e4 100644 --- a/java/java-tests/testSrc/com/intellij/codeInsight/daemon/LightAdvHighlightingJdk6Test.java +++ b/java/java-tests/testSrc/com/intellij/codeInsight/daemon/LightAdvHighlightingJdk6Test.java @@ -63,4 +63,8 @@ public class LightAdvHighlightingJdk6Test extends LightDaemonAnalyzerTestCase { public void testAgentPremain() { doTest(false, false); } + + public void testInitializedBeforeUsed() throws Exception { + doTest(false, false); + } } From 2bae1e2e6a0440b2d865d908e51b127441e15006 Mon Sep 17 00:00:00 2001 From: Anna Kozlova Date: Fri, 3 Jul 2015 12:39:00 +0300 Subject: [PATCH 29/39] introduce 'Java' group for intentions (IDEA-142046) --- RegExpSupport/src/META-INF/RegExpPlugin.xml | 2 +- .../src/META-INF/TypeMigration.xml | 6 +- .../siyeh/IntentionPowerPackBundle.properties | 28 ++--- plugins/java-i18n/src/META-INF/plugin.xml | 2 +- resources/src/META-INF/IdeaPlugin.xml | 106 +++++++++--------- 5 files changed, 72 insertions(+), 72 deletions(-) diff --git a/RegExpSupport/src/META-INF/RegExpPlugin.xml b/RegExpSupport/src/META-INF/RegExpPlugin.xml index 3e7ce6ac9352..efb7cc128638 100644 --- a/RegExpSupport/src/META-INF/RegExpPlugin.xml +++ b/RegExpSupport/src/META-INF/RegExpPlugin.xml @@ -21,7 +21,7 @@ org.intellij.lang.regexp.intention.CheckRegExpIntentionAction - Declaration + RegExp/Declaration diff --git a/java/typeMigration/src/META-INF/TypeMigration.xml b/java/typeMigration/src/META-INF/TypeMigration.xml index b460dad4165a..8ab2163d80d3 100644 --- a/java/typeMigration/src/META-INF/TypeMigration.xml +++ b/java/typeMigration/src/META-INF/TypeMigration.xml @@ -9,15 +9,15 @@ com.intellij.refactoring.typeMigration.intentions.ConvertFieldToAtomicIntention - Concurrency + Java/Concurrency com.intellij.refactoring.typeMigration.intentions.ConvertFieldToThreadLocalIntention - Concurrency + Java/Concurrency com.intellij.refactoring.typeMigration.intentions.ChangeClassParametersIntention - Declaration + Java/Declaration diff --git a/plugins/IntentionPowerPak/src/com/siyeh/IntentionPowerPackBundle.properties b/plugins/IntentionPowerPak/src/com/siyeh/IntentionPowerPackBundle.properties index 505c62657666..ae2654d33d5b 100644 --- a/plugins/IntentionPowerPak/src/com/siyeh/IntentionPowerPackBundle.properties +++ b/plugins/IntentionPowerPak/src/com/siyeh/IntentionPowerPackBundle.properties @@ -225,20 +225,20 @@ postfix.prefix.intention.name=Replace with ''{0}'' #categories -intention.category.annotations=Annotations -intention.category.numbers=Numbers -intention.category.boolean=Boolean -intention.category.conditional.operator=Conditional Operator -intention.category.shift.operation=Shift Operation -intention.category.junit=JUnit -intention.category.declaration=Declaration -intention.category.imports=Imports -intention.category.comments=Comments -intention.category.control.flow=Control Flow -intention.category.strings=Strings -intention.category.modifiers=Modifiers -intention.category.try.statements=Try Statements -intention.category.other=Other +intention.category.annotations=Java/Annotations +intention.category.numbers=Java/Numbers +intention.category.boolean=Java/Boolean +intention.category.conditional.operator=Java/Conditional Operator +intention.category.shift.operation=Java/Shift Operation +intention.category.junit=Java/JUnit +intention.category.declaration=Java/Declaration +intention.category.imports=Java/Imports +intention.category.comments=Java/Comments +intention.category.control.flow=Java/Control Flow +intention.category.strings=Java/Strings +intention.category.modifiers=Java/Modifiers +intention.category.try.statements=Java/Try Statements +intention.category.other=Java/Other #warnings 0.is.declared.in.1.but.when.public.should.be.declared.in.a.file.named.2={0} is declared in {1} but when public should be declared in a file named {2} diff --git a/plugins/java-i18n/src/META-INF/plugin.xml b/plugins/java-i18n/src/META-INF/plugin.xml index 97432e4252e1..036ede59b81b 100644 --- a/plugins/java-i18n/src/META-INF/plugin.xml +++ b/plugins/java-i18n/src/META-INF/plugin.xml @@ -63,7 +63,7 @@ com.intellij.codeInspection.capitalization.AnnotateCapitalizationIntention - I18N + Java/I18N diff --git a/resources/src/META-INF/IdeaPlugin.xml b/resources/src/META-INF/IdeaPlugin.xml index 06d676173454..ddf7a5d0259b 100644 --- a/resources/src/META-INF/IdeaPlugin.xml +++ b/resources/src/META-INF/IdeaPlugin.xml @@ -743,205 +743,205 @@ com.intellij.codeInsight.daemon.quickFix.RedundantLambdaParameterTypeIntention - Declaration + Java/Declaration com.intellij.codeInsight.intention.impl.SplitIfAction - Control Flow + Java/Control Flow com.intellij.codeInsight.intention.impl.InvertIfConditionAction - Control Flow + Java/Control Flow com.intellij.codeInsight.intention.impl.ExtractIfConditionAction - Control Flow + Java/Control Flow com.intellij.codeInsight.daemon.impl.quickfix.RemoveRedundantElseAction - Control Flow + Java/Control Flow com.intellij.codeInsight.intention.impl.AddNotNullAnnotationIntention - Annotations + Java/Annotations AddAnnotationFix com.intellij.codeInsight.intention.impl.AddDeprecationAnnotationIntention - Annotations + Java/Annotations AddAnnotationFix com.intellij.codeInsight.intention.impl.AddNullableAnnotationIntention - Annotations + Java/Annotations AddAnnotationFix com.intellij.codeInspection.dataFlow.EditContractIntention - Annotations + Java/Annotations EditContractIntention com.intellij.codeInsight.daemon.impl.quickfix.IterateOverIterableIntention - Control Flow + Java/Control Flow com.intellij.codeInsight.intention.impl.DeannotateIntentionAction - Annotations + Java/Annotations com.intellij.codeInsight.intention.impl.CreateSwitchIntention - Control Flow + Java/Control Flow com.intellij.codeInsight.intention.impl.SwapIfStatementsIntentionAction - Control Flow + Java/Control Flow com.intellij.codeInsight.intention.impl.ConvertCompareToToEqualsIntention - Control Flow + Java/Control Flow com.intellij.codeInsight.intention.impl.CreateFieldFromParameterAction - Declaration + Java/Declaration com.intellij.codeInsight.intention.impl.AssignFieldFromParameterAction - Declaration + Java/Declaration com.intellij.codeInsight.intention.impl.BindFieldsFromParametersAction - Declaration + Java/Declaration com.intellij.codeInsight.daemon.impl.quickfix.CreateLocalVarFromInstanceofAction - Declaration + Java/Declaration com.intellij.codeInsight.daemon.impl.quickfix.CreateCastExpressionFromInstanceofAction - Declaration + Java/Declaration com.intellij.testIntegration.createTest.CreateTestAction - Declaration + Java/Declaration com.intellij.testIntegration.createTest.GenerateMissedTestsAction - Declaration + Java/Declaration com.intellij.codeInsight.intention.impl.CreateSubclassAction - Declaration + Java/Declaration com.intellij.codeInsight.intention.impl.ImplementAbstractMethodAction - Declaration + Java/Declaration com.intellij.codeInsight.intention.impl.CopyAbstractMethodImplementationAction - Declaration + Java/Declaration com.intellij.codeInsight.intention.impl.SplitDeclarationAction - Declaration + Java/Declaration com.intellij.codeInsight.intention.impl.JoinDeclarationAndAssignmentAction - Declaration + Java/Declaration com.intellij.codeInsight.intention.impl.PushConditionInCallAction - Declaration + Java/Declaration com.intellij.codeInsight.intention.impl.MoveInitializerToConstructorAction - Declaration + Java/Declaration com.intellij.testIntegration.intention.MoveInitializerToSetUpMethodAction - Declaration + Java/Declaration com.intellij.codeInsight.intention.impl.MoveFieldAssignmentToInitializerAction - Declaration + Java/Declaration com.intellij.codeInsight.daemon.impl.quickfix.AddRuntimeExceptionToThrowsAction - Declaration + Java/Declaration com.intellij.codeInsight.intention.impl.MakeTypeGenericAction - Declaration + Java/Declaration com.intellij.codeInsight.intention.impl.AddOverrideAnnotationAction - Annotations + Java/Annotations com.intellij.codeInsight.daemon.impl.quickfix.DelegateWithDefaultParamValueIntentionAction - Declaration + Java/Declaration com.intellij.codeInsight.daemon.impl.quickfix.DefineParamsDefaultValueAction - Declaration + Java/Declaration com.intellij.codeInsight.intention.impl.IntroduceVariableIntentionAction - Refactorings + Java/Refactorings com.intellij.codeInsight.intention.impl.EncapsulateFieldAction - Refactorings + Java/Refactorings com.intellij.codeInsight.intention.impl.SimplifyBooleanExpressionAction - Boolean + Java/Boolean com.intellij.codeInsight.intention.impl.ConcatenationToMessageFormatAction - I18N + Java/I18N com.intellij.codeInsight.intention.impl.ConvertToBasicLatinAction - I18N + Java/I18N com.intellij.codeInsight.intention.impl.AddOnDemandStaticImportAction - Imports + Java/Imports com.intellij.codeInsight.intention.impl.AddSingleMemberStaticImportAction - Imports + Java/Imports com.intellij.codeInsight.intention.impl.ExpandStaticImportAction - Imports + Java/Imports com.intellij.codeInspection.actions.UnimplementInterfaceAction - Declaration + Java/Declaration com.intellij.codeInspection.actions.ReplaceImplementsWithStaticImportAction - Declaration + Java/Declaration com.intellij.codeInsight.intention.impl.ConvertColorRepresentationIntentionAction - Declaration + Java/Declaration com.intellij.codeInsight.intention.impl.AddJavadocIntention - Declaration + Java/Declaration @@ -956,12 +956,12 @@ com.intellij.codeInsight.intention.impl.ReplaceCastWithVariableAction - Other + Java/Imports com.intellij.codeInsight.intention.impl.BreakStringOnLineBreaksIntentionAction - Strings + Java/Strings @@ -971,21 +971,21 @@ com.intellij.codeInsight.intention.impl.RemoveLiteralUnderscoresAction - Numbers + Java/Numbers com.intellij.codeInsight.intention.impl.InsertLiteralUnderscoresAction - Numbers + Java/Numbers com.intellij.codeInsight.daemon.impl.quickfix.ConvertToStringLiteralAction - Strings + Java/Strings com.intellij.codeInsight.intention.impl.SurroundAutoCloseableAction - Try Statements + Java/Try Statements From b27533f02e16f244b908d9ae3b85acf9bdd796ea Mon Sep 17 00:00:00 2001 From: Anna Kozlova Date: Fri, 3 Jul 2015 13:36:43 +0300 Subject: [PATCH 30/39] fix onDemand check for classes resolved to default imports like 'java.lang' (IDEA-141782) --- .../psi/impl/source/codeStyle/ImportHelper.java | 16 +++++++++++++--- .../intention/AddImportActionTest.groovy | 5 ++++- 2 files changed, 17 insertions(+), 4 deletions(-) diff --git a/java/java-impl/src/com/intellij/psi/impl/source/codeStyle/ImportHelper.java b/java/java-impl/src/com/intellij/psi/impl/source/codeStyle/ImportHelper.java index 8bb1a8daa501..e5cb7d55ed61 100644 --- a/java/java-impl/src/com/intellij/psi/impl/source/codeStyle/ImportHelper.java +++ b/java/java-impl/src/com/intellij/psi/impl/source/codeStyle/ImportHelper.java @@ -412,7 +412,7 @@ public class ImportHelper{ useOnDemand = false; } // name of class we try to import is the same as of the class defined in this file - if (curRefClass != null) { + if (containsInCurrentFile(file, curRefClass)) { useOnDemand = true; } // check conflicts @@ -428,10 +428,9 @@ public class ImportHelper{ } if (useOnDemand && - curRefClass != null && refClass.getContainingClass() != null && mySettings.INSERT_INNER_CLASS_IMPORTS && - "java.lang".equals(StringUtil.getPackageName(curRefClass.getQualifiedName()))) { + containsInCurrentFile(file, curRefClass)) { return false; } @@ -465,6 +464,17 @@ public class ImportHelper{ return true; } + private static boolean containsInCurrentFile(@NotNull PsiJavaFile file, PsiClass curRefClass) { + if (curRefClass != null) { + final String curRefClassQualifiedName = curRefClass.getQualifiedName(); + if (curRefClassQualifiedName != null && + ArrayUtil.find(file.getImplicitlyImportedPackages(), StringUtil.getPackageName(curRefClassQualifiedName)) < 0) { + return true; + } + } + return false; + } + private static void calcClassesToReimport(PsiJavaFile file, JavaPsiFacade facade, PsiResolveHelper helper, String packageName, List classesToReimport, Collection onDemandRefs) { if (onDemandRefs.isEmpty()) { diff --git a/java/java-tests/testSrc/com/intellij/codeInsight/intention/AddImportActionTest.groovy b/java/java-tests/testSrc/com/intellij/codeInsight/intention/AddImportActionTest.groovy index fd276d36590d..86f0236b88f3 100644 --- a/java/java-tests/testSrc/com/intellij/codeInsight/intention/AddImportActionTest.groovy +++ b/java/java-tests/testSrc/com/intellij/codeInsight/intention/AddImportActionTest.groovy @@ -17,8 +17,11 @@ package com.intellij.codeInsight.intention import com.intellij.lang.java.JavaLanguage; import com.intellij.pom.java.LanguageLevel +import com.intellij.psi.PsiClass +import com.intellij.psi.PsiFile import com.intellij.psi.codeStyle.CodeStyleSettings import com.intellij.psi.codeStyle.CodeStyleSettingsManager +import com.intellij.psi.impl.source.codeStyle.ImportHelper import com.intellij.testFramework.IdeaTestUtil import com.intellij.testFramework.fixtures.LightCodeInsightFixtureTestCase @@ -74,7 +77,7 @@ public class Foo { } ''' importClass() - myFixture.checkResult '''import foo.*; + myFixture.checkResult '''import foo.StringValue; public class Foo { StringValue sv; From 1a6b4ca813d6450a2e5bac3b9c22e6ec62406665 Mon Sep 17 00:00:00 2001 From: Anna Kozlova Date: Fri, 3 Jul 2015 14:54:30 +0300 Subject: [PATCH 31/39] restore coverage information for groovy files and for multiple classes in one java file (IDEA-142057) --- .../view/JavaCoverageViewExtension.java | 30 +++++++++---------- 1 file changed, 15 insertions(+), 15 deletions(-) diff --git a/plugins/coverage/src/com/intellij/coverage/view/JavaCoverageViewExtension.java b/plugins/coverage/src/com/intellij/coverage/view/JavaCoverageViewExtension.java index c6a8c108b734..99799ff40d8f 100644 --- a/plugins/coverage/src/com/intellij/coverage/view/JavaCoverageViewExtension.java +++ b/plugins/coverage/src/com/intellij/coverage/view/JavaCoverageViewExtension.java @@ -251,21 +251,7 @@ public class JavaCoverageViewExtension extends CoverageViewExtension { } }); for (final PsiFile file : childFiles) { - if (file instanceof PsiJavaFile) { - PsiClass[] classes = ApplicationManager.getApplication().runReadAction(new Computable() { - public PsiClass[] compute() { - return file.isValid() ? ((PsiJavaFile) file).getClasses() : PsiClass.EMPTY_ARRAY; - } - }); - if (classes.length > 0) { - PsiClass aClass = classes[0]; - if (!(node instanceof CoverageListRootNode) && getClassCoverageInfo(aClass) == null) continue; - children.add(new CoverageListNode(myProject, aClass, mySuitesBundle, myStateBean)); - } - } - else if (file instanceof PsiClassOwner) { - children.add(new CoverageListNode(myProject, file, mySuitesBundle, myStateBean)); - } + collectFileChildren(file, node, children); } } else if (!myStateBean.myFlattenPackages) { @@ -287,6 +273,20 @@ public class JavaCoverageViewExtension extends CoverageViewExtension { return children; } + protected void collectFileChildren(final PsiFile file, AbstractTreeNode node, List children) { + if (file instanceof PsiClassOwner) { + PsiClass[] classes = ApplicationManager.getApplication().runReadAction(new Computable() { + public PsiClass[] compute() { + return file.isValid() ? ((PsiClassOwner) file).getClasses() : PsiClass.EMPTY_ARRAY; + } + }); + for (PsiClass aClass : classes) { + if (!(node instanceof CoverageListRootNode) && getClassCoverageInfo(aClass) == null) continue; + children.add(new CoverageListNode(myProject, aClass, mySuitesBundle, myStateBean)); + } + } + } + @Nullable private PackageAnnotator.ClassCoverageInfo getClassCoverageInfo(final PsiClass aClass) { return myAnnotator.getClassCoverageInfo(ApplicationManager.getApplication().runReadAction(new NullableComputable() { From 71314005dd387b2815226605cdee3f6f98ec9c29 Mon Sep 17 00:00:00 2001 From: Daniil Ovchinnikov Date: Fri, 3 Jul 2015 14:58:05 +0300 Subject: [PATCH 32/39] [groovy] abstract collection with consumer --- .../resolve/ast/AstTransformContributor.java | 28 +++++++++++++------ .../resolve/ast/AutoCloneContributor.java | 9 +++--- .../ast/AutoExternalizeContributor.java | 10 +++---- .../ast/ConstructorAnnotationsProcessor.java | 12 ++++---- .../ast/DelegatedMethodsContributor.java | 9 ++++-- .../ast/GrInheritConstructorContributor.java | 9 +++--- .../lang/resolve/ast/LoggingContributor.java | 9 +++--- 7 files changed, 49 insertions(+), 37 deletions(-) diff --git a/plugins/groovy/groovy-psi/src/org/jetbrains/plugins/groovy/lang/resolve/ast/AstTransformContributor.java b/plugins/groovy/groovy-psi/src/org/jetbrains/plugins/groovy/lang/resolve/ast/AstTransformContributor.java index 22ddaf513fe0..206427d2eaeb 100644 --- a/plugins/groovy/groovy-psi/src/org/jetbrains/plugins/groovy/lang/resolve/ast/AstTransformContributor.java +++ b/plugins/groovy/groovy-psi/src/org/jetbrains/plugins/groovy/lang/resolve/ast/AstTransformContributor.java @@ -1,5 +1,5 @@ /* - * Copyright 2000-2014 JetBrains s.r.o. + * Copyright 2000-2015 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. @@ -19,6 +19,7 @@ import com.intellij.openapi.extensions.ExtensionPointName; import com.intellij.openapi.util.Computable; import com.intellij.openapi.util.RecursionManager; import com.intellij.psi.PsiMethod; +import com.intellij.util.Consumer; import org.jetbrains.annotations.NotNull; import org.jetbrains.plugins.groovy.lang.psi.api.statements.GrField; import org.jetbrains.plugins.groovy.lang.psi.api.statements.typedef.GrTypeDefinition; @@ -32,13 +33,14 @@ import java.util.List; * @author Max Medvedev */ public abstract class AstTransformContributor { - public static final ExtensionPointName EP_NAME = ExtensionPointName.create("org.intellij.groovy.astTransformContributor"); + public static final ExtensionPointName EP_NAME = + ExtensionPointName.create("org.intellij.groovy.astTransformContributor"); - public void collectMethods(@NotNull final GrTypeDefinition clazz, Collection collector) { + public void collectMethods(@NotNull final GrTypeDefinition clazz, Consumer collector) { } - public void collectFields(@NotNull final GrTypeDefinition clazz, Collection collector) { + public void collectFields(@NotNull final GrTypeDefinition clazz, Consumer collector) { } @@ -47,9 +49,14 @@ public abstract class AstTransformContributor { Collection result = RecursionManager.doPreventingRecursion(clazz, true, new Computable>() { @Override public Collection compute() { - Collection collector = new ArrayList(); + final Collection collector = new ArrayList(); for (final AstTransformContributor contributor : EP_NAME.getExtensions()) { - contributor.collectMethods(clazz, collector); + contributor.collectMethods(clazz, new Consumer() { + @Override + public void consume(PsiMethod method) { + collector.add(method); + } + }); } return collector; } @@ -62,9 +69,14 @@ public abstract class AstTransformContributor { List fields = RecursionManager.doPreventingRecursion(clazz, true, new Computable>() { @Override public List compute() { - List collector = new ArrayList(); + final List collector = new ArrayList(); for (final AstTransformContributor contributor : EP_NAME.getExtensions()) { - contributor.collectFields(clazz, collector); + contributor.collectFields(clazz, new Consumer() { + @Override + public void consume(GrField field) { + collector.add(field); + } + }); } return collector; } diff --git a/plugins/groovy/groovy-psi/src/org/jetbrains/plugins/groovy/lang/resolve/ast/AutoCloneContributor.java b/plugins/groovy/groovy-psi/src/org/jetbrains/plugins/groovy/lang/resolve/ast/AutoCloneContributor.java index df50d86d242d..c4527f30b76a 100644 --- a/plugins/groovy/groovy-psi/src/org/jetbrains/plugins/groovy/lang/resolve/ast/AutoCloneContributor.java +++ b/plugins/groovy/groovy-psi/src/org/jetbrains/plugins/groovy/lang/resolve/ast/AutoCloneContributor.java @@ -1,5 +1,5 @@ /* - * Copyright 2000-2014 JetBrains s.r.o. + * Copyright 2000-2015 JetBrains s.r.o. * * Licensed under the Apache License, Version 2.0 (the "License"); * you may not use this file except in compliance with the License. @@ -18,20 +18,19 @@ package org.jetbrains.plugins.groovy.lang.resolve.ast; import com.intellij.psi.PsiMethod; import com.intellij.psi.PsiModifier; import com.intellij.psi.impl.light.LightMethodBuilder; +import com.intellij.util.Consumer; import org.jetbrains.annotations.NotNull; import org.jetbrains.plugins.groovy.lang.psi.api.statements.typedef.GrTypeDefinition; import org.jetbrains.plugins.groovy.lang.psi.impl.PsiImplUtil; import org.jetbrains.plugins.groovy.lang.psi.util.GroovyCommonClassNames; -import java.util.Collection; - /** * @author Max Medvedev */ public class AutoCloneContributor extends AstTransformContributor { @Override - public void collectMethods(@NotNull GrTypeDefinition clazz, @NotNull Collection collector) { + public void collectMethods(@NotNull GrTypeDefinition clazz, @NotNull Consumer collector) { if (PsiImplUtil.getAnnotation(clazz, GroovyCommonClassNames.GROOVY_TRANSFORM_AUTO_CLONE) == null) return; final LightMethodBuilder clone = new LightMethodBuilder(clazz.getManager(), "clone"); @@ -39,6 +38,6 @@ public class AutoCloneContributor extends AstTransformContributor { clone.setContainingClass(clazz); clone.addException(CloneNotSupportedException.class.getName()); clone.setOriginInfo("created by @AutoClone"); - collector.add(clone); + collector.consume(clone); } } diff --git a/plugins/groovy/groovy-psi/src/org/jetbrains/plugins/groovy/lang/resolve/ast/AutoExternalizeContributor.java b/plugins/groovy/groovy-psi/src/org/jetbrains/plugins/groovy/lang/resolve/ast/AutoExternalizeContributor.java index d5c6d916af54..9e0b5aa764a2 100644 --- a/plugins/groovy/groovy-psi/src/org/jetbrains/plugins/groovy/lang/resolve/ast/AutoExternalizeContributor.java +++ b/plugins/groovy/groovy-psi/src/org/jetbrains/plugins/groovy/lang/resolve/ast/AutoExternalizeContributor.java @@ -1,5 +1,5 @@ /* - * Copyright 2000-2014 JetBrains s.r.o. + * Copyright 2000-2015 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. @@ -17,6 +17,7 @@ package org.jetbrains.plugins.groovy.lang.resolve.ast; import com.intellij.psi.PsiMethod; import com.intellij.psi.impl.light.LightMethodBuilder; +import com.intellij.util.Consumer; import org.jetbrains.annotations.NotNull; import org.jetbrains.plugins.groovy.lang.psi.api.statements.typedef.GrTypeDefinition; import org.jetbrains.plugins.groovy.lang.psi.impl.PsiImplUtil; @@ -25,7 +26,6 @@ import org.jetbrains.plugins.groovy.lang.psi.util.GroovyCommonClassNames; import java.io.IOException; import java.io.ObjectInput; import java.io.ObjectOutput; -import java.util.Collection; /** * @author Max Medvedev @@ -33,7 +33,7 @@ import java.util.Collection; public class AutoExternalizeContributor extends AstTransformContributor { @Override - public void collectMethods(@NotNull GrTypeDefinition clazz, @NotNull Collection collector) { + public void collectMethods(@NotNull GrTypeDefinition clazz, @NotNull Consumer collector) { if (!hasGeneratedImplementations(clazz)) return; final LightMethodBuilder write = new LightMethodBuilder(clazz.getManager(), "writeExternal"); @@ -41,13 +41,13 @@ public class AutoExternalizeContributor extends AstTransformContributor { write.addParameter("out", ObjectOutput.class.getName()); write.addException(IOException.class.getName()); write.setOriginInfo("created by @AutoExternalize"); - collector.add(write); + collector.consume(write); final LightMethodBuilder read = new LightMethodBuilder(clazz.getManager(), "readExternal"); read.setContainingClass(clazz); read.addParameter("oin", ObjectInput.class.getName()); read.setOriginInfo("created by @AutoExternalize"); - collector.add(read); + collector.consume(read); } private static boolean hasGeneratedImplementations(GrTypeDefinition clazz) { diff --git a/plugins/groovy/groovy-psi/src/org/jetbrains/plugins/groovy/lang/resolve/ast/ConstructorAnnotationsProcessor.java b/plugins/groovy/groovy-psi/src/org/jetbrains/plugins/groovy/lang/resolve/ast/ConstructorAnnotationsProcessor.java index 18f37a410587..ebe0e649a96b 100644 --- a/plugins/groovy/groovy-psi/src/org/jetbrains/plugins/groovy/lang/resolve/ast/ConstructorAnnotationsProcessor.java +++ b/plugins/groovy/groovy-psi/src/org/jetbrains/plugins/groovy/lang/resolve/ast/ConstructorAnnotationsProcessor.java @@ -1,5 +1,5 @@ /* - * Copyright 2000-2014 JetBrains s.r.o. + * Copyright 2000-2015 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. @@ -19,6 +19,7 @@ package org.jetbrains.plugins.groovy.lang.resolve.ast; import com.intellij.openapi.util.text.StringUtil; import com.intellij.psi.*; import com.intellij.psi.util.PropertyUtil; +import com.intellij.util.Consumer; import org.jetbrains.annotations.NotNull; import org.jetbrains.annotations.Nullable; import org.jetbrains.plugins.groovy.lang.psi.api.statements.GrField; @@ -30,7 +31,6 @@ import org.jetbrains.plugins.groovy.lang.psi.util.GroovyCommonClassNames; import org.jetbrains.plugins.groovy.lang.psi.util.PsiUtil; import org.jetbrains.plugins.groovy.lang.resolve.CollectClassMembersUtil; -import java.util.Collection; import java.util.HashSet; import java.util.Map; import java.util.Set; @@ -41,7 +41,7 @@ import java.util.Set; public class ConstructorAnnotationsProcessor extends AstTransformContributor { @Override - public void collectMethods(@NotNull GrTypeDefinition typeDefinition, @NotNull Collection collector) { + public void collectMethods(@NotNull GrTypeDefinition typeDefinition, @NotNull Consumer collector) { if (typeDefinition.getName() == null) return; PsiModifierList modifierList = typeDefinition.getModifierList(); @@ -63,8 +63,8 @@ public class ConstructorAnnotationsProcessor extends AstTransformContributor { final GrLightMethodBuilder fieldsConstructor = generateFieldConstructor(typeDefinition, tupleConstructor, immutable, canonical); final GrLightMethodBuilder mapConstructor = generateMapConstructor(typeDefinition); - collector.add(fieldsConstructor); - collector.add(mapConstructor); + collector.consume(fieldsConstructor); + collector.consume(mapConstructor); } @NotNull @@ -154,7 +154,7 @@ public class ConstructorAnnotationsProcessor extends AstTransformContributor { } } - final Map properties = PropertyUtil.getAllProperties(true, false, methods); + final Map properties = PropertyUtil.getAllProperties(true, false, methods); for (PsiField field : CollectClassMembersUtil.getFields(psiClass, false)) { final String name = field.getName(); if (includeFields || diff --git a/plugins/groovy/groovy-psi/src/org/jetbrains/plugins/groovy/lang/resolve/ast/DelegatedMethodsContributor.java b/plugins/groovy/groovy-psi/src/org/jetbrains/plugins/groovy/lang/resolve/ast/DelegatedMethodsContributor.java index 17d1e24a0766..21de6c0527e1 100644 --- a/plugins/groovy/groovy-psi/src/org/jetbrains/plugins/groovy/lang/resolve/ast/DelegatedMethodsContributor.java +++ b/plugins/groovy/groovy-psi/src/org/jetbrains/plugins/groovy/lang/resolve/ast/DelegatedMethodsContributor.java @@ -1,5 +1,5 @@ /* - * Copyright 2000-2014 JetBrains s.r.o. + * Copyright 2000-2015 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. @@ -26,6 +26,7 @@ import com.intellij.psi.util.MethodSignature; import com.intellij.psi.util.MethodSignatureUtil; import com.intellij.psi.util.PsiUtil; import com.intellij.psi.util.TypeConversionUtil; +import com.intellij.util.Consumer; import com.intellij.util.containers.ContainerUtil; import com.intellij.util.containers.hash.HashSet; import gnu.trove.THashMap; @@ -50,7 +51,7 @@ import java.util.*; */ public class DelegatedMethodsContributor extends AstTransformContributor { @Override - public void collectMethods(@NotNull final GrTypeDefinition clazz, @NotNull Collection collector) { + public void collectMethods(@NotNull final GrTypeDefinition clazz, @NotNull Consumer collector) { Set processed = new HashSet(); if (!checkForDelegate(clazz)) return; @@ -66,7 +67,9 @@ public class DelegatedMethodsContributor extends AstTransformContributor { addMethodChecked(signatures, method, PsiSubstitutor.EMPTY, result); } - collector.addAll(result); + for (PsiMethod method : result) { + collector.consume(method); + } } private static boolean checkForDelegate(GrTypeDefinition clazz) { diff --git a/plugins/groovy/groovy-psi/src/org/jetbrains/plugins/groovy/lang/resolve/ast/GrInheritConstructorContributor.java b/plugins/groovy/groovy-psi/src/org/jetbrains/plugins/groovy/lang/resolve/ast/GrInheritConstructorContributor.java index 13767661fefb..e95a9541db7b 100644 --- a/plugins/groovy/groovy-psi/src/org/jetbrains/plugins/groovy/lang/resolve/ast/GrInheritConstructorContributor.java +++ b/plugins/groovy/groovy-psi/src/org/jetbrains/plugins/groovy/lang/resolve/ast/GrInheritConstructorContributor.java @@ -1,5 +1,5 @@ /* - * Copyright 2000-2014 JetBrains s.r.o. + * Copyright 2000-2015 JetBrains s.r.o. * * Licensed under the Apache License, Version 2.0 (the "License"); * you may not use this file except in compliance with the License. @@ -18,21 +18,20 @@ package org.jetbrains.plugins.groovy.lang.resolve.ast; import com.intellij.openapi.util.text.StringUtil; import com.intellij.psi.*; import com.intellij.psi.util.TypeConversionUtil; +import com.intellij.util.Consumer; import com.intellij.util.VisibilityUtil; import org.jetbrains.annotations.NotNull; import org.jetbrains.plugins.groovy.lang.psi.api.statements.typedef.GrTypeDefinition; import org.jetbrains.plugins.groovy.lang.psi.impl.synthetic.GrLightMethodBuilder; import org.jetbrains.plugins.groovy.lang.psi.util.GroovyCommonClassNames; -import java.util.Collection; - /** * @author Maxim.Medvedev */ public class GrInheritConstructorContributor extends AstTransformContributor { @Override - public void collectMethods(@NotNull GrTypeDefinition psiClass, @NotNull Collection collector) { + public void collectMethods(@NotNull GrTypeDefinition psiClass, @NotNull Consumer collector) { if (psiClass.isAnonymous() || psiClass.isInterface() || psiClass.isEnum()) { return; } @@ -59,7 +58,7 @@ public class GrInheritConstructorContributor extends AstTransformContributor { inheritedConstructor.addParameter(name, type, false); } if (psiClass.findCodeMethodsBySignature(inheritedConstructor, false).length == 0) { - collector.add(inheritedConstructor); + collector.consume(inheritedConstructor); } } } diff --git a/plugins/groovy/groovy-psi/src/org/jetbrains/plugins/groovy/lang/resolve/ast/LoggingContributor.java b/plugins/groovy/groovy-psi/src/org/jetbrains/plugins/groovy/lang/resolve/ast/LoggingContributor.java index fafc7e423fdc..78fcb66d90b0 100644 --- a/plugins/groovy/groovy-psi/src/org/jetbrains/plugins/groovy/lang/resolve/ast/LoggingContributor.java +++ b/plugins/groovy/groovy-psi/src/org/jetbrains/plugins/groovy/lang/resolve/ast/LoggingContributor.java @@ -1,5 +1,5 @@ /* - * Copyright 2000-2014 JetBrains s.r.o. + * Copyright 2000-2015 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. @@ -17,6 +17,7 @@ package org.jetbrains.plugins.groovy.lang.resolve.ast; import com.google.common.collect.ImmutableMap; import com.intellij.psi.PsiModifier; +import com.intellij.util.Consumer; import org.jetbrains.annotations.NotNull; import org.jetbrains.plugins.groovy.lang.psi.api.auxiliary.modifiers.GrModifierList; import org.jetbrains.plugins.groovy.lang.psi.api.auxiliary.modifiers.annotation.GrAnnotation; @@ -25,8 +26,6 @@ import org.jetbrains.plugins.groovy.lang.psi.api.statements.typedef.GrTypeDefini import org.jetbrains.plugins.groovy.lang.psi.impl.synthetic.GrLightField; import org.jetbrains.plugins.groovy.lang.psi.util.PsiUtil; -import java.util.Collection; - /** * @author peter */ @@ -39,7 +38,7 @@ public class LoggingContributor extends AstTransformContributor { build(); @Override - public void collectFields(@NotNull GrTypeDefinition psiClass, @NotNull Collection collector) { + public void collectFields(@NotNull GrTypeDefinition psiClass, @NotNull Consumer collector) { GrModifierList modifierList = psiClass.getModifierList(); if (modifierList == null) return; @@ -52,7 +51,7 @@ public class LoggingContributor extends AstTransformContributor { field.setNavigationElement(annotation); field.getModifierList().setModifiers(PsiModifier.PRIVATE, PsiModifier.FINAL, PsiModifier.STATIC); field.setOriginInfo("created by @" + annotation.getShortName()); - collector.add(field); + collector.consume(field); } } } From 698bdc9c5fd409f9cd252fb465e91c70381e3067 Mon Sep 17 00:00:00 2001 From: Dmitry Jemerov Date: Fri, 3 Jul 2015 14:07:10 +0200 Subject: [PATCH 33/39] add Kotlin runtime to PyCharm layouts (IDEA-142239) --- python/build/pycharm_community_build.gant | 5 +++++ python/edu/build/pycharm_edu_build.gant | 5 +++++ 2 files changed, 10 insertions(+) diff --git a/python/build/pycharm_community_build.gant b/python/build/pycharm_community_build.gant index b1daea58a3a3..9f0451976e7d 100644 --- a/python/build/pycharm_community_build.gant +++ b/python/build/pycharm_community_build.gant @@ -266,6 +266,11 @@ private layoutFull(Map args, String target, Set usedJars) { fileset(file: it) } + fileset(dir: "$home/community/build/kotlinc/lib") { + include(name: "kotlin-runtime.jar") + include(name: "kotlin-reflect.jar") + } + dir("libpty") { fileset(dir: "$ch/lib/libpty") { exclude(name: "*.txt") diff --git a/python/edu/build/pycharm_edu_build.gant b/python/edu/build/pycharm_edu_build.gant index b5ae93ba586a..286e928a011e 100644 --- a/python/edu/build/pycharm_edu_build.gant +++ b/python/edu/build/pycharm_edu_build.gant @@ -303,6 +303,11 @@ private layoutFull(Map args, String target, Set usedJars) { fileset(file: it) } + fileset(dir: "$home/community/build/kotlinc/lib") { + include(name: "kotlin-runtime.jar") + include(name: "kotlin-reflect.jar") + } + dir("libpty") { fileset(dir: "$ch/lib/libpty") { exclude(name: "*.txt") From 977c3dbb2386aa7e19aa4dea80a33dc4b9d6bc9f Mon Sep 17 00:00:00 2001 From: Dmitry Jemerov Date: Fri, 3 Jul 2015 14:07:57 +0200 Subject: [PATCH 34/39] refer to community home as $cj --- python/build/pycharm_community_build.gant | 2 +- python/edu/build/pycharm_edu_build.gant | 2 +- 2 files changed, 2 insertions(+), 2 deletions(-) diff --git a/python/build/pycharm_community_build.gant b/python/build/pycharm_community_build.gant index 9f0451976e7d..45cd7c83fc62 100644 --- a/python/build/pycharm_community_build.gant +++ b/python/build/pycharm_community_build.gant @@ -266,7 +266,7 @@ private layoutFull(Map args, String target, Set usedJars) { fileset(file: it) } - fileset(dir: "$home/community/build/kotlinc/lib") { + fileset(dir: "$ch/build/kotlinc/lib") { include(name: "kotlin-runtime.jar") include(name: "kotlin-reflect.jar") } diff --git a/python/edu/build/pycharm_edu_build.gant b/python/edu/build/pycharm_edu_build.gant index 286e928a011e..f21bd2065136 100644 --- a/python/edu/build/pycharm_edu_build.gant +++ b/python/edu/build/pycharm_edu_build.gant @@ -303,7 +303,7 @@ private layoutFull(Map args, String target, Set usedJars) { fileset(file: it) } - fileset(dir: "$home/community/build/kotlinc/lib") { + fileset(dir: "$ch/build/kotlinc/lib") { include(name: "kotlin-runtime.jar") include(name: "kotlin-reflect.jar") } From 1f02e22dbd668eaeee1ebd4e7ab7ea83c76e0d14 Mon Sep 17 00:00:00 2001 From: peter Date: Fri, 3 Jul 2015 13:09:19 +0200 Subject: [PATCH 35/39] enable ProjectManagerImpl.LOG_PROJECT_LEAKAGE_IN_TESTS --- .../com/intellij/openapi/project/impl/ProjectManagerImpl.java | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/platform/platform-impl/src/com/intellij/openapi/project/impl/ProjectManagerImpl.java b/platform/platform-impl/src/com/intellij/openapi/project/impl/ProjectManagerImpl.java index d39275763b53..c68ec93bd415 100644 --- a/platform/platform-impl/src/com/intellij/openapi/project/impl/ProjectManagerImpl.java +++ b/platform/platform-impl/src/com/intellij/openapi/project/impl/ProjectManagerImpl.java @@ -217,7 +217,7 @@ public class ProjectManagerImpl extends ProjectManagerEx implements PersistentSt } public static int TEST_PROJECTS_CREATED; - private static final boolean LOG_PROJECT_LEAKAGE_IN_TESTS = false; + private static final boolean LOG_PROJECT_LEAKAGE_IN_TESTS = true; private static final int MAX_LEAKY_PROJECTS = 42; @SuppressWarnings("FieldCanBeLocal") private final Map myProjects = new WeakHashMap(); From b63c470c46687c928b45067da72a1dbaa16e2b04 Mon Sep 17 00:00:00 2001 From: peter Date: Fri, 3 Jul 2015 14:08:56 +0200 Subject: [PATCH 36/39] JavaFilePasteProvider: normalize line separators --- .../java-impl/src/com/intellij/ide/JavaFilePasteProvider.java | 4 +++- 1 file changed, 3 insertions(+), 1 deletion(-) diff --git a/java/java-impl/src/com/intellij/ide/JavaFilePasteProvider.java b/java/java-impl/src/com/intellij/ide/JavaFilePasteProvider.java index a18ef1eb1632..20a0cb12bb4c 100644 --- a/java/java-impl/src/com/intellij/ide/JavaFilePasteProvider.java +++ b/java/java-impl/src/com/intellij/ide/JavaFilePasteProvider.java @@ -27,6 +27,7 @@ import com.intellij.openapi.fileEditor.OpenFileDescriptor; import com.intellij.openapi.ide.CopyPasteManager; import com.intellij.openapi.project.Project; import com.intellij.openapi.util.TextRange; +import com.intellij.openapi.util.text.StringUtil; import com.intellij.psi.*; import com.intellij.psi.codeStyle.CodeStyleManager; import com.intellij.util.IncorrectOperationException; @@ -128,7 +129,8 @@ public class JavaFilePasteProvider implements PasteProvider { private static PsiJavaFile createJavaFileFromClipboardContent(final Project project) { String text = CopyPasteManager.getInstance().getContents(DataFlavor.stringFlavor); if (text == null) return null; - PsiFile psiFile = PsiFileFactory.getInstance(project).createFileFromText("A.java", JavaLanguage.INSTANCE, text); + PsiFile psiFile = PsiFileFactory.getInstance(project).createFileFromText("A.java", JavaLanguage.INSTANCE, + StringUtil.convertLineSeparators(text)); return psiFile instanceof PsiJavaFile ? (PsiJavaFile)psiFile : null; } } From b02eab3f0a384975d6ebae38b7a879b0ea75bcd6 Mon Sep 17 00:00:00 2001 From: peter Date: Fri, 3 Jul 2015 14:23:55 +0200 Subject: [PATCH 37/39] AllClassesSearchExecutor: wait for smart mode (IDEA-CR-3480) --- .../impl/search/AllClassesSearchExecutor.java | 30 +++++++++++-------- 1 file changed, 18 insertions(+), 12 deletions(-) diff --git a/java/java-indexing-impl/src/com/intellij/psi/impl/search/AllClassesSearchExecutor.java b/java/java-indexing-impl/src/com/intellij/psi/impl/search/AllClassesSearchExecutor.java index 293d3350040b..067db93f8551 100644 --- a/java/java-indexing-impl/src/com/intellij/psi/impl/search/AllClassesSearchExecutor.java +++ b/java/java-indexing-impl/src/com/intellij/psi/impl/search/AllClassesSearchExecutor.java @@ -81,7 +81,7 @@ public class AllClassesSearchExecutor implements QueryExecutor() { + final PsiClass[] classes = MethodUsagesSearcher.resolveInReadAction(project, new Computable() { @Override public PsiClass[] compute() { return cache.getClassesByName(name, scope); @@ -97,21 +97,27 @@ public class AllClassesSearchExecutor implements QueryExecutor consumer) { + public static Project processClassNames(final Project project, final GlobalSearchScope scope, final Consumer consumer) { final ProgressIndicator indicator = ProgressIndicatorProvider.getGlobalProgressIndicator(); - PsiShortNamesCache.getInstance(project).processAllClassNames(new Processor() { - int i = 0; - + MethodUsagesSearcher.resolveInReadAction(project, new Computable() { @Override - public boolean process(String s) { - if (indicator != null && i++ % 512 == 0) { - indicator.checkCanceled(); - } - consumer.consume(s); - return true; + public Void compute() { + PsiShortNamesCache.getInstance(project).processAllClassNames(new Processor() { + int i = 0; + + @Override + public boolean process(String s) { + if (indicator != null && i++ % 512 == 0) { + indicator.checkCanceled(); + } + consumer.consume(s); + return true; + } + }, scope, IdFilter.getProjectIdFilter(project, true)); + return null; } - }, scope, IdFilter.getProjectIdFilter(project, true)); + }); if (indicator != null) { indicator.checkCanceled(); From e4eb7603aa5d4a8e3f1d542daf10f31ccc888034 Mon Sep 17 00:00:00 2001 From: Denis Fokin Date: Fri, 3 Jul 2015 15:36:40 +0300 Subject: [PATCH 38/39] IDEA-142260 Focus issue with switching between spaces on mac --- .../src/com/intellij/openapi/wm/impl/FocusManagerImpl.java | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/platform/platform-impl/src/com/intellij/openapi/wm/impl/FocusManagerImpl.java b/platform/platform-impl/src/com/intellij/openapi/wm/impl/FocusManagerImpl.java index 24bac1bb79ff..545a12d416c3 100644 --- a/platform/platform-impl/src/com/intellij/openapi/wm/impl/FocusManagerImpl.java +++ b/platform/platform-impl/src/com/intellij/openapi/wm/impl/FocusManagerImpl.java @@ -1098,7 +1098,7 @@ public class FocusManagerImpl extends IdeFocusManager implements Disposable { if (mgr.getFocusOwner() == null) { Component c = getComponent(myLastFocusedAtDeactivation, ideFrame); if (c == null || !c.isShowing()) { - c = getComponent(myLastFocused, ideFrame); + c = getComponent(myLastFocusedAtDeactivation, ideFrame); } final boolean mouseEventAhead = IdeEventQueue.isMouseEventAhead(null); From a2d45184b96609fdbf3c6d475d57ea5b18b7459f Mon Sep 17 00:00:00 2001 From: Daniil Ovchinnikov Date: Fri, 3 Jul 2015 15:51:09 +0300 Subject: [PATCH 39/39] [groovy] revert 7131400 --- .../resolve/ast/AstTransformContributor.java | 26 +++++-------------- .../resolve/ast/AutoCloneContributor.java | 7 ++--- .../ast/AutoExternalizeContributor.java | 8 +++--- .../ast/ConstructorAnnotationsProcessor.java | 10 +++---- .../ast/DelegatedMethodsContributor.java | 7 ++--- .../ast/GrInheritConstructorContributor.java | 7 ++--- .../lang/resolve/ast/LoggingContributor.java | 7 ++--- 7 files changed, 30 insertions(+), 42 deletions(-) diff --git a/plugins/groovy/groovy-psi/src/org/jetbrains/plugins/groovy/lang/resolve/ast/AstTransformContributor.java b/plugins/groovy/groovy-psi/src/org/jetbrains/plugins/groovy/lang/resolve/ast/AstTransformContributor.java index 206427d2eaeb..ee75bf4f2b9e 100644 --- a/plugins/groovy/groovy-psi/src/org/jetbrains/plugins/groovy/lang/resolve/ast/AstTransformContributor.java +++ b/plugins/groovy/groovy-psi/src/org/jetbrains/plugins/groovy/lang/resolve/ast/AstTransformContributor.java @@ -19,7 +19,6 @@ import com.intellij.openapi.extensions.ExtensionPointName; import com.intellij.openapi.util.Computable; import com.intellij.openapi.util.RecursionManager; import com.intellij.psi.PsiMethod; -import com.intellij.util.Consumer; import org.jetbrains.annotations.NotNull; import org.jetbrains.plugins.groovy.lang.psi.api.statements.GrField; import org.jetbrains.plugins.groovy.lang.psi.api.statements.typedef.GrTypeDefinition; @@ -33,14 +32,13 @@ import java.util.List; * @author Max Medvedev */ public abstract class AstTransformContributor { - public static final ExtensionPointName EP_NAME = - ExtensionPointName.create("org.intellij.groovy.astTransformContributor"); + public static final ExtensionPointName EP_NAME = ExtensionPointName.create("org.intellij.groovy.astTransformContributor"); - public void collectMethods(@NotNull final GrTypeDefinition clazz, Consumer collector) { + public void collectMethods(@NotNull final GrTypeDefinition clazz, Collection collector) { } - public void collectFields(@NotNull final GrTypeDefinition clazz, Consumer collector) { + public void collectFields(@NotNull final GrTypeDefinition clazz, Collection collector) { } @@ -49,14 +47,9 @@ public abstract class AstTransformContributor { Collection result = RecursionManager.doPreventingRecursion(clazz, true, new Computable>() { @Override public Collection compute() { - final Collection collector = new ArrayList(); + Collection collector = new ArrayList(); for (final AstTransformContributor contributor : EP_NAME.getExtensions()) { - contributor.collectMethods(clazz, new Consumer() { - @Override - public void consume(PsiMethod method) { - collector.add(method); - } - }); + contributor.collectMethods(clazz, collector); } return collector; } @@ -69,14 +62,9 @@ public abstract class AstTransformContributor { List fields = RecursionManager.doPreventingRecursion(clazz, true, new Computable>() { @Override public List compute() { - final List collector = new ArrayList(); + List collector = new ArrayList(); for (final AstTransformContributor contributor : EP_NAME.getExtensions()) { - contributor.collectFields(clazz, new Consumer() { - @Override - public void consume(GrField field) { - collector.add(field); - } - }); + contributor.collectFields(clazz, collector); } return collector; } diff --git a/plugins/groovy/groovy-psi/src/org/jetbrains/plugins/groovy/lang/resolve/ast/AutoCloneContributor.java b/plugins/groovy/groovy-psi/src/org/jetbrains/plugins/groovy/lang/resolve/ast/AutoCloneContributor.java index c4527f30b76a..d3b77fbc336f 100644 --- a/plugins/groovy/groovy-psi/src/org/jetbrains/plugins/groovy/lang/resolve/ast/AutoCloneContributor.java +++ b/plugins/groovy/groovy-psi/src/org/jetbrains/plugins/groovy/lang/resolve/ast/AutoCloneContributor.java @@ -18,19 +18,20 @@ package org.jetbrains.plugins.groovy.lang.resolve.ast; import com.intellij.psi.PsiMethod; import com.intellij.psi.PsiModifier; import com.intellij.psi.impl.light.LightMethodBuilder; -import com.intellij.util.Consumer; import org.jetbrains.annotations.NotNull; import org.jetbrains.plugins.groovy.lang.psi.api.statements.typedef.GrTypeDefinition; import org.jetbrains.plugins.groovy.lang.psi.impl.PsiImplUtil; import org.jetbrains.plugins.groovy.lang.psi.util.GroovyCommonClassNames; +import java.util.Collection; + /** * @author Max Medvedev */ public class AutoCloneContributor extends AstTransformContributor { @Override - public void collectMethods(@NotNull GrTypeDefinition clazz, @NotNull Consumer collector) { + public void collectMethods(@NotNull GrTypeDefinition clazz, @NotNull Collection collector) { if (PsiImplUtil.getAnnotation(clazz, GroovyCommonClassNames.GROOVY_TRANSFORM_AUTO_CLONE) == null) return; final LightMethodBuilder clone = new LightMethodBuilder(clazz.getManager(), "clone"); @@ -38,6 +39,6 @@ public class AutoCloneContributor extends AstTransformContributor { clone.setContainingClass(clazz); clone.addException(CloneNotSupportedException.class.getName()); clone.setOriginInfo("created by @AutoClone"); - collector.consume(clone); + collector.add(clone); } } diff --git a/plugins/groovy/groovy-psi/src/org/jetbrains/plugins/groovy/lang/resolve/ast/AutoExternalizeContributor.java b/plugins/groovy/groovy-psi/src/org/jetbrains/plugins/groovy/lang/resolve/ast/AutoExternalizeContributor.java index 9e0b5aa764a2..ef619d478ba8 100644 --- a/plugins/groovy/groovy-psi/src/org/jetbrains/plugins/groovy/lang/resolve/ast/AutoExternalizeContributor.java +++ b/plugins/groovy/groovy-psi/src/org/jetbrains/plugins/groovy/lang/resolve/ast/AutoExternalizeContributor.java @@ -17,7 +17,6 @@ package org.jetbrains.plugins.groovy.lang.resolve.ast; import com.intellij.psi.PsiMethod; import com.intellij.psi.impl.light.LightMethodBuilder; -import com.intellij.util.Consumer; import org.jetbrains.annotations.NotNull; import org.jetbrains.plugins.groovy.lang.psi.api.statements.typedef.GrTypeDefinition; import org.jetbrains.plugins.groovy.lang.psi.impl.PsiImplUtil; @@ -26,6 +25,7 @@ import org.jetbrains.plugins.groovy.lang.psi.util.GroovyCommonClassNames; import java.io.IOException; import java.io.ObjectInput; import java.io.ObjectOutput; +import java.util.Collection; /** * @author Max Medvedev @@ -33,7 +33,7 @@ import java.io.ObjectOutput; public class AutoExternalizeContributor extends AstTransformContributor { @Override - public void collectMethods(@NotNull GrTypeDefinition clazz, @NotNull Consumer collector) { + public void collectMethods(@NotNull GrTypeDefinition clazz, @NotNull Collection collector) { if (!hasGeneratedImplementations(clazz)) return; final LightMethodBuilder write = new LightMethodBuilder(clazz.getManager(), "writeExternal"); @@ -41,13 +41,13 @@ public class AutoExternalizeContributor extends AstTransformContributor { write.addParameter("out", ObjectOutput.class.getName()); write.addException(IOException.class.getName()); write.setOriginInfo("created by @AutoExternalize"); - collector.consume(write); + collector.add(write); final LightMethodBuilder read = new LightMethodBuilder(clazz.getManager(), "readExternal"); read.setContainingClass(clazz); read.addParameter("oin", ObjectInput.class.getName()); read.setOriginInfo("created by @AutoExternalize"); - collector.consume(read); + collector.add(read); } private static boolean hasGeneratedImplementations(GrTypeDefinition clazz) { diff --git a/plugins/groovy/groovy-psi/src/org/jetbrains/plugins/groovy/lang/resolve/ast/ConstructorAnnotationsProcessor.java b/plugins/groovy/groovy-psi/src/org/jetbrains/plugins/groovy/lang/resolve/ast/ConstructorAnnotationsProcessor.java index ebe0e649a96b..0d38863fe9ba 100644 --- a/plugins/groovy/groovy-psi/src/org/jetbrains/plugins/groovy/lang/resolve/ast/ConstructorAnnotationsProcessor.java +++ b/plugins/groovy/groovy-psi/src/org/jetbrains/plugins/groovy/lang/resolve/ast/ConstructorAnnotationsProcessor.java @@ -19,7 +19,6 @@ package org.jetbrains.plugins.groovy.lang.resolve.ast; import com.intellij.openapi.util.text.StringUtil; import com.intellij.psi.*; import com.intellij.psi.util.PropertyUtil; -import com.intellij.util.Consumer; import org.jetbrains.annotations.NotNull; import org.jetbrains.annotations.Nullable; import org.jetbrains.plugins.groovy.lang.psi.api.statements.GrField; @@ -31,6 +30,7 @@ import org.jetbrains.plugins.groovy.lang.psi.util.GroovyCommonClassNames; import org.jetbrains.plugins.groovy.lang.psi.util.PsiUtil; import org.jetbrains.plugins.groovy.lang.resolve.CollectClassMembersUtil; +import java.util.Collection; import java.util.HashSet; import java.util.Map; import java.util.Set; @@ -41,7 +41,7 @@ import java.util.Set; public class ConstructorAnnotationsProcessor extends AstTransformContributor { @Override - public void collectMethods(@NotNull GrTypeDefinition typeDefinition, @NotNull Consumer collector) { + public void collectMethods(@NotNull GrTypeDefinition typeDefinition, @NotNull Collection collector) { if (typeDefinition.getName() == null) return; PsiModifierList modifierList = typeDefinition.getModifierList(); @@ -63,8 +63,8 @@ public class ConstructorAnnotationsProcessor extends AstTransformContributor { final GrLightMethodBuilder fieldsConstructor = generateFieldConstructor(typeDefinition, tupleConstructor, immutable, canonical); final GrLightMethodBuilder mapConstructor = generateMapConstructor(typeDefinition); - collector.consume(fieldsConstructor); - collector.consume(mapConstructor); + collector.add(fieldsConstructor); + collector.add(mapConstructor); } @NotNull @@ -154,7 +154,7 @@ public class ConstructorAnnotationsProcessor extends AstTransformContributor { } } - final Map properties = PropertyUtil.getAllProperties(true, false, methods); + final Map properties = PropertyUtil.getAllProperties(true, false, methods); for (PsiField field : CollectClassMembersUtil.getFields(psiClass, false)) { final String name = field.getName(); if (includeFields || diff --git a/plugins/groovy/groovy-psi/src/org/jetbrains/plugins/groovy/lang/resolve/ast/DelegatedMethodsContributor.java b/plugins/groovy/groovy-psi/src/org/jetbrains/plugins/groovy/lang/resolve/ast/DelegatedMethodsContributor.java index 21de6c0527e1..6ff0c74a9f0c 100644 --- a/plugins/groovy/groovy-psi/src/org/jetbrains/plugins/groovy/lang/resolve/ast/DelegatedMethodsContributor.java +++ b/plugins/groovy/groovy-psi/src/org/jetbrains/plugins/groovy/lang/resolve/ast/DelegatedMethodsContributor.java @@ -26,7 +26,6 @@ import com.intellij.psi.util.MethodSignature; import com.intellij.psi.util.MethodSignatureUtil; import com.intellij.psi.util.PsiUtil; import com.intellij.psi.util.TypeConversionUtil; -import com.intellij.util.Consumer; import com.intellij.util.containers.ContainerUtil; import com.intellij.util.containers.hash.HashSet; import gnu.trove.THashMap; @@ -51,7 +50,7 @@ import java.util.*; */ public class DelegatedMethodsContributor extends AstTransformContributor { @Override - public void collectMethods(@NotNull final GrTypeDefinition clazz, @NotNull Consumer collector) { + public void collectMethods(@NotNull final GrTypeDefinition clazz, @NotNull Collection collector) { Set processed = new HashSet(); if (!checkForDelegate(clazz)) return; @@ -67,9 +66,7 @@ public class DelegatedMethodsContributor extends AstTransformContributor { addMethodChecked(signatures, method, PsiSubstitutor.EMPTY, result); } - for (PsiMethod method : result) { - collector.consume(method); - } + collector.addAll(result); } private static boolean checkForDelegate(GrTypeDefinition clazz) { diff --git a/plugins/groovy/groovy-psi/src/org/jetbrains/plugins/groovy/lang/resolve/ast/GrInheritConstructorContributor.java b/plugins/groovy/groovy-psi/src/org/jetbrains/plugins/groovy/lang/resolve/ast/GrInheritConstructorContributor.java index e95a9541db7b..c83731a468ae 100644 --- a/plugins/groovy/groovy-psi/src/org/jetbrains/plugins/groovy/lang/resolve/ast/GrInheritConstructorContributor.java +++ b/plugins/groovy/groovy-psi/src/org/jetbrains/plugins/groovy/lang/resolve/ast/GrInheritConstructorContributor.java @@ -18,20 +18,21 @@ package org.jetbrains.plugins.groovy.lang.resolve.ast; import com.intellij.openapi.util.text.StringUtil; import com.intellij.psi.*; import com.intellij.psi.util.TypeConversionUtil; -import com.intellij.util.Consumer; import com.intellij.util.VisibilityUtil; import org.jetbrains.annotations.NotNull; import org.jetbrains.plugins.groovy.lang.psi.api.statements.typedef.GrTypeDefinition; import org.jetbrains.plugins.groovy.lang.psi.impl.synthetic.GrLightMethodBuilder; import org.jetbrains.plugins.groovy.lang.psi.util.GroovyCommonClassNames; +import java.util.Collection; + /** * @author Maxim.Medvedev */ public class GrInheritConstructorContributor extends AstTransformContributor { @Override - public void collectMethods(@NotNull GrTypeDefinition psiClass, @NotNull Consumer collector) { + public void collectMethods(@NotNull GrTypeDefinition psiClass, @NotNull Collection collector) { if (psiClass.isAnonymous() || psiClass.isInterface() || psiClass.isEnum()) { return; } @@ -58,7 +59,7 @@ public class GrInheritConstructorContributor extends AstTransformContributor { inheritedConstructor.addParameter(name, type, false); } if (psiClass.findCodeMethodsBySignature(inheritedConstructor, false).length == 0) { - collector.consume(inheritedConstructor); + collector.add(inheritedConstructor); } } } diff --git a/plugins/groovy/groovy-psi/src/org/jetbrains/plugins/groovy/lang/resolve/ast/LoggingContributor.java b/plugins/groovy/groovy-psi/src/org/jetbrains/plugins/groovy/lang/resolve/ast/LoggingContributor.java index 78fcb66d90b0..c2e03d2482f4 100644 --- a/plugins/groovy/groovy-psi/src/org/jetbrains/plugins/groovy/lang/resolve/ast/LoggingContributor.java +++ b/plugins/groovy/groovy-psi/src/org/jetbrains/plugins/groovy/lang/resolve/ast/LoggingContributor.java @@ -17,7 +17,6 @@ package org.jetbrains.plugins.groovy.lang.resolve.ast; import com.google.common.collect.ImmutableMap; import com.intellij.psi.PsiModifier; -import com.intellij.util.Consumer; import org.jetbrains.annotations.NotNull; import org.jetbrains.plugins.groovy.lang.psi.api.auxiliary.modifiers.GrModifierList; import org.jetbrains.plugins.groovy.lang.psi.api.auxiliary.modifiers.annotation.GrAnnotation; @@ -26,6 +25,8 @@ import org.jetbrains.plugins.groovy.lang.psi.api.statements.typedef.GrTypeDefini import org.jetbrains.plugins.groovy.lang.psi.impl.synthetic.GrLightField; import org.jetbrains.plugins.groovy.lang.psi.util.PsiUtil; +import java.util.Collection; + /** * @author peter */ @@ -38,7 +39,7 @@ public class LoggingContributor extends AstTransformContributor { build(); @Override - public void collectFields(@NotNull GrTypeDefinition psiClass, @NotNull Consumer collector) { + public void collectFields(@NotNull GrTypeDefinition psiClass, @NotNull Collection collector) { GrModifierList modifierList = psiClass.getModifierList(); if (modifierList == null) return; @@ -51,7 +52,7 @@ public class LoggingContributor extends AstTransformContributor { field.setNavigationElement(annotation); field.getModifierList().setModifiers(PsiModifier.PRIVATE, PsiModifier.FINAL, PsiModifier.STATIC); field.setOriginInfo("created by @" + annotation.getShortName()); - collector.consume(field); + collector.add(field); } } }