From f6c426cb7dcb019917175e332303eb667e1b9f4a Mon Sep 17 00:00:00 2001 From: Vassiliy Date: Thu, 20 Mar 2014 21:19:00 +0400 Subject: [PATCH 01/36] IDEA-122561 Some code is not shielded by "ide.mac.message.dialogs.as.sheets" key --- .../platform-api/src/com/intellij/openapi/ui/Messages.java | 4 +++- 1 file changed, 3 insertions(+), 1 deletion(-) diff --git a/platform/platform-api/src/com/intellij/openapi/ui/Messages.java b/platform/platform-api/src/com/intellij/openapi/ui/Messages.java index e35eb60018d9..be946e68c7eb 100644 --- a/platform/platform-api/src/com/intellij/openapi/ui/Messages.java +++ b/platform/platform-api/src/com/intellij/openapi/ui/Messages.java @@ -1317,7 +1317,9 @@ public class Messages { setButtonsAlignment(SwingConstants.CENTER); setDoNotAskOption(doNotAskOption); init(); - MacUtil.adjustFocusTraversal(myDisposable); + if (isMacSheetEmulation()) { + MacUtil.adjustFocusTraversal(myDisposable); + } } @NotNull From 46863158804651cb267048597f63162a3374bbe1 Mon Sep 17 00:00:00 2001 From: Anna Kozlova Date: Thu, 20 Mar 2014 17:50:09 +0100 Subject: [PATCH 02/36] A class may not at the same time be a subtype of two interface types which are different parameterizations of the same generic interface(IDEA-122475); revert workarounds for javac 6 bug --- .../daemon/impl/analysis/GenericsHighlightUtil.java | 4 ++-- .../ambiguousInheritance/pck/AmbiguousMethodCall.java | 2 +- .../InheritedWithDifferentArgsInTypeParams.java | 2 +- .../InheritedWithDifferentArgsInTypeParams1.java | 10 ++++++++++ .../InheritedWithDifferentArgsInTypeParams.java | 2 +- .../codeInsight/daemon/GenericsHighlightingTest.java | 1 + 6 files changed, 16 insertions(+), 5 deletions(-) create mode 100644 java/java-tests/testData/codeInsight/daemonCodeAnalyzer/genericsHighlighting/InheritedWithDifferentArgsInTypeParams1.java diff --git a/java/java-analysis-impl/src/com/intellij/codeInsight/daemon/impl/analysis/GenericsHighlightUtil.java b/java/java-analysis-impl/src/com/intellij/codeInsight/daemon/impl/analysis/GenericsHighlightUtil.java index 72ad0f26efa1..77a928abfb6b 100644 --- a/java/java-analysis-impl/src/com/intellij/codeInsight/daemon/impl/analysis/GenericsHighlightUtil.java +++ b/java/java-analysis-impl/src/com/intellij/codeInsight/daemon/impl/analysis/GenericsHighlightUtil.java @@ -358,8 +358,8 @@ public class GenericsHighlightUtil { if (inheritedSubstitutor != null) { final PsiTypeParameter[] typeParameters = superClass.getTypeParameters(); for (PsiTypeParameter typeParameter : typeParameters) { - PsiType type1 = GenericsUtil.eliminateWildcards(inheritedSubstitutor.substitute(typeParameter)); - PsiType type2 = GenericsUtil.eliminateWildcards(superTypeSubstitutor.substitute(typeParameter)); + PsiType type1 = inheritedSubstitutor.substitute(typeParameter); + PsiType type2 = superTypeSubstitutor.substitute(typeParameter); if (!Comparing.equal(type1, type2)) { String description = JavaErrorMessages.message("generics.cannot.be.inherited.with.different.type.arguments", diff --git a/java/java-tests/testData/codeInsight/daemonCodeAnalyzer/advHighlighting7/ambiguousInheritance/pck/AmbiguousMethodCall.java b/java/java-tests/testData/codeInsight/daemonCodeAnalyzer/advHighlighting7/ambiguousInheritance/pck/AmbiguousMethodCall.java index 580a30a72403..5eab22e56d86 100644 --- a/java/java-tests/testData/codeInsight/daemonCodeAnalyzer/advHighlighting7/ambiguousInheritance/pck/AmbiguousMethodCall.java +++ b/java/java-tests/testData/codeInsight/daemonCodeAnalyzer/advHighlighting7/ambiguousInheritance/pck/AmbiguousMethodCall.java @@ -7,7 +7,7 @@ interface A interface B extends A { } -class C & B> +class C & B> { void foo(T x) { diff --git a/java/java-tests/testData/codeInsight/daemonCodeAnalyzer/genericsHighlighting/InheritedWithDifferentArgsInTypeParams.java b/java/java-tests/testData/codeInsight/daemonCodeAnalyzer/genericsHighlighting/InheritedWithDifferentArgsInTypeParams.java index 2adff2f8f495..180b75572c6e 100644 --- a/java/java-tests/testData/codeInsight/daemonCodeAnalyzer/genericsHighlighting/InheritedWithDifferentArgsInTypeParams.java +++ b/java/java-tests/testData/codeInsight/daemonCodeAnalyzer/genericsHighlighting/InheritedWithDifferentArgsInTypeParams.java @@ -18,7 +18,7 @@ interface IA2 {} interface IB2 extends IA2 {} class A2 { - & IB2> void foo(){} + & IB2> void foo(){} } diff --git a/java/java-tests/testData/codeInsight/daemonCodeAnalyzer/genericsHighlighting/InheritedWithDifferentArgsInTypeParams1.java b/java/java-tests/testData/codeInsight/daemonCodeAnalyzer/genericsHighlighting/InheritedWithDifferentArgsInTypeParams1.java new file mode 100644 index 000000000000..f7fda29752d4 --- /dev/null +++ b/java/java-tests/testData/codeInsight/daemonCodeAnalyzer/genericsHighlighting/InheritedWithDifferentArgsInTypeParams1.java @@ -0,0 +1,10 @@ +import java.util.List; + +interface Base { +} + +interface Middle extends Base> { +} + +interface Child extends Middle, Base> { +} diff --git a/java/java-tests/testData/codeInsight/daemonCodeAnalyzer/genericsHighlighting8/InheritedWithDifferentArgsInTypeParams.java b/java/java-tests/testData/codeInsight/daemonCodeAnalyzer/genericsHighlighting8/InheritedWithDifferentArgsInTypeParams.java index 2adff2f8f495..a1c0d83bc64a 100644 --- a/java/java-tests/testData/codeInsight/daemonCodeAnalyzer/genericsHighlighting8/InheritedWithDifferentArgsInTypeParams.java +++ b/java/java-tests/testData/codeInsight/daemonCodeAnalyzer/genericsHighlighting8/InheritedWithDifferentArgsInTypeParams.java @@ -18,7 +18,7 @@ interface IA2 {} interface IB2 extends IA2 {} class A2 { - & IB2> void foo(){} + <T extends IA2 & IB2> void foo(){} } diff --git a/java/java-tests/testSrc/com/intellij/codeInsight/daemon/GenericsHighlightingTest.java b/java/java-tests/testSrc/com/intellij/codeInsight/daemon/GenericsHighlightingTest.java index 9b8861a5a01c..529065446905 100644 --- a/java/java-tests/testSrc/com/intellij/codeInsight/daemon/GenericsHighlightingTest.java +++ b/java/java-tests/testSrc/com/intellij/codeInsight/daemon/GenericsHighlightingTest.java @@ -238,6 +238,7 @@ public class GenericsHighlightingTest extends LightDaemonAnalyzerTestCase { public void testIDEA106964() throws Exception { doTest5(false);} public void testIDEA107782() throws Exception { doTest5(false);} public void testInheritedWithDifferentArgsInTypeParams() throws Exception { doTest5(false);} + public void testInheritedWithDifferentArgsInTypeParams1() throws Exception { doTest5(false);} public void testIllegalForwardReferenceInTypeParameterDefinition() throws Exception { doTest5(false);} public void testIDEA57877() throws Exception { doTest5(false);} From 6bc99a3133468a3df0581b7423c42d4d4d474300 Mon Sep 17 00:00:00 2001 From: Anna Kozlova Date: Thu, 20 Mar 2014 19:55:46 +0100 Subject: [PATCH 03/36] IDEA-122548 Exception while inlining method --- .../inline/InlineMethodProcessor.java | 3 +-- .../MethodInsideChangeIfStatement.java | 26 +++++++++++++++++++ .../MethodInsideChangeIfStatement.java.after | 22 ++++++++++++++++ .../refactoring/inline/InlineMethodTest.java | 4 +++ 4 files changed, 53 insertions(+), 2 deletions(-) create mode 100644 java/java-tests/testData/refactoring/inlineMethod/MethodInsideChangeIfStatement.java create mode 100644 java/java-tests/testData/refactoring/inlineMethod/MethodInsideChangeIfStatement.java.after diff --git a/java/java-impl/src/com/intellij/refactoring/inline/InlineMethodProcessor.java b/java/java-impl/src/com/intellij/refactoring/inline/InlineMethodProcessor.java index c9649a026fbb..1225fe6cbe2a 100644 --- a/java/java-impl/src/com/intellij/refactoring/inline/InlineMethodProcessor.java +++ b/java/java-impl/src/com/intellij/refactoring/inline/InlineMethodProcessor.java @@ -48,7 +48,6 @@ import com.intellij.refactoring.BaseRefactoringProcessor; import com.intellij.refactoring.RefactoringBundle; import com.intellij.refactoring.introduceParameter.Util; import com.intellij.refactoring.listeners.RefactoringEventData; -import com.intellij.refactoring.listeners.RefactoringEventListener; import com.intellij.refactoring.rename.NonCodeUsageInfoFactory; import com.intellij.refactoring.rename.RenameJavaVariableProcessor; import com.intellij.refactoring.util.*; @@ -1265,7 +1264,7 @@ public class InlineMethodProcessor extends BaseRefactoringProcessor { if (parentStatement != null) { PsiElement parent = ref.getParent(); while (!parent.equals(parentStatement)) { - if (parent instanceof PsiStatement && !(parent instanceof PsiDeclarationStatement)) { + if (parent instanceof PsiExpressionStatement) { String text = "{\n}"; PsiBlockStatement blockStatement = (PsiBlockStatement)myFactory.createStatementFromText(text, null); blockStatement = (PsiBlockStatement)myCodeStyleManager.reformat(blockStatement); diff --git a/java/java-tests/testData/refactoring/inlineMethod/MethodInsideChangeIfStatement.java b/java/java-tests/testData/refactoring/inlineMethod/MethodInsideChangeIfStatement.java new file mode 100644 index 000000000000..1df5d47a74ab --- /dev/null +++ b/java/java-tests/testData/refactoring/inlineMethod/MethodInsideChangeIfStatement.java @@ -0,0 +1,26 @@ +import java.util.ArrayList; +import java.util.List; + +class Test { + List foo(String[] strs) + { + final List result = new ArrayList(); + int start = -1; + for (int i = 0; i < strs.length; i++) + { + if (idx(i) == 42 && start == -1) + { + start = i; + } else if (idx(i) != 24 && start != -1) + { + result.add("".substring(idx(start))); + } + } + return result; + } + + private static int idx(int i) { + return i; + } + +} \ No newline at end of file diff --git a/java/java-tests/testData/refactoring/inlineMethod/MethodInsideChangeIfStatement.java.after b/java/java-tests/testData/refactoring/inlineMethod/MethodInsideChangeIfStatement.java.after new file mode 100644 index 000000000000..e43e7e849a44 --- /dev/null +++ b/java/java-tests/testData/refactoring/inlineMethod/MethodInsideChangeIfStatement.java.after @@ -0,0 +1,22 @@ +import java.util.ArrayList; +import java.util.List; + +class Test { + List foo(String[] strs) + { + final List result = new ArrayList(); + int start = -1; + for (int i = 0; i < strs.length; i++) + { + if (i == 42 && start == -1) + { + start = i; + } else if (i != 24 && start != -1) + { + result.add("".substring(start)); + } + } + return result; + } + +} \ No newline at end of file diff --git a/java/java-tests/testSrc/com/intellij/refactoring/inline/InlineMethodTest.java b/java/java-tests/testSrc/com/intellij/refactoring/inline/InlineMethodTest.java index ec5ab9e53e96..c77b344f6722 100644 --- a/java/java-tests/testSrc/com/intellij/refactoring/inline/InlineMethodTest.java +++ b/java/java-tests/testSrc/com/intellij/refactoring/inline/InlineMethodTest.java @@ -260,6 +260,10 @@ public class InlineMethodTest extends LightRefactoringTestCase { doTest(true); } + public void testMethodInsideChangeIfStatement() throws Exception { + doTest(); + } + private void doTestInlineThisOnly() { @NonNls String fileName = "/refactoring/inlineMethod/" + getTestName(false) + ".java"; configureByFile(fileName); From 4a1dd3b7c7bc3aafed5096152659850dd8269aaa Mon Sep 17 00:00:00 2001 From: Oleg Sukhodolsky Date: Fri, 21 Mar 2014 08:29:56 +0400 Subject: [PATCH 04/36] RUBY-15071: restoring an old logic which fights with extra new-lines --- .../sm/runner/OutputLineSplitter.java | 3 ++- ...tputToGeneralTestsEventsConverterTest.java | 25 +++++++++++-------- 2 files changed, 17 insertions(+), 11 deletions(-) diff --git a/platform/smRunner/src/com/intellij/execution/testframework/sm/runner/OutputLineSplitter.java b/platform/smRunner/src/com/intellij/execution/testframework/sm/runner/OutputLineSplitter.java index 14a94953ab65..1ee0b76183ee 100644 --- a/platform/smRunner/src/com/intellij/execution/testframework/sm/runner/OutputLineSplitter.java +++ b/platform/smRunner/src/com/intellij/execution/testframework/sm/runner/OutputLineSplitter.java @@ -131,8 +131,9 @@ public abstract class OutputLineSplitter { myStdOutChunks.clear(); } + final boolean isTCLikeFakeOutput = chunks.size() == 1; for (OutputChunk chunk : chunks) { - onLineAvailable(chunk.getText(), chunk.getKey(), false); + onLineAvailable(chunk.getText(), chunk.getKey(), isTCLikeFakeOutput); } } diff --git a/platform/smRunner/testSrc/com/intellij/execution/testframework/sm/runner/OutputToGeneralTestsEventsConverterTest.java b/platform/smRunner/testSrc/com/intellij/execution/testframework/sm/runner/OutputToGeneralTestsEventsConverterTest.java index 409d9923b6ac..2fafd4957935 100644 --- a/platform/smRunner/testSrc/com/intellij/execution/testframework/sm/runner/OutputToGeneralTestsEventsConverterTest.java +++ b/platform/smRunner/testSrc/com/intellij/execution/testframework/sm/runner/OutputToGeneralTestsEventsConverterTest.java @@ -43,35 +43,40 @@ public class OutputToGeneralTestsEventsConverterTest extends BaseSMTRunnerTestCa } public void testLineBreaks_ServiceMessage() { - doCheckOutptut("\n##teamcity[enteredTheMatrix timestamp = '2011-06-03T13:00:08.259+0400']\n", "[stdout]\n", true); + doCheckOutptut("\n##teamcity[enteredTheMatrix timestamp = '2011-06-03T13:00:08.259+0400']\n", "", true); } public void testLineBreaks_NormalOutput() { doCheckOutptut("\na\nb\n\nc\n", "[stdout]\n" + - "[stdout]a\n" + - "[stdout]b\n" + + "[stdout]a" + "[stdout]\n" + - "[stdout]c\n", + "[stdout]b" + + "[stdout]\n" + + "[stdout]\n" + + "[stdout]c" + + "[stdout]\n", true); } public void testLineBreaks_OutptutAndCommands() { doCheckOutptut("\na\n##teamcity[enteredTheMatrix timestamp = '2011-06-03T13:00:08.259+0400']\nb\n##teamcity[enteredTheMatrix timestamp = '2011-06-03T13:00:08.259+0400']\n\nc\n", "[stdout]\n" + - "[stdout]a\n" + - "[stdout]b\n" + + "[stdout]a" + + "[stdout]b" + "[stdout]\n" + - "[stdout]c\n", + "[stdout]c" + + "[stdout]\n", true); } public void testLineBreaks_AutoSplitIfProcessHandlerDoestSupportIt() { doCheckOutptut("\na\n##teamcity[enteredTheMatrix timestamp = '2011-06-03T13:00:08.259+0400']\nb\n##teamcity[testCount count = '1' timestamp = '2011-06-03T13:00:08.259+0400']\n\nc\n", "[stdout]\n" + - "[stdout]a\n" + - "[stdout]b\n" + + "[stdout]a" + + "[stdout]b" + "[stdout]\n" + - "[stdout]c\n", + "[stdout]c" + + "[stdout]\n", false); } From 944dfe23c681bf0ad69e14c1eef8d91ecf8d2d11 Mon Sep 17 00:00:00 2001 From: Anton Makeev Date: Wed, 19 Mar 2014 12:16:27 +0100 Subject: [PATCH 05/36] Platform: OS X scrollbars (leak in AWT listener fixed + only keep scrollbar visible while mouse is moving over the scrollpane) --- .../util/ui/ButtonlessScrollBarUI.java | 60 +++++++++++++++---- 1 file changed, 47 insertions(+), 13 deletions(-) diff --git a/platform/platform-api/src/com/intellij/util/ui/ButtonlessScrollBarUI.java b/platform/platform-api/src/com/intellij/util/ui/ButtonlessScrollBarUI.java index 7433fa66eef7..7c740c9821cb 100644 --- a/platform/platform-api/src/com/intellij/util/ui/ButtonlessScrollBarUI.java +++ b/platform/platform-api/src/com/intellij/util/ui/ButtonlessScrollBarUI.java @@ -62,7 +62,9 @@ public class ButtonlessScrollBarUI extends BasicScrollBarUI { private final AdjustmentListener myAdjustmentListener; private final MouseMotionAdapter myMouseMotionListener; private final MouseAdapter myMouseListener; - private final AWTEventListener myAWTListener; + private final HierarchyListener myHierarchyListener; + private final AWTEventListener myAWTMouseListener; + private boolean myAWTMouseListenerAdded; public static final int DELAY_FRAMES = 4; public static final int FRAMES_COUNT = 10 + DELAY_FRAMES; @@ -126,19 +128,33 @@ public class ButtonlessScrollBarUI extends BasicScrollBarUI { } }; - myAWTListener = new AWTEventListener() { + myHierarchyListener = new HierarchyListener() { @Override + public void hierarchyChanged(HierarchyEvent e) { + if (e.getChanged() == scrollbar + && (HierarchyEvent.DISPLAYABILITY_CHANGED & e.getChangeFlags()) != 0) { + updateAWTMotionListener(false); + } + } + }; + myAWTMouseListener = new AWTEventListener() { public void eventDispatched(AWTEvent event) { if (event.getID() == MouseEvent.MOUSE_MOVED) { - // user is moving mouse outside of the scrollbar and fade-out hasn't started yet - if (!myMouseOverScrollbar && !myMacScrollbarHidden && myMacScrollbarFadeLevel == 0) { - resetMacScrollbarFadeout(); + + // user is moving inside the scrollpane of the scrollbar and fade-out hasn't started yet + Container scrollpane = SwingUtilities.getAncestorOfClass(JScrollPane.class, scrollbar); + if (scrollpane != null) { + Point loc = ((MouseEvent)event).getLocationOnScreen(); + SwingUtilities.convertPointFromScreen(loc, scrollpane); + if (scrollpane.contains(loc) && !myMacScrollbarHidden && myMacScrollbarFadeLevel == 0) { + resetMacScrollbarFadeout(); + } } } } }; } - + protected static boolean isMacScrollbar() { return UIUtil.isUnderNativeMacLookAndFeel() && !Registry.is("ui.no.mac.scrollbar"); } @@ -252,11 +268,27 @@ public class ButtonlessScrollBarUI extends BasicScrollBarUI { scrollbar.addAdjustmentListener(myAdjustmentListener); scrollbar.addMouseListener(myMouseListener); scrollbar.addMouseMotionListener(myMouseMotionListener); - //Toolkit.getDefaultToolkit().addAWTEventListener(myAWTListener, AWTEvent.MOUSE_MOTION_EVENT_MASK); - + + scrollbar.addHierarchyListener(myHierarchyListener); + updateAWTMotionListener(false); + resetMacScrollbarFadeout(); } + private void updateAWTMotionListener(boolean forceRemove) { + boolean shouldAdd = scrollbar.isDisplayable(); + + if (myAWTMouseListenerAdded && (!shouldAdd || forceRemove)) { + Toolkit.getDefaultToolkit().removeAWTEventListener(myAWTMouseListener); + myAWTMouseListenerAdded = false; + } + + if (!myAWTMouseListenerAdded && shouldAdd && !forceRemove) { + Toolkit.getDefaultToolkit().addAWTEventListener(myAWTMouseListener, AWTEvent.MOUSE_MOTION_EVENT_MASK); + myAWTMouseListenerAdded = true; + } + } + private void initRegularThumbAnimator() { myThumbFadeAnimator = new Animator("Regular scrollbar thumb animator", FRAMES_COUNT, FRAMES_COUNT * 50, false) { @Override @@ -333,6 +365,13 @@ public class ButtonlessScrollBarUI extends BasicScrollBarUI { super.uninstallListeners(); } + scrollbar.removeAdjustmentListener(myAdjustmentListener); + scrollbar.removeMouseListener(myMouseListener); + scrollbar.removeMouseMotionListener(myMouseMotionListener); + + scrollbar.removeHierarchyListener(myHierarchyListener); + updateAWTMotionListener(true); + Disposer.dispose(myThumbFadeAnimator); myThumbFadeAnimator = null; @@ -340,11 +379,6 @@ public class ButtonlessScrollBarUI extends BasicScrollBarUI { myMouseOverScrollbarExpandAnimator = null; Disposer.dispose(myMacScrollbarFadeAnimator); myMacScrollbarFadeAnimator = null; - - scrollbar.removeAdjustmentListener(myAdjustmentListener); - scrollbar.removeMouseListener(myMouseListener); - scrollbar.removeMouseMotionListener(myMouseMotionListener); - //Toolkit.getDefaultToolkit().removeAWTEventListener(myAWTListener); } @Override From 8f9d0abaa7c7bab6dfac6cf934ad215d2d319767 Mon Sep 17 00:00:00 2001 From: Anton Makeev Date: Wed, 19 Mar 2014 19:36:06 +0100 Subject: [PATCH 06/36] Platform: OS X scrollbars (do not directly cast view's parents to scrollbar) --- .../match/ArrangementMatchingRulesControl.java | 9 +++++---- .../lookup/impl/CompletionExtender.java | 8 +++++--- .../intellij/ui/components/JBScrollPane.java | 17 +++++++++++++++++ .../intellij/ui/components/ZoomingDelegate.java | 3 +-- .../maven/indices/MavenArtifactSearchPanel.java | 14 ++++++-------- 5 files changed, 34 insertions(+), 17 deletions(-) diff --git a/platform/lang-impl/src/com/intellij/application/options/codeStyle/arrangement/match/ArrangementMatchingRulesControl.java b/platform/lang-impl/src/com/intellij/application/options/codeStyle/arrangement/match/ArrangementMatchingRulesControl.java index 497790713243..c972c6bb38b0 100644 --- a/platform/lang-impl/src/com/intellij/application/options/codeStyle/arrangement/match/ArrangementMatchingRulesControl.java +++ b/platform/lang-impl/src/com/intellij/application/options/codeStyle/arrangement/match/ArrangementMatchingRulesControl.java @@ -16,7 +16,6 @@ package com.intellij.application.options.codeStyle.arrangement.match; import com.intellij.application.options.codeStyle.arrangement.ArrangementConstants; -import com.intellij.psi.codeStyle.arrangement.std.ArrangementStandardSettingsManager; import com.intellij.application.options.codeStyle.arrangement.color.ArrangementColorsProvider; import com.intellij.application.options.codeStyle.arrangement.ui.ArrangementEditorAware; import com.intellij.application.options.codeStyle.arrangement.ui.ArrangementRepresentationAware; @@ -28,8 +27,10 @@ import com.intellij.openapi.diagnostic.Logger; import com.intellij.psi.codeStyle.arrangement.match.StdArrangementEntryMatcher; import com.intellij.psi.codeStyle.arrangement.match.StdArrangementMatchRule; import com.intellij.psi.codeStyle.arrangement.model.ArrangementAtomMatchCondition; +import com.intellij.psi.codeStyle.arrangement.std.ArrangementStandardSettingsManager; import com.intellij.psi.codeStyle.arrangement.std.ArrangementUiComponent; import com.intellij.psi.codeStyle.arrangement.std.StdArrangementTokens; +import com.intellij.ui.components.JBScrollPane; import com.intellij.ui.table.JBTable; import com.intellij.util.ui.AbstractTableCellEditor; import gnu.trove.TIntArrayList; @@ -349,10 +350,10 @@ public class ArrangementMatchingRulesControl extends JBTable { } myEditorRow = rowToEdit + 1; ArrangementEditorComponent editor = new ArrangementEditorComponent(this, myEditorRow, myEditor); - Container parent = getParent(); int width = getBounds().width; - if (parent instanceof JViewport) { - width -= ((JScrollPane)parent.getParent()).getVerticalScrollBar().getWidth(); + JScrollPane scrollPane = JBScrollPane.findScrollPane(getParent()); + if (scrollPane != null) { + width -= scrollPane.getVerticalScrollBar().getWidth(); } editor.applyAvailableWidth(width); myEditor.reset(rowToEdit); diff --git a/platform/lang-impl/src/com/intellij/codeInsight/lookup/impl/CompletionExtender.java b/platform/lang-impl/src/com/intellij/codeInsight/lookup/impl/CompletionExtender.java index 14d471e082fc..0b638cde5891 100644 --- a/platform/lang-impl/src/com/intellij/codeInsight/lookup/impl/CompletionExtender.java +++ b/platform/lang-impl/src/com/intellij/codeInsight/lookup/impl/CompletionExtender.java @@ -16,6 +16,7 @@ package com.intellij.codeInsight.lookup.impl; import com.intellij.ui.ListExpandableItemsHandler; +import com.intellij.ui.components.JBScrollPane; import org.jetbrains.annotations.NotNull; import javax.swing.*; @@ -31,9 +32,10 @@ public class CompletionExtender extends ListExpandableItemsHandler { list.addComponentListener(new ComponentAdapter() { @Override public void componentShown(ComponentEvent e) { - if (myComponent.getParent() != null && myComponent.getParent().getParent() instanceof JScrollPane) { - final JScrollBar verticalScrollBar = ((JScrollPane)myComponent.getParent().getParent()).getVerticalScrollBar(); - final JScrollBar horizontalScrollBar = ((JScrollPane)myComponent.getParent().getParent()).getVerticalScrollBar(); + JScrollPane scrollPane = JBScrollPane.findScrollPane(myComponent); + if (scrollPane != null) { + final JScrollBar verticalScrollBar = scrollPane.getVerticalScrollBar(); + final JScrollBar horizontalScrollBar = scrollPane.getVerticalScrollBar(); final AdjustmentListener listener = new AdjustmentListener() { @Override public void adjustmentValueChanged(AdjustmentEvent e) { diff --git a/platform/platform-api/src/com/intellij/ui/components/JBScrollPane.java b/platform/platform-api/src/com/intellij/ui/components/JBScrollPane.java index 4311a6e4f909..72c85333b773 100644 --- a/platform/platform-api/src/com/intellij/ui/components/JBScrollPane.java +++ b/platform/platform-api/src/com/intellij/ui/components/JBScrollPane.java @@ -60,6 +60,23 @@ public class JBScrollPane extends JScrollPane { init(); } + public static JScrollPane findScrollPane(Component c) { + if (c == null) return null; + + if (!(c instanceof JViewport)) { + c = c.getParent(); + if (!(c instanceof JViewport)) return null; + } + + c = c.getParent(); + if (c instanceof JLayeredPane) { + c = c.getParent(); + } + if (!(c instanceof JBScrollPane)) return null; + + return (JBScrollPane)c; + } + @Override public void setVerticalScrollBar(JScrollBar c) { JScrollBar old = getVerticalScrollBar(); diff --git a/platform/platform-api/src/com/intellij/ui/components/ZoomingDelegate.java b/platform/platform-api/src/com/intellij/ui/components/ZoomingDelegate.java index 17d754de1470..998c51ee825f 100644 --- a/platform/platform-api/src/com/intellij/ui/components/ZoomingDelegate.java +++ b/platform/platform-api/src/com/intellij/ui/components/ZoomingDelegate.java @@ -86,8 +86,7 @@ public class ZoomingDelegate { } protected void scrollTo(int voffset, int hoffset) { - JViewport viewport = (JViewport)myViewportComponent; - JScrollPane pane = (JScrollPane)viewport.getParent(); + JScrollPane pane = JBScrollPane.findScrollPane(myViewportComponent); JScrollBar vsb = pane.getVerticalScrollBar(); vsb.setValue(voffset); JScrollBar hsb = pane.getHorizontalScrollBar(); diff --git a/plugins/maven/src/main/java/org/jetbrains/idea/maven/indices/MavenArtifactSearchPanel.java b/plugins/maven/src/main/java/org/jetbrains/idea/maven/indices/MavenArtifactSearchPanel.java index de2de97c7051..eae5dc3d8225 100644 --- a/plugins/maven/src/main/java/org/jetbrains/idea/maven/indices/MavenArtifactSearchPanel.java +++ b/plugins/maven/src/main/java/org/jetbrains/idea/maven/indices/MavenArtifactSearchPanel.java @@ -22,6 +22,7 @@ import com.intellij.openapi.project.Project; import com.intellij.openapi.util.Comparing; import com.intellij.openapi.util.Pair; import com.intellij.ui.*; +import com.intellij.ui.components.JBScrollPane; import com.intellij.ui.treeStructure.Tree; import com.intellij.util.Alarm; import com.intellij.util.ui.AbstractLayoutManager; @@ -346,14 +347,11 @@ public class MavenArtifactSearchPanel extends JPanel { Insets insets = tree.getInsets(); w -= insets.left + insets.right; - Container parent = tree.getParent(); - if (parent != null) { - Container parentParent = parent.getParent(); - if (parentParent instanceof JScrollPane) { - JScrollBar sb = ((JScrollPane)parentParent).getVerticalScrollBar(); - if (sb != null) { - w -= sb.getWidth(); - } + JScrollPane scrollPane = JBScrollPane.findScrollPane(tree); + if (scrollPane != null) { + JScrollBar sb = scrollPane.getVerticalScrollBar(); + if (sb != null) { + w -= sb.getWidth(); } } return w; From e6c34e4353a0f71034daf3c1ea35b73366f70355 Mon Sep 17 00:00:00 2001 From: Max Medvedev Date: Fri, 21 Mar 2014 11:16:26 +0400 Subject: [PATCH 07/36] logging --- .../org/jetbrains/plugins/groovy/annotator/GroovyAnnotator.java | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/plugins/groovy/src/org/jetbrains/plugins/groovy/annotator/GroovyAnnotator.java b/plugins/groovy/src/org/jetbrains/plugins/groovy/annotator/GroovyAnnotator.java index f03cc15292a5..44aabf8db5c1 100644 --- a/plugins/groovy/src/org/jetbrains/plugins/groovy/annotator/GroovyAnnotator.java +++ b/plugins/groovy/src/org/jetbrains/plugins/groovy/annotator/GroovyAnnotator.java @@ -970,7 +970,7 @@ public class GroovyAnnotator extends GroovyElementVisitor { private static void registerFix(Annotation annotation, LocalQuickFix fix, PsiElement place) { final InspectionManager manager = InspectionManager.getInstance(place.getProject()); - assert !place.getTextRange().isEmpty(); + assert !place.getTextRange().isEmpty() : place.getContainingFile().getName(); final ProblemDescriptor descriptor = manager.createProblemDescriptor(place, place, annotation.getMessage(), annotation.getHighlightType(), true, LocalQuickFix.EMPTY_ARRAY); From 37cf7a50c2e4c6326066d842aa0c8d7de8c5dcb2 Mon Sep 17 00:00:00 2001 From: Max Medvedev Date: Fri, 21 Mar 2014 11:57:06 +0400 Subject: [PATCH 08/36] Empty descriptor PSI anchor fixed --- .../org/jetbrains/plugins/groovy/annotator/GroovyAnnotator.java | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/plugins/groovy/src/org/jetbrains/plugins/groovy/annotator/GroovyAnnotator.java b/plugins/groovy/src/org/jetbrains/plugins/groovy/annotator/GroovyAnnotator.java index 44aabf8db5c1..51e507df0e6e 100644 --- a/plugins/groovy/src/org/jetbrains/plugins/groovy/annotator/GroovyAnnotator.java +++ b/plugins/groovy/src/org/jetbrains/plugins/groovy/annotator/GroovyAnnotator.java @@ -1795,7 +1795,7 @@ public class GroovyAnnotator extends GroovyElementVisitor { if (containingClass != null) { final PsiModifierList list = containingClass.getModifierList(); if (list != null && !list.hasModifierProperty(ABSTRACT)) { - registerFix(annotation, new GrModifierFix(containingClass, ABSTRACT, false, true, GrModifierFix.MODIFIER_LIST), list); + registerFix(annotation, new GrModifierFix(containingClass, ABSTRACT, false, true, GrModifierFix.MODIFIER_LIST_OWNER), containingClass); } } } From a4747a994bd48d98a5cfc18c07ec967473311aa5 Mon Sep 17 00:00:00 2001 From: Vladimir Krivosheev Date: Fri, 21 Mar 2014 08:48:20 +0100 Subject: [PATCH 09/36] nodejs 136.1205 published --- platform/platform-resources/src/brokenPlugins.txt | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/platform/platform-resources/src/brokenPlugins.txt b/platform/platform-resources/src/brokenPlugins.txt index fbe99dd6d4c4..0796f382f06a 100644 --- a/platform/platform-resources/src/brokenPlugins.txt +++ b/platform/platform-resources/src/brokenPlugins.txt @@ -2,7 +2,7 @@ // Each line contains plugin ID and list of versions that are broken. // If plugin name or version contains a space you can quote it like in command line. -NodeJS 134.1276 134.1163 134.1145 134.1081 134.1039 134.985 134.680 134.31 134.307 134.262 134.198 134.125 +NodeJS 134.1276 134.1163 134.1145 134.1081 134.1039 134.985 134.680 134.31 134.307 134.262 134.198 134.125 136.1141 com.jetbrains.php 133.982 133.679 133.51 133.326 131.98 131.374 131.332 131.235 131.205 130.1639 130.1481 130.1176 129.91 129.814 129.672 129.362 127.67 127.100 126.334 123.66 122.875 121.62 121.390 121.215 121.12 com.jetbrains.lang.ejs 131.17 131.12 com.jetbrains.twig 133.51 130.1639 From 545e3533f790d6fe79efe34221650fc6b3890a56 Mon Sep 17 00:00:00 2001 From: Bas Leijdekkers Date: Thu, 20 Mar 2014 20:18:52 +0100 Subject: [PATCH 10/36] fix property value --- .../hg4idea/resources/org/zmlx/hg4idea/HgVcsMessages.properties | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/plugins/hg4idea/resources/org/zmlx/hg4idea/HgVcsMessages.properties b/plugins/hg4idea/resources/org/zmlx/hg4idea/HgVcsMessages.properties index af459be969f5..c1a2765a903a 100644 --- a/plugins/hg4idea/resources/org/zmlx/hg4idea/HgVcsMessages.properties +++ b/plugins/hg4idea/resources/org/zmlx/hg4idea/HgVcsMessages.properties @@ -80,7 +80,7 @@ hg4idea.init.already.under.hg.option.create.repo.here=Create new repository here hg4idea.init.created.notification.title=Mercurial repository created hg4idea.init.created.notification.description=Repository was created in {0} hg4idea.init.error.title=Error creating Mercurial repository -hg4idea.init.error.description=Couldn't create a Mercurial repository in {0} +hg4idea.init.error.description=Couldn''t create a Mercurial repository in {0} hg4idea.move.progress=Moving files in the VCS... From f8551ee32a15d0aba814e5636ba858365e962d0d Mon Sep 17 00:00:00 2001 From: Bas Leijdekkers Date: Fri, 21 Mar 2014 09:09:44 +0100 Subject: [PATCH 11/36] IDEA-122565 (CVS: files shown not under version control in 13.1) --- .../cvsSupport2/cvsstatuses/CvsChangeProvider.java | 12 ++++++------ 1 file changed, 6 insertions(+), 6 deletions(-) diff --git a/plugins/cvs/cvs-plugin/src/com/intellij/cvsSupport2/cvsstatuses/CvsChangeProvider.java b/plugins/cvs/cvs-plugin/src/com/intellij/cvsSupport2/cvsstatuses/CvsChangeProvider.java index aa6cde45c22e..ee82d0874566 100644 --- a/plugins/cvs/cvs-plugin/src/com/intellij/cvsSupport2/cvsstatuses/CvsChangeProvider.java +++ b/plugins/cvs/cvs-plugin/src/com/intellij/cvsSupport2/cvsstatuses/CvsChangeProvider.java @@ -288,13 +288,13 @@ public class CvsChangeProvider implements ChangeProvider { return; } final CvsInfo info = myEntriesManager.getCvsInfoFor(dir); - if (info.getIgnoreFilter().shouldBeIgnored(dir.getName())) { - builder.processIgnoredFile(dir); - return; - } if (info.getRepository() == null) { - // don't report unversioned directories as switched (IDEADEV-17178) - builder.processUnversionedFile(dir); + if (info.getIgnoreFilter().shouldBeIgnored(dir.getName())) { + builder.processIgnoredFile(dir); + } + else { + builder.processUnversionedFile(dir); + } return; } final String dirTag = info.getStickyTag(); From c33e62c61cb6fb67627812781743f708dc1d06fe Mon Sep 17 00:00:00 2001 From: Alexander Zolotov Date: Fri, 21 Mar 2014 12:19:41 +0400 Subject: [PATCH 12/36] TemplateState: yet another debug info --- .../codeInsight/template/impl/TemplateState.java | 16 +++++++++++++--- 1 file changed, 13 insertions(+), 3 deletions(-) diff --git a/platform/lang-impl/src/com/intellij/codeInsight/template/impl/TemplateState.java b/platform/lang-impl/src/com/intellij/codeInsight/template/impl/TemplateState.java index 0d3c52e41ff8..ccac27bb3f98 100644 --- a/platform/lang-impl/src/com/intellij/codeInsight/template/impl/TemplateState.java +++ b/platform/lang-impl/src/com/intellij/codeInsight/template/impl/TemplateState.java @@ -362,11 +362,11 @@ public class TemplateState implements Disposable { mySegments.addSegment(segmentOffset, segmentOffset); } - LOG.assertTrue(myTemplateRange.isValid(), myTemplateRange.toString()); + LOG.assertTrue(myTemplateRange.isValid(), getRangesDebugInfo()); calcResults(false); - LOG.assertTrue(myTemplateRange.isValid(), myTemplateRange.toString()); + LOG.assertTrue(myTemplateRange.isValid(), getRangesDebugInfo()); calcResults(false); //Fixed SCR #[vk500] : all variables should be recalced twice on start. - LOG.assertTrue(myTemplateRange.isValid(), myTemplateRange.toString()); + LOG.assertTrue(myTemplateRange.isValid(), getRangesDebugInfo()); doReformat(null); int nextVariableNumber = getNextVariableNumber(-1); @@ -392,6 +392,16 @@ public class TemplateState implements Disposable { }); } + private String getRangesDebugInfo() { + return myTemplateRange.toString() + + "\ntemplateKey: " + + myTemplate.getKey() + + "\ntemplateText: " + + myTemplate.getTemplateText() + + "\ntemplateText: " + + myTemplate.getTemplateText(); + } + private void doReformat(final TextRange range) { RangeMarker rangeMarker = null; if (range != null) { From c351f3b066978963bfb5ee5dd6e18ac48c44047c Mon Sep 17 00:00:00 2001 From: Alexander Zolotov Date: Fri, 21 Mar 2014 12:20:37 +0400 Subject: [PATCH 13/36] Add toString method in diagnostic purposes --- .../com/intellij/injected/editor/RangeMarkerWindow.java | 9 ++++++++- 1 file changed, 8 insertions(+), 1 deletion(-) diff --git a/platform/lang-impl/src/com/intellij/injected/editor/RangeMarkerWindow.java b/platform/lang-impl/src/com/intellij/injected/editor/RangeMarkerWindow.java index 9a29e09d0a92..fbe0d3070009 100644 --- a/platform/lang-impl/src/com/intellij/injected/editor/RangeMarkerWindow.java +++ b/platform/lang-impl/src/com/intellij/injected/editor/RangeMarkerWindow.java @@ -1,5 +1,5 @@ /* - * Copyright 2000-2012 JetBrains s.r.o. + * 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. @@ -157,4 +157,11 @@ public class RangeMarkerWindow implements RangeMarkerEx { public void dispose() { myHostMarker.dispose(); } + + @Override + public String toString() { + return "RangeMarkerWindow" + (isGreedyToLeft() ? "[" : "(") + (isValid() ? "valid" : "invalid") + "," + + getStartOffset() + "," + getEndOffset() + + (isGreedyToRight() ? "]" : ")") + " " + getId(); + } } From ba95020e8a63c6e3be015c096aa54a48da8c6b77 Mon Sep 17 00:00:00 2001 From: Vassiliy Date: Fri, 21 Mar 2014 12:36:21 +0400 Subject: [PATCH 14/36] Balloons: fix for inverted "contains" condition (causes NPE and wrong behavior) --- platform/platform-impl/src/com/intellij/ui/BalloonImpl.java | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/platform/platform-impl/src/com/intellij/ui/BalloonImpl.java b/platform/platform-impl/src/com/intellij/ui/BalloonImpl.java index 1277d6df7ced..486f88b00945 100644 --- a/platform/platform-impl/src/com/intellij/ui/BalloonImpl.java +++ b/platform/platform-impl/src/com/intellij/ui/BalloonImpl.java @@ -502,7 +502,7 @@ public class BalloonImpl implements Balloon, IdeTooltip.Ui { myLayeredPane.remove(myComp); createComponent(); - if (!new Rectangle(myComp.getSize()).contains(new Rectangle(myLayeredPane.getSize()))) { // Balloon is bigger than window, don't show it at all. + if (!new Rectangle(myLayeredPane.getSize()).contains(new Rectangle(myComp.getSize()))) { // Balloon is bigger than window, don't show it at all. myLayeredPane = null; hide(); return; From ea9d3c6736167feee4132b8c6be3d3efe1036505 Mon Sep 17 00:00:00 2001 From: Vladimir Krivosheev Date: Fri, 21 Mar 2014 09:53:56 +0100 Subject: [PATCH 15/36] =?UTF-8?q?extract=20BasicGutterContentProvider=20?= =?UTF-8?q?=E2=80=94=20we=20need=20gutter=20content=20provider=20in=20any?= =?UTF-8?q?=20case=20to=20provide=20pretty=20UI=20(in/out=20markers)?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- .../console/BasicGutterContentProvider.java | 77 +++++++++++++++++++ .../console/GutterContentProvider.java | 2 +- .../console/LanguageConsoleBuilder.java | 18 +---- 3 files changed, 82 insertions(+), 15 deletions(-) create mode 100644 platform/lang-impl/src/com/intellij/execution/console/BasicGutterContentProvider.java diff --git a/platform/lang-impl/src/com/intellij/execution/console/BasicGutterContentProvider.java b/platform/lang-impl/src/com/intellij/execution/console/BasicGutterContentProvider.java new file mode 100644 index 000000000000..ec146652aae8 --- /dev/null +++ b/platform/lang-impl/src/com/intellij/execution/console/BasicGutterContentProvider.java @@ -0,0 +1,77 @@ +package com.intellij.execution.console; + +import com.intellij.openapi.editor.Document; +import com.intellij.openapi.editor.Editor; +import com.intellij.openapi.util.text.StringUtil; +import com.intellij.ui.JBColor; +import org.jetbrains.annotations.NotNull; +import org.jetbrains.annotations.Nullable; + +import java.awt.*; + +public class BasicGutterContentProvider extends GutterContentProvider { + public static final String EVAL_OUT_MARKER = "\u200C"; + public static final String EVAL_IN_MARKER = EVAL_OUT_MARKER + EVAL_OUT_MARKER; + + @Override + public boolean hasText() { + return false; + } + + @Nullable + @Override + public String getText(int line, @NotNull Editor editor) { + return null; + } + + @Nullable + @Override + public String getToolTip(int line, @NotNull Editor editor) { + return null; + } + + @Override + public void doAction(int line, @NotNull Editor editor) { + } + + @Override + public void beforeEvaluate(@NotNull Editor editor) { + Document document = editor.getDocument(); + document.insertString(document.getTextLength(), EVAL_IN_MARKER); + } + + @Override + public boolean drawIcon(int line, @NotNull Graphics g, int y, @NotNull Editor editor) { + int markerCount = getMarkerCount(line, editor.getDocument()); + if (markerCount == EVAL_OUT_MARKER.length() || markerCount == EVAL_IN_MARKER.length()) { + g.setColor(JBColor.GRAY); + g.drawString(markerCount == EVAL_IN_MARKER.length() ? ">" : "<", 3, y); + return true; + } + return false; + } + + @Override + public final boolean isShowSeparatorLine(int line, @NotNull Editor editor) { + Document document = editor.getDocument(); + if ((line + 1) >= document.getLineCount()) { + return true; + } + + int markerCount = getMarkerCount(line, document); + if (markerCount == EVAL_IN_MARKER.length()) { + return getMarkerCount(line + 1, document) != EVAL_OUT_MARKER.length(); + } + else { + return doIsShowSeparatorLine(line, editor, document); + } + } + + protected boolean doIsShowSeparatorLine(int line, @NotNull Editor editor, @NotNull Document document) { + return true; + } + + private static int getMarkerCount(int line, @NotNull Document document) { + return StringUtil.countChars(document.getImmutableCharSequence(), EVAL_IN_MARKER.charAt(0), document.getLineStartOffset(line), true); + } +} \ No newline at end of file diff --git a/platform/lang-impl/src/com/intellij/execution/console/GutterContentProvider.java b/platform/lang-impl/src/com/intellij/execution/console/GutterContentProvider.java index c2eed1a09cd3..d0a4691c3d9f 100644 --- a/platform/lang-impl/src/com/intellij/execution/console/GutterContentProvider.java +++ b/platform/lang-impl/src/com/intellij/execution/console/GutterContentProvider.java @@ -28,7 +28,7 @@ public abstract class GutterContentProvider { public abstract void doAction(int line, @NotNull Editor editor); - public abstract void drawIcon(int line, @NotNull Graphics g, int y, @NotNull Editor editor); + public abstract boolean drawIcon(int line, @NotNull Graphics g, int y, @NotNull Editor editor); public boolean isShowSeparatorLine(int line, @NotNull Editor editor) { return true; diff --git a/platform/lang-impl/src/com/intellij/execution/console/LanguageConsoleBuilder.java b/platform/lang-impl/src/com/intellij/execution/console/LanguageConsoleBuilder.java index 9bbd5b53fd50..185379c60f92 100644 --- a/platform/lang-impl/src/com/intellij/execution/console/LanguageConsoleBuilder.java +++ b/platform/lang-impl/src/com/intellij/execution/console/LanguageConsoleBuilder.java @@ -179,7 +179,6 @@ public final class LanguageConsoleBuilder { } private final static class GutteredLanguageConsole extends LanguageConsoleImpl { - @Nullable private final GutterContentProvider gutterContentProvider; @Nullable private final PairFunction psiFileFactory; @@ -193,13 +192,13 @@ public final class LanguageConsoleBuilder { setShowSeparatorLine(false); - this.gutterContentProvider = gutterContentProvider; + this.gutterContentProvider = gutterContentProvider == null ? new BasicGutterContentProvider() : gutterContentProvider; this.psiFileFactory = psiFileFactory; } @Override boolean isHistoryViewerForceAdditionalColumnsUsage() { - return gutterContentProvider == null; + return false; } @Override @@ -222,7 +221,7 @@ public final class LanguageConsoleBuilder { protected void setupEditorDefault(@NotNull EditorEx editor) { super.setupEditorDefault(editor); - if (editor == getConsoleEditor() || gutterContentProvider == null) { + if (editor == getConsoleEditor()) { return; } @@ -283,12 +282,7 @@ public final class LanguageConsoleBuilder { @Override protected void doAddPromptToHistory() { - if (gutterContentProvider == null) { - super.doAddPromptToHistory(); - } - else { - gutterContentProvider.beforeEvaluate(getHistoryViewer()); - } + gutterContentProvider.beforeEvaluate(getHistoryViewer()); } private final class GutterUpdateScheduler extends DocumentAdapter implements DocumentBulkUpdateListener { @@ -350,10 +344,7 @@ public final class LanguageConsoleBuilder { private void documentCleared() { gutterSizeUpdater = null; - lineEndGutter.documentCleared(); - - assert gutterContentProvider != null; gutterContentProvider.documentCleared(getHistoryViewer()); } @@ -419,7 +410,6 @@ public final class LanguageConsoleBuilder { int actualStartLine = startLine == 0 ? 0 : startLine - 1; int y = (actualStartLine + 1) * lineHeight; g.setColor(editor.getColorsScheme().getColor(EditorColors.INDENT_GUIDE_COLOR)); - assert gutterContentProvider != null; for (int visualLine = actualStartLine; visualLine < endLine; visualLine++) { if (gutterContentProvider.isShowSeparatorLine(editor.visualToLogicalPosition(new VisualPosition(visualLine, 0)).line, editor)) { g.drawLine(0, y, clip.width, y); From 062c0f1be799bc4245c8954f8865aed267604c2e Mon Sep 17 00:00:00 2001 From: Oleg Sukhodolsky Date: Fri, 21 Mar 2014 13:16:04 +0400 Subject: [PATCH 16/36] EA-55032: there is no reason to request UI update if update queue has been already disposed --- .../com/intellij/execution/console/LanguageConsoleImpl.java | 3 +++ 1 file changed, 3 insertions(+) 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 c15e00acfbf3..bb646a81ee46 100644 --- a/platform/lang-impl/src/com/intellij/execution/console/LanguageConsoleImpl.java +++ b/platform/lang-impl/src/com/intellij/execution/console/LanguageConsoleImpl.java @@ -583,6 +583,9 @@ public class LanguageConsoleImpl implements Disposable, TypeSafeDataProvider { public void queueUiUpdate(boolean forceScrollToEnd) { myForceScrollToEnd.compareAndSet(false, forceScrollToEnd); + if (myUpdateQueue.isDisposed()) { + return; + } myUpdateQueue.request(); } From ae3300276e6eae887196492692cafe7bbe5883cc Mon Sep 17 00:00:00 2001 From: "Egor.Ushakov" Date: Fri, 21 Mar 2014 13:48:42 +0400 Subject: [PATCH 17/36] update navbar on frame selection --- .../com/intellij/debugger/ui/FramesPanel.java | 20 ++++++++++++++++++- 1 file changed, 19 insertions(+), 1 deletion(-) diff --git a/java/debugger/impl/src/com/intellij/debugger/ui/FramesPanel.java b/java/debugger/impl/src/com/intellij/debugger/ui/FramesPanel.java index 52bcf8acce32..e17b8af10827 100644 --- a/java/debugger/impl/src/com/intellij/debugger/ui/FramesPanel.java +++ b/java/debugger/impl/src/com/intellij/debugger/ui/FramesPanel.java @@ -17,6 +17,7 @@ package com.intellij.debugger.ui; import com.intellij.debugger.DebuggerBundle; import com.intellij.debugger.DebuggerInvocationUtil; +import com.intellij.debugger.SourcePosition; import com.intellij.debugger.actions.DebuggerActions; import com.intellij.debugger.engine.DebugProcessImpl; import com.intellij.debugger.engine.DebuggerManagerThreadImpl; @@ -59,7 +60,9 @@ import com.intellij.ui.components.panels.Wrapper; import com.intellij.util.Alarm; import com.sun.jdi.ObjectCollectedException; import com.sun.jdi.VMDisconnectedException; +import org.jetbrains.annotations.NonNls; import org.jetbrains.annotations.NotNull; +import org.jetbrains.annotations.Nullable; import javax.swing.*; import javax.swing.border.EmptyBorder; @@ -76,7 +79,7 @@ import java.util.List; import java.util.concurrent.atomic.AtomicBoolean; import java.util.concurrent.atomic.AtomicLong; -public class FramesPanel extends UpdatableDebuggerView { +public class FramesPanel extends UpdatableDebuggerView implements DataProvider { private static final Icon FILTER_STACK_FRAMES_ICON = AllIcons.Debugger.Class_filter; private final JComboBox myThreadsCombo; @@ -147,6 +150,21 @@ public class FramesPanel extends UpdatableDebuggerView { return myStateManager; } + @Nullable + @Override + public Object getData(@NonNls String dataId) { + if (CommonDataKeys.PSI_FILE.is(dataId)) { + DebuggerContextImpl context = myStateManager.getContext(); + if (context != null) { + SourcePosition position = context.getSourcePosition(); + if (position != null) { + return position.getFile(); + } + } + } + return null; + } + private class FramesListener implements ListSelectionListener { boolean myIsEnabled = true; From d6873556e4d0221b2a4483596a8c4e06719b33f9 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Yann=20C=C3=A9bron?= Date: Fri, 21 Mar 2014 11:06:11 +0100 Subject: [PATCH 18/36] IDEA-72979 DOM: make DelimitedListConverter work nicely with TagValues --- .../converters/DelimitedListConverter.java | 38 +++++++++---------- 1 file changed, 19 insertions(+), 19 deletions(-) diff --git a/xml/dom-openapi/src/com/intellij/util/xml/converters/DelimitedListConverter.java b/xml/dom-openapi/src/com/intellij/util/xml/converters/DelimitedListConverter.java index 079495541c64..f7b946dec9cb 100644 --- a/xml/dom-openapi/src/com/intellij/util/xml/converters/DelimitedListConverter.java +++ b/xml/dom-openapi/src/com/intellij/util/xml/converters/DelimitedListConverter.java @@ -1,5 +1,5 @@ /* - * Copyright 2000-2009 JetBrains s.r.o. + * 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. @@ -14,12 +14,6 @@ * limitations under the License. */ -/* - * Created by IntelliJ IDEA. - * User: Sergey.Vasiliev - * Date: Nov 13, 2006 - * Time: 4:37:22 PM - */ package com.intellij.util.xml.converters; import com.intellij.codeInsight.daemon.EmptyResolveMessageProvider; @@ -33,10 +27,8 @@ import com.intellij.psi.PsiReferenceBase; import com.intellij.util.ArrayUtil; import com.intellij.util.Function; import com.intellij.util.IncorrectOperationException; -import com.intellij.util.xml.ConvertContext; -import com.intellij.util.xml.CustomReferenceConverter; -import com.intellij.util.xml.GenericDomValue; -import com.intellij.util.xml.ResolvingConverter; +import com.intellij.util.xml.*; +import com.intellij.xml.util.XmlTagUtil; import org.jetbrains.annotations.NonNls; import org.jetbrains.annotations.NotNull; import org.jetbrains.annotations.Nullable; @@ -76,7 +68,7 @@ public abstract class DelimitedListConverter extends ResolvingConverter void filterVariants(List variants, GenericDomValue> genericDomValue) { final List list = genericDomValue.getValue(); if (list != null) { - for (Iterator i = variants.iterator(); i.hasNext();) { + for (Iterator i = variants.iterator(); i.hasNext(); ) { final T variant = i.next(); for (T existing : list) { if (existing.equals(variant)) { @@ -149,7 +141,15 @@ public abstract class DelimitedListConverter extends ResolvingConverter> genericDomValue, final boolean delimitersOnly) { - return new MyPsiReference(element, new TextRange(start, end), context, genericDomValue, delimitersOnly); + return new MyPsiReference(element, getTextRange(genericDomValue, start, end), context, genericDomValue, delimitersOnly); + } + + protected TextRange getTextRange(GenericDomValue value, int start, int end) { + if (value instanceof GenericAttributeValue) { + return new TextRange(start, end); + } + TextRange tagRange = XmlTagUtil.getTrimmedValueRange(value.getXmlTag()); + return new TextRange(tagRange.getStartOffset() + start - 1, tagRange.getStartOffset() + end - 1); } @Override @@ -201,7 +201,7 @@ public abstract class DelimitedListConverter extends ResolvingConverter ref = new Ref(); PsiElement element = referenceHandleElementRename(this, newElementName, getSuperElementRenameFunction(ref)); if (!ref.isNull()) { - throw ref.get(); + throw ref.get(); } return element; @@ -210,9 +210,10 @@ public abstract class DelimitedListConverter extends ResolvingConverter ref = new Ref(); - PsiElement bindElement = referenceBindToElement(this, element, getSuperBindToElementFunction(ref), getSuperElementRenameFunction(ref)); + PsiElement bindElement = + referenceBindToElement(this, element, getSuperBindToElementFunction(ref), getSuperElementRenameFunction(ref)); if (!ref.isNull()) { - throw ref.get(); + throw ref.get(); } return bindElement; @@ -261,16 +262,15 @@ public abstract class DelimitedListConverter extends ResolvingConverter superBindToElementFunction, final Function superElementRenameFunction) - throws IncorrectOperationException { + throws IncorrectOperationException { return superBindToElementFunction.fun(element); } protected PsiElement referenceHandleElementRename(final PsiReference psiReference, final String newName, final Function superHandleElementRename) - throws IncorrectOperationException { + throws IncorrectOperationException { return superHandleElementRename.fun(newName); } - } From 913d75583079eeb5d191c6bebc880a92bdcb564e Mon Sep 17 00:00:00 2001 From: Alexey Kudravtsev Date: Thu, 20 Mar 2014 12:30:00 +0400 Subject: [PATCH 19/36] avoid unnecessary SecurityException --- .../util/containers/ConcurrentHashMap.java | 30 ++----------------- 1 file changed, 3 insertions(+), 27 deletions(-) diff --git a/platform/util/src/com/intellij/util/containers/ConcurrentHashMap.java b/platform/util/src/com/intellij/util/containers/ConcurrentHashMap.java index d70ef92d98e7..09eb36c84272 100644 --- a/platform/util/src/com/intellij/util/containers/ConcurrentHashMap.java +++ b/platform/util/src/com/intellij/util/containers/ConcurrentHashMap.java @@ -1,5 +1,5 @@ /* - * Copyright 2000-2013 JetBrains s.r.o. + * 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. @@ -18,6 +18,7 @@ package com.intellij.util.containers; import com.intellij.util.ConcurrencyUtil; import com.intellij.util.IncorrectOperationException; +import com.intellij.util.concurrency.AtomicFieldUpdater; import gnu.trove.TObjectHashingStrategy; import jsr166e.CountedCompleter; import jsr166e.ForkJoinPool; @@ -7137,32 +7138,7 @@ public class ConcurrentHashMap extends AbstractMap implements Concur * @return a sun.misc.Unsafe */ private static Unsafe getUnsafe() { - try { - return Unsafe.getUnsafe(); - } - catch (SecurityException tryReflectionInstead) { - } - try { - return AccessController.doPrivileged - (new PrivilegedExceptionAction() { - @Override - public Unsafe run() throws Exception { - Class k = Unsafe.class; - for (Field f : k.getDeclaredFields()) { - f.setAccessible(true); - Object x = f.get(null); - if (k.isInstance(x)) { - return k.cast(x); - } - } - throw new NoSuchFieldError("the Unsafe"); - } - }); - } - catch (PrivilegedActionException e) { - throw new RuntimeException("Could not initialize intrinsics", - e.getCause()); - } + return AtomicFieldUpdater.getUnsafe(); } ////////////////////// IJ specific From 0d278735bd832dfe9550336dfa32188027a5c03c Mon Sep 17 00:00:00 2001 From: Alexey Kudravtsev Date: Thu, 20 Mar 2014 12:52:40 +0400 Subject: [PATCH 20/36] optimisation: no expensive Class.getmodifiers() and checkAccess() calls --- .../impl/source/tree/JavaDocElementType.java | 10 ++-- .../psi/impl/source/tree/JavaElementType.java | 10 ++-- .../src/com/intellij/util/ReflectionUtil.java | 46 +++++++++++++++++++ .../com/intellij/util/text/StringFactory.java | 17 ++----- 4 files changed, 62 insertions(+), 21 deletions(-) diff --git a/java/java-psi-impl/src/com/intellij/psi/impl/source/tree/JavaDocElementType.java b/java/java-psi-impl/src/com/intellij/psi/impl/source/tree/JavaDocElementType.java index 847d7f313141..b046de964cdf 100644 --- a/java/java-psi-impl/src/com/intellij/psi/impl/source/tree/JavaDocElementType.java +++ b/java/java-psi-impl/src/com/intellij/psi/impl/source/tree/JavaDocElementType.java @@ -1,5 +1,5 @@ /* - * Copyright 2000-2013 JetBrains s.r.o. + * 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. @@ -33,22 +33,24 @@ import com.intellij.util.ReflectionUtil; import org.jetbrains.annotations.NonNls; import org.jetbrains.annotations.NotNull; import org.jetbrains.annotations.Nullable; +import sun.reflect.ConstructorAccessor; import java.lang.reflect.Constructor; public interface JavaDocElementType { class JavaDocCompositeElementType extends IJavaDocElementType implements ICompositeElementType { - private final Constructor myConstructor; + private final ConstructorAccessor myConstructor; private JavaDocCompositeElementType(@NonNls final String debugName, final Class nodeClass) { super(debugName); - myConstructor = ReflectionUtil.getDefaultConstructor(nodeClass); + Constructor constructor = ReflectionUtil.getDefaultConstructor(nodeClass); + myConstructor = ReflectionUtil.getConstructorAccessor(constructor); } @NotNull @Override public ASTNode createCompositeNode() { - return ReflectionUtil.createInstance(myConstructor); + return ReflectionUtil.createInstanceViaConstructorAccessor(myConstructor); } } diff --git a/java/java-psi-impl/src/com/intellij/psi/impl/source/tree/JavaElementType.java b/java/java-psi-impl/src/com/intellij/psi/impl/source/tree/JavaElementType.java index 14bc9b457614..4fbbad26964d 100644 --- a/java/java-psi-impl/src/com/intellij/psi/impl/source/tree/JavaElementType.java +++ b/java/java-psi-impl/src/com/intellij/psi/impl/source/tree/JavaElementType.java @@ -1,5 +1,5 @@ /* - * Copyright 2000-2013 JetBrains s.r.o. + * 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. @@ -35,12 +35,13 @@ import com.intellij.util.diff.FlyweightCapableTreeStructure; import org.jetbrains.annotations.NonNls; import org.jetbrains.annotations.NotNull; import org.jetbrains.annotations.Nullable; +import sun.reflect.ConstructorAccessor; import java.lang.reflect.Constructor; public interface JavaElementType { class JavaCompositeElementType extends IJavaElementType implements ICompositeElementType { - private final Constructor myConstructor; + private final ConstructorAccessor myConstructor; private JavaCompositeElementType(@NonNls final String debugName, final Class nodeClass) { this(debugName, nodeClass, false); @@ -48,13 +49,14 @@ public interface JavaElementType { private JavaCompositeElementType(@NonNls final String debugName, final Class nodeClass, final boolean leftBound) { super(debugName, leftBound); - myConstructor = ReflectionUtil.getDefaultConstructor(nodeClass); + Constructor constructor = ReflectionUtil.getDefaultConstructor(nodeClass); + myConstructor = ReflectionUtil.getConstructorAccessor(constructor); } @NotNull @Override public ASTNode createCompositeNode() { - return ReflectionUtil.createInstance(myConstructor); + return ReflectionUtil.createInstanceViaConstructorAccessor(myConstructor); } } diff --git a/platform/util/src/com/intellij/util/ReflectionUtil.java b/platform/util/src/com/intellij/util/ReflectionUtil.java index 8cd891e1fc35..d80d2e0bf129 100644 --- a/platform/util/src/com/intellij/util/ReflectionUtil.java +++ b/platform/util/src/com/intellij/util/ReflectionUtil.java @@ -16,12 +16,14 @@ package com.intellij.util; +import com.intellij.Patches; import com.intellij.openapi.diagnostic.Logger; import com.intellij.openapi.util.Condition; import com.intellij.util.containers.ContainerUtil; import org.jetbrains.annotations.NonNls; import org.jetbrains.annotations.NotNull; import org.jetbrains.annotations.Nullable; +import sun.reflect.ConstructorAccessor; import java.lang.reflect.*; import java.util.ArrayList; @@ -347,6 +349,50 @@ public class ReflectionUtil { } } + static { + // method getConstructorAccessorMethod is not necessary since JDK7, use acquireConstructorAccessor return value instead + assert Patches.USE_REFLECTION_TO_ACCESS_JDK7; + } + private static final Method acquireConstructorAccessorMethod; + private static final Method getConstructorAccessorMethod; + static { + try { + Method accessor = Constructor.class.getDeclaredMethod("acquireConstructorAccessor"); + accessor.setAccessible(true); + acquireConstructorAccessorMethod = accessor; + Method get = Constructor.class.getDeclaredMethod("getConstructorAccessor"); + get.setAccessible(true); + getConstructorAccessorMethod = get; + } + catch (NoSuchMethodException e) { + throw new RuntimeException(e); + } + } + + @NotNull + public static ConstructorAccessor getConstructorAccessor(@NotNull Constructor constructor) { + constructor.setAccessible(true); + // it is faster to invoke constructor via sun.reflect.ConstructorAccessor; it avoids AccessibleObject.checkAccess() + try { + acquireConstructorAccessorMethod.invoke(constructor); + return (ConstructorAccessor)getConstructorAccessorMethod.invoke(constructor); + } + catch (Exception e) { + throw new RuntimeException(e); + } + } + + @NotNull + public static T createInstanceViaConstructorAccessor(@NotNull ConstructorAccessor constructorAccessor, + @NotNull Object... arguments) { + try { + return (T)constructorAccessor.newInstance(arguments); + } + catch (Exception e) { + throw new RuntimeException(e); + } + } + @NotNull public static T createInstance(@NotNull Constructor constructor, @NotNull Object... args) { try { diff --git a/platform/util/src/com/intellij/util/text/StringFactory.java b/platform/util/src/com/intellij/util/text/StringFactory.java index 85ae65e2b655..c34dd1fe17b3 100644 --- a/platform/util/src/com/intellij/util/text/StringFactory.java +++ b/platform/util/src/com/intellij/util/text/StringFactory.java @@ -1,5 +1,5 @@ /* - * Copyright 2000-2012 JetBrains s.r.o. + * 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. @@ -15,11 +15,11 @@ */ package com.intellij.util.text; +import com.intellij.util.ReflectionUtil; import org.jetbrains.annotations.NotNull; import sun.reflect.ConstructorAccessor; import java.lang.reflect.Constructor; -import java.lang.reflect.Method; public class StringFactory { // String(char[], boolean). Works since JDK1.7, earlier JDKs have too slow reflection anyway @@ -29,11 +29,7 @@ public class StringFactory { ConstructorAccessor constructorAccessor = null; try { Constructor newC = String.class.getDeclaredConstructor(char[].class, boolean.class); - newC.setAccessible(true); - // it is faster to invoke constructor via sun.reflect.ConstructorAccessor; it avoids AccessibleObject.checkAccess() - Method accessor = Constructor.class.getDeclaredMethod("acquireConstructorAccessor"); - accessor.setAccessible(true); - constructorAccessor = (ConstructorAccessor)accessor.invoke(newC); + constructorAccessor = ReflectionUtil.getConstructorAccessor(newC); } catch (Exception ignored) { } @@ -50,12 +46,7 @@ public class StringFactory { @NotNull public static String createShared(@NotNull char[] chars) { if (ourConstructorAccessor != null) { - try { - return (String)ourConstructorAccessor.newInstance(new Object[]{chars, Boolean.TRUE}); - } - catch (Exception e) { - throw new RuntimeException(e); - } + return ReflectionUtil.createInstanceViaConstructorAccessor(ourConstructorAccessor, chars, Boolean.TRUE); } return new String(chars); } From 5004732171bc14d9506d32df3b0cc0c990c43500 Mon Sep 17 00:00:00 2001 From: Alexey Kudravtsev Date: Thu, 20 Mar 2014 13:26:48 +0400 Subject: [PATCH 21/36] optimisation: concurrent sets --- .../fileTypes/impl/IgnoredFileCache.java | 66 +- .../util/containers/ConcurrentBitSet.java | 1017 ++++------------- .../util/containers/ConcurrentBitSetTest.java | 124 ++ 3 files changed, 376 insertions(+), 831 deletions(-) create mode 100644 platform/util/testSrc/com/intellij/util/containers/ConcurrentBitSetTest.java diff --git a/platform/platform-impl/src/com/intellij/openapi/fileTypes/impl/IgnoredFileCache.java b/platform/platform-impl/src/com/intellij/openapi/fileTypes/impl/IgnoredFileCache.java index d55dbc73a453..8663cbe6b769 100644 --- a/platform/platform-impl/src/com/intellij/openapi/fileTypes/impl/IgnoredFileCache.java +++ b/platform/platform-impl/src/com/intellij/openapi/fileTypes/impl/IgnoredFileCache.java @@ -22,24 +22,24 @@ import com.intellij.openapi.vfs.newvfs.BulkFileListener; import com.intellij.openapi.vfs.newvfs.NewVirtualFile; import com.intellij.openapi.vfs.newvfs.events.VFileEvent; import com.intellij.openapi.vfs.newvfs.events.VFilePropertyChangeEvent; -import com.intellij.util.containers.IntArrayList; +import com.intellij.util.containers.ConcurrentBitSet; +import com.intellij.util.containers.ConcurrentIntObjectMap; +import com.intellij.util.containers.StripedLockIntObjectConcurrentHashMap; import com.intellij.util.messages.MessageBusConnection; -import gnu.trove.TIntHashSet; import org.jetbrains.annotations.NotNull; -import java.util.BitSet; import java.util.List; /** * @author peter */ class IgnoredFileCache { - private final BitSet myCheckedIds = new BitSet(); - private final TIntHashSet myIgnoredIds = new TIntHashSet(); + private final ConcurrentBitSet myCheckedIds = new ConcurrentBitSet(); + private final ConcurrentIntObjectMap myIgnoredIds = new StripedLockIntObjectConcurrentHashMap(); private final IgnoredPatternSet myIgnoredPatterns; - private int myVfsEventNesting = 0; + private volatile int myVfsEventNesting = 0; - IgnoredFileCache(IgnoredPatternSet ignoredPatterns) { + IgnoredFileCache(@NotNull IgnoredPatternSet ignoredPatterns) { myIgnoredPatterns = ignoredPatterns; MessageBusConnection connect = ApplicationManager.getApplication().getMessageBus().connect(); connect.subscribe(VirtualFileManager.VFS_CHANGES, new BulkFileListener() { @@ -56,43 +56,27 @@ class IgnoredFileCache { myVfsEventNesting--; } - private void clearCacheForChangedFiles(List events) { - final IntArrayList ids = collectChangedIds(events); - synchronized (myCheckedIds) { - for (int i : ids.toArray()) { - myCheckedIds.clear(i); - } - } - } - - private IntArrayList collectChangedIds(List events) { - final IntArrayList ids = new IntArrayList(); + private void clearCacheForChangedFiles(@NotNull List events) { for (final VFileEvent event : events) { VirtualFile file = event.getFile(); - if (!(file instanceof NewVirtualFile)) { - continue; - } - - if (event instanceof VFilePropertyChangeEvent) { + if (file instanceof NewVirtualFile && event instanceof VFilePropertyChangeEvent) { int id = ((NewVirtualFile)file).getId(); if (id >= 0) { - ids.add(id); + myCheckedIds.clear(id); + myIgnoredIds.remove(id); } } } - return ids; } }); } void clearCache() { - synchronized (myCheckedIds) { - myCheckedIds.clear(); - myIgnoredIds.clear(); - } + myCheckedIds.clear(); + myIgnoredIds.clear(); } - boolean isFileIgnored(VirtualFile file) { + boolean isFileIgnored(@NotNull VirtualFile file) { if (myVfsEventNesting != 0 || !(file instanceof NewVirtualFile)) { return isFileIgnoredNoCache(file); } @@ -102,25 +86,23 @@ class IgnoredFileCache { return isFileIgnoredNoCache(file); } - synchronized (myCheckedIds) { - if (myCheckedIds.get(id)) { - return myIgnoredIds.contains(id); - } + ConcurrentBitSet checkedIds = myCheckedIds; + if (checkedIds.get(id)) { + return myIgnoredIds.containsKey(id); } boolean result = isFileIgnoredNoCache(file); - synchronized (myCheckedIds) { - myCheckedIds.set(id); - if (result) { - myIgnoredIds.add(id); - } else { - myIgnoredIds.remove(id); - } + if (result) { + myIgnoredIds.put(id, Boolean.TRUE); } + else { + myIgnoredIds.remove(id); + } + checkedIds.set(id); return result; } - private boolean isFileIgnoredNoCache(VirtualFile file) { + private boolean isFileIgnoredNoCache(@NotNull VirtualFile file) { return myIgnoredPatterns.isIgnored(file.getName()); } } diff --git a/platform/util/src/com/intellij/util/containers/ConcurrentBitSet.java b/platform/util/src/com/intellij/util/containers/ConcurrentBitSet.java index 34083f36a1f6..38e44df366ab 100644 --- a/platform/util/src/com/intellij/util/containers/ConcurrentBitSet.java +++ b/platform/util/src/com/intellij/util/containers/ConcurrentBitSet.java @@ -1,415 +1,96 @@ /* - * Copyright (c) 1995, 2013, Oracle and/or its affiliates. All rights reserved. - * ORACLE PROPRIETARY/CONFIDENTIAL. Use is subject to license terms. - * - * - * - * - * - * - * - * - * - * - * - * - * - * - * - * - * + * 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.util.containers; -import com.intellij.util.ArrayUtil; -import com.intellij.util.concurrency.AtomicFieldUpdater; -import sun.misc.Unsafe; +import org.jetbrains.annotations.NotNull; -import java.nio.ByteBuffer; -import java.nio.ByteOrder; -import java.nio.LongBuffer; -import java.util.Arrays; +import java.util.concurrent.atomic.AtomicLongArray; +import java.util.concurrent.atomic.AtomicReferenceArray; /** - * This class implements a vector of bits that grows as needed. Each - * component of the bit set has a {@code boolean} value. The - * bits of a {@code BitSet} are indexed by nonnegative integers. - * Individual indexed bits can be examined, set, or cleared. One - * {@code BitSet} may be used to modify the contents of another - * {@code BitSet} through logical AND, logical inclusive OR, and - * logical exclusive OR operations. - *

- *

By default, all bits in the set initially have the value - * {@code false}. - *

- *

Every bit set has a current size, which is the number of bits - * of space currently in use by the bit set. Note that the size is - * related to the implementation of a bit set, so it may change with - * implementation. The length of a bit set relates to logical length - * of a bit set and is defined independently of implementation. - *

- *

Unless otherwise noted, passing a null parameter to any of the - * methods in a {@code BitSet} will result in a - * {@code NullPointerException}. - *

- *

A {@code BitSet} is not safe for multithreaded use without - * external synchronization. + * This class is a thread-safe version of the + * {@code java.util.BitSet} except for some methods which don't make sense in concurrent environment or those i was too lazy to implement. * - * @author Arthur van Hoff - * @author Michael McCloskey - * @author Martin Buchholz - * @since JDK1.0 + * Implementation is based on "Lock-free Dynamically Resizable Arrays" by Dechev, Pirkelbauer, Bjarne Stroustrup. + * http://www.stroustrup.com/lock-free-vector.pdf + * + * @see java.util.BitSet */ public class ConcurrentBitSet { - public static final AtomicFieldUpdater FIELD_UPDATER = - AtomicFieldUpdater.forFieldOfType(ConcurrentBitSet.class, long[].class); - /* - * BitSets are packed into arrays of "words." Currently a word is - * a long, which consists of 64 bits, requiring 6 address bits. - * The choice of word size is determined purely by performance concerns. - */ + /** + * An array of 32 longword vectors. + * Vector at index "i" has length of (1 << i) long words. + * Each long word stores next 64 bits part of the set. + * Therefore the i-th bit of the set is stored in {@code arrays.get(arrayIndex(i)).get(wordIndexInArray(i))} word in the {@code 1L << i} position. + */ + private final AtomicReferenceArray arrays = new AtomicReferenceArray(32); + private static int arrayIndex(int bitIndex) { + int i = (bitIndex >> ADDRESS_BITS_PER_WORD) + 1; + return 31 - Integer.numberOfLeadingZeros(i); + } + private static int wordIndexInArray(int bitIndex) { + int i = (bitIndex >> ADDRESS_BITS_PER_WORD) + 1; + return clearHighestBit(i); + } + + private static int clearHighestBit(int index) { + int i = index>>1; + i |= i >> 1; + i |= i >> 2; + i |= i >> 4; + i |= i >> 8; + i |= i >> 16; + return index & i; + } + + /* BitSets are packed into arrays of "words." Currently a word is + a long, which consists of 64 bits, requiring 6 address bits. + The choice of word size is determined purely by performance concerns. + */ private static final int ADDRESS_BITS_PER_WORD = 6; private static final int BITS_PER_WORD = 1 << ADDRESS_BITS_PER_WORD; - private static final int BIT_INDEX_MASK = BITS_PER_WORD - 1; /* Used to shift left or right for a partial word mask */ - private static final long WORD_MASK = 0xffffffffffffffffL; - - /** - * The internal field corresponding to the serialField "bits". - */ - private volatile long[] words; - - - /** - * Given a bit index, return word index containing it. - */ - private static int wordIndex(int bitIndex) { - return bitIndex >> ADDRESS_BITS_PER_WORD; - } - - /** - * Creates a new bit set. All bits are initially {@code false}. - */ - public ConcurrentBitSet() { - initWords(BITS_PER_WORD); - } - - /** - * Creates a bit set whose initial size is large enough to explicitly - * represent bits with indices in the range {@code 0} through - * {@code nbits-1}. All bits are initially {@code false}. - * - * @param nbits the initial size of the bit set - * @throws NegativeArraySizeException if the specified initial size - * is negative - */ - public ConcurrentBitSet(int nbits) { - // nbits can't be negative; size 0 is OK - if (nbits < 0) { - throw new NegativeArraySizeException("nbits < 0: " + nbits); - } - - initWords(nbits); - } - - private void initWords(int nbits) { - words = new long[wordIndex(nbits - 1) + 1]; - } - - /** - * Creates a bit set using words as the internal representation. - * The last word (if there is one) must be non-zero. - */ - private ConcurrentBitSet(long[] words) { - this.words = words; - } - - /** - * Returns a new bit set containing all the bits in the given long array. - *

- *

More precisely, - *
{@code BitSet.valueOf(longs).get(n) == ((longs[n/64] & (1L<<(n%64))) != 0)} - *
for all {@code n < 64 * longs.length}. - *

- *

This method is equivalent to - * {@code BitSet.valueOf(LongBuffer.wrap(longs))}. - * - * @param longs a long array containing a little-endian representation - * of a sequence of bits to be used as the initial bits of the - * new bit set - * @return a {@code BitSet} containing all the bits in the long array - * @since 1.7 - */ - public static ConcurrentBitSet valueOf(long[] longs) { - int n; - for (n = longs.length; n > 0 && longs[n - 1] == 0; n--) { - ; - } - return new ConcurrentBitSet(Arrays.copyOf(longs, n)); - } - - /** - * Returns a new bit set containing all the bits in the given long - * buffer between its position and limit. - *

- *

More precisely, - *
{@code BitSet.valueOf(lb).get(n) == ((lb.get(lb.position()+n/64) & (1L<<(n%64))) != 0)} - *
for all {@code n < 64 * lb.remaining()}. - *

- *

The long buffer is not modified by this method, and no - * reference to the buffer is retained by the bit set. - * - * @param lb a long buffer containing a little-endian representation - * of a sequence of bits between its position and limit, to be - * used as the initial bits of the new bit set - * @return a {@code BitSet} containing all the bits in the buffer in the - * specified range - * @since 1.7 - */ - public static ConcurrentBitSet valueOf(LongBuffer lb) { - lb = lb.slice(); - int n; - for (n = lb.remaining(); n > 0 && lb.get(n - 1) == 0; n--) { - ; - } - long[] words = new long[n]; - lb.get(words); - return new ConcurrentBitSet(words); - } - - /** - * Returns a new bit set containing all the bits in the given byte array. - *

- *

More precisely, - *
{@code BitSet.valueOf(bytes).get(n) == ((bytes[n/8] & (1<<(n%8))) != 0)} - *
for all {@code n < 8 * bytes.length}. - *

- *

This method is equivalent to - * {@code BitSet.valueOf(ByteBuffer.wrap(bytes))}. - * - * @param bytes a byte array containing a little-endian - * representation of a sequence of bits to be used as the - * initial bits of the new bit set - * @return a {@code BitSet} containing all the bits in the byte array - * @since 1.7 - */ - public static ConcurrentBitSet valueOf(byte[] bytes) { - return ConcurrentBitSet.valueOf(ByteBuffer.wrap(bytes)); - } - - /** - * Returns a new bit set containing all the bits in the given byte - * buffer between its position and limit. - *

- *

More precisely, - *
{@code BitSet.valueOf(bb).get(n) == ((bb.get(bb.position()+n/8) & (1<<(n%8))) != 0)} - *
for all {@code n < 8 * bb.remaining()}. - *

- *

The byte buffer is not modified by this method, and no - * reference to the buffer is retained by the bit set. - * - * @param bb a byte buffer containing a little-endian representation - * of a sequence of bits between its position and limit, to be - * used as the initial bits of the new bit set - * @return a {@code BitSet} containing all the bits in the buffer in the - * specified range - * @since 1.7 - */ - public static ConcurrentBitSet valueOf(ByteBuffer bb) { - bb = bb.slice().order(ByteOrder.LITTLE_ENDIAN); - int n; - for (n = bb.remaining(); n > 0 && bb.get(n - 1) == 0; n--) { - ; - } - long[] words = new long[(n + 7) / 8]; - bb.limit(n); - int i = 0; - while (bb.remaining() >= 8) { - words[i++] = bb.getLong(); - } - for (int remaining = bb.remaining(), j = 0; j < remaining; j++) { - words[i] |= (bb.get() & 0xffL) << 8 * j; - } - return new ConcurrentBitSet(words); - } - - /** - * Returns a new byte array containing all the bits in this bit set. - *

- *

More precisely, if - *
{@code byte[] bytes = s.toByteArray();} - *
then {@code bytes.length == (s.length()+7)/8} and - *
{@code s.get(n) == ((bytes[n/8] & (1<<(n%8))) != 0)} - *
for all {@code n < 8 * bytes.length}. - * - * @return a byte array containing a little-endian representation - * of all the bits in this bit set - * @since 1.7 - */ - public byte[] toByteArray() { - long[] words = this.words; - int n = words.length; - if (n == 0) { - return new byte[0]; - } - int len = 8 * (n - 1); - for (long x = words[n - 1]; x != 0; x >>>= 8) { - len++; - } - byte[] bytes = new byte[len]; - ByteBuffer bb = ByteBuffer.wrap(bytes).order(ByteOrder.LITTLE_ENDIAN); - for (int i = 0; i < n - 1; i++) { - bb.putLong(words[i]); - } - for (long x = words[n - 1]; x != 0; x >>>= 8) { - bb.put((byte)(x & 0xff)); - } - return bytes; - } - - /** - * Returns a new long array containing all the bits in this bit set. - *

- *

More precisely, if - *
{@code long[] longs = s.toLongArray();} - *
then {@code longs.length == (s.length()+63)/64} and - *
{@code s.get(n) == ((longs[n/64] & (1L<<(n%64))) != 0)} - *
for all {@code n < 64 * longs.length}. - * - * @return a long array containing a little-endian representation - * of all the bits in this bit set - * @since 1.7 - */ - public long[] toLongArray() { - long[] words = this.words; - return Arrays.copyOf(words, words.length); - } - - /** - * Ensures that the BitSet can hold enough words. - * - * @param wordsRequired the minimum acceptable number of words. - */ - private long[] ensureCapacity(int wordsRequired) { - long[] newWords; - long[] words; - do { - words = this.words; - if (words.length >= wordsRequired) { - newWords = words; - break; - } - int request = Math.max(3 * words.length / 2, wordsRequired); - newWords = Arrays.copyOf(words, request); - } while (!FIELD_UPDATER.compareAndSet(this, words, newWords)); - return newWords; - } - - /** - * Ensures that the BitSet can accommodate a given wordIndex, - * temporarily violating the invariants. The caller must - * restore the invariants before returning to the user, - * possibly using recalculateWordsInUse(). - * - * @param wordIndex the index to be accommodated. - */ - private long[] expandTo(int wordIndex) { - int wordsRequired = wordIndex + 1; - return ensureCapacity(wordsRequired); - } - - /** - * Checks that fromIndex ... toIndex is a valid range of bit indices. - */ - private static void checkRange(int fromIndex, int toIndex) { - if (fromIndex < 0) { - throw new IndexOutOfBoundsException("fromIndex < 0: " + fromIndex); - } - if (toIndex < 0) { - throw new IndexOutOfBoundsException("toIndex < 0: " + toIndex); - } - if (fromIndex > toIndex) { - throw new IndexOutOfBoundsException("fromIndex: " + fromIndex + - " > toIndex: " + toIndex); - } - } + private static final long WORD_MASK = -1L; /** * Sets the bit at the specified index to the complement of its * current value. * * @param bitIndex the index of the bit to flip + * @return new bit value * @throws IndexOutOfBoundsException if the specified index is negative - * @since 1.4 */ - public void flip(int bitIndex) { + public boolean flip(int bitIndex) { if (bitIndex < 0) { throw new IndexOutOfBoundsException("bitIndex < 0: " + bitIndex); } - int wordIndex = wordIndex(bitIndex); + AtomicLongArray array = getOrCreateArray(bitIndex); - while (true) { - long[] words = expandTo(wordIndex); - long word; - long newWord; - do { - word = words[wordIndex]; - newWord = word ^ (1L << bitIndex); - } - while (!compareAndSet(words, wordIndex, word, newWord)); - if (words == this.words) break; - } - } + int wordIndexInArray = wordIndexInArray(bitIndex); - /** - * Sets each bit from the specified {@code fromIndex} (inclusive) to the - * specified {@code toIndex} (exclusive) to the complement of its current - * value. - * - * @param fromIndex index of the first bit to flip - * @param toIndex index after the last bit to flip - * @throws IndexOutOfBoundsException if {@code fromIndex} is negative, - * or {@code toIndex} is negative, or {@code fromIndex} is - * larger than {@code toIndex} - * @since 1.4 - */ - public void flip(int fromIndex, int toIndex) { - checkRange(fromIndex, toIndex); - - if (fromIndex == toIndex) { - return; - } - - int startWordIndex = wordIndex(fromIndex); - int endWordIndex = wordIndex(toIndex - 1); - - - long firstWordMask = WORD_MASK << fromIndex; - long lastWordMask = WORD_MASK >>> -toIndex; - long[] words = expandTo(endWordIndex); - if (startWordIndex == endWordIndex) { - // Case 1: One word - words[startWordIndex] ^= firstWordMask & lastWordMask; - } - else { - // Case 2: Multiple words - // Handle first word - words[startWordIndex] ^= firstWordMask; - - // Handle intermediate words, if any - for (int i = startWordIndex + 1; i < endWordIndex; i++) { - words[i] ^= WORD_MASK; - } - - // Handle last word - words[endWordIndex] ^= lastWordMask; + long word; + long newWord; + do { + word = array.get(wordIndexInArray); + newWord = word ^ (1L << bitIndex); } + while (!array.compareAndSet(wordIndexInArray, word, newWord)); + return (newWord & (1L << bitIndex)) != 0; } /** @@ -417,26 +98,22 @@ public class ConcurrentBitSet { * * @param bitIndex a bit index * @throws IndexOutOfBoundsException if the specified index is negative - * @since JDK1.0 */ public void set(int bitIndex) { if (bitIndex < 0) { throw new IndexOutOfBoundsException("bitIndex < 0: " + bitIndex); } - int wordIndex = wordIndex(bitIndex); + AtomicLongArray array = getOrCreateArray(bitIndex); - long[] words = expandTo(wordIndex); - while (true) { - long word; - long newWord; - do { - word = words[wordIndex]; - newWord = word | (1L << bitIndex); - } - while (!compareAndSet(words, wordIndex, word, newWord)); - if (words == this.words) break; + int wordIndexInArray = wordIndexInArray(bitIndex); + long word; + long newWord; + do { + word = array.get(wordIndexInArray); + newWord = word | (1L << bitIndex); } + while (!array.compareAndSet(wordIndexInArray, word, newWord)); } /** @@ -445,7 +122,6 @@ public class ConcurrentBitSet { * @param bitIndex a bit index * @param value a boolean value to set * @throws IndexOutOfBoundsException if the specified index is negative - * @since 1.4 */ public void set(int bitIndex, boolean value) { if (value) { @@ -456,79 +132,56 @@ public class ConcurrentBitSet { } } - - /** * Sets the bit specified by the index to {@code false}. * * @param bitIndex the index of the bit to be cleared * @throws IndexOutOfBoundsException if the specified index is negative - * @since JDK1.0 */ public void clear(int bitIndex) { if (bitIndex < 0) { throw new IndexOutOfBoundsException("bitIndex < 0: " + bitIndex); } - int wordIndex = wordIndex(bitIndex); - long[] words = this.words; - if (wordIndex >= words.length) { - return; + AtomicLongArray array = getOrCreateArray(bitIndex); + + int wordIndexInArray = wordIndexInArray(bitIndex); + long word; + long newWord; + do { + word = array.get(wordIndexInArray); + newWord = word & ~ (1L << bitIndex); } + while (!array.compareAndSet(wordIndexInArray, word, newWord)); + } - while (true) { - long word; - long newWord; - do { - word = words[wordIndex]; - newWord = word & ~(1L << bitIndex); - } - while (!compareAndSet(words, wordIndex, word, newWord)); - if (words == this.words) break; + @NotNull + private AtomicLongArray getOrCreateArray(int bitIndex) { + int arrayIndex = arrayIndex(bitIndex); + AtomicLongArray array; + + // while loop is here because of clear() method + while ((array = arrays.get(arrayIndex)) == null) { + arrays.compareAndSet(arrayIndex, null, new AtomicLongArray(1< words.length) throw new IndexOutOfBoundsException(); - return ((long) index << shift) + base; - } - - private static boolean compareAndSet(long[] words, int wordIndex, long expectedWord, long targetWord) { - return UNSAFE.compareAndSwapLong(words, indexToOffset(words, wordIndex), expectedWord, targetWord); - } /** - * Sets all of the bits in this BitSet to {@code false}. - * - * @since 1.4 + * Clear method in presense of concurrency complicates everything to no end. + * PLEASE REWRITE EVERY OTHER METHOD IF EVER DECIDE TO IMPLEMENT THIS */ public void clear() { - words = ArrayUtil.EMPTY_LONG_ARRAY; + for (int i=0; i len) { - toIndex = len; - } - - ConcurrentBitSet result = new ConcurrentBitSet(toIndex - fromIndex); - int targetWords = wordIndex(toIndex - fromIndex - 1) + 1; - int sourceIndex = wordIndex(fromIndex); - boolean wordAligned = (fromIndex & BIT_INDEX_MASK) == 0; - - // Process all words but the last word - for (int i = 0; i < targetWords - 1; i++, sourceIndex++) { - result.words[i] = wordAligned ? words[sourceIndex] : - words[sourceIndex] >>> fromIndex | - words[sourceIndex + 1] << -fromIndex; - } - - // Process the last word - long lastWordMask = WORD_MASK >>> -toIndex; - result.words[targetWords - 1] = - (toIndex - 1 & BIT_INDEX_MASK) < (fromIndex & BIT_INDEX_MASK) - ? /* straddles source words */ - words[sourceIndex] >>> fromIndex | - (words[sourceIndex + 1] & lastWordMask) << -fromIndex - : - (words[sourceIndex] & lastWordMask) >>> fromIndex; - - return result; - } - - /** - * Returns the index of the first bit that is set to {@code true} - * that occurs on or after the specified starting index. If no such - * bit exists then {@code -1} is returned. - *

- *

To iterate over the {@code true} bits in a {@code BitSet}, - * use the following loop: - *

- *

 {@code
-   * for (int i = bs.nextSetBit(0); i >= 0; i = bs.nextSetBit(i+1)) {
-   *     // operate on index i here
-   * }}
- * - * @param fromIndex the index to start checking from (inclusive) - * @return the index of the next set bit, or {@code -1} if there - * is no such bit - * @throws IndexOutOfBoundsException if the specified index is negative - * @since 1.4 - */ + * Returns the index of the first bit that is set to {@code true} + * that occurs on or after the specified starting index. If no such + * bit exists then {@code -1} is returned. + *

+ *

To iterate over the {@code true} bits, + * use the following loop: + *

+ *

 {@code
+  * for (int i = bs.nextSetBit(0); i >= 0; i = bs.nextSetBit(i+1)) {
+  *     // operate on index i here
+  * }}
+ * + * @param fromIndex the index to start checking from (inclusive) + * @return the index of the next set bit, or {@code -1} if there + * is no such bit + * @throws IndexOutOfBoundsException if the specified index is negative + */ public int nextSetBit(int fromIndex) { if (fromIndex < 0) { - throw new IndexOutOfBoundsException("fromIndex < 0: " + fromIndex); + throw new IndexOutOfBoundsException("bitIndex < 0: " + fromIndex); } - int u = wordIndex(fromIndex); - long[] words = this.words; - if (u >= words.length) { + int arrayIndex; + AtomicLongArray array = null; + for (arrayIndex = arrayIndex(fromIndex); arrayIndex < arrays.length() && (array = arrays.get(arrayIndex)) == null; arrayIndex++); + if (array == null) { return -1; } - long word = words[u] & WORD_MASK << fromIndex; + int wordIndexInArray = wordIndexInArray(fromIndex); + + long word = array.get(wordIndexInArray) & (WORD_MASK << fromIndex); while (true) { if (word != 0) { - return u * BITS_PER_WORD + Long.numberOfTrailingZeros(word); + return ((1<= words.length) { - return fromIndex; + int arrayIndex = arrayIndex(fromIndex); + AtomicLongArray array = arrays.get(arrayIndex); + int wordIndexInArray = wordIndexInArray(fromIndex); + if (array == null) { + return ((1< - *

To iterate over the {@code true} bits in a {@code BitSet}, - * use the following loop: - *

- *

 {@code
-   * for (int i = bs.length(); (i = bs.previousSetBit(i-1)) >= 0; ) {
-   *     // operate on index i here
-   * }}
- * - * @param fromIndex the index to start checking from (inclusive) - * @return the index of the previous set bit, or {@code -1} if there - * is no such bit - * @throws IndexOutOfBoundsException if the specified index is less - * than {@code -1} - * @since 1.7 - */ - public int previousSetBit(int fromIndex) { - if (fromIndex < 0) { - if (fromIndex == -1) { - return -1; - } - throw new IndexOutOfBoundsException( - "fromIndex < -1: " + fromIndex); - } - - int u = wordIndex(fromIndex); - long[] words = this.words; - if (u >= words.length) { - return length() - 1; - } - - long word = words[u] & WORD_MASK >>> -(fromIndex + 1); - - while (true) { - if (word != 0) { - return (u + 1) * BITS_PER_WORD - 1 - Long.numberOfLeadingZeros(word); - } - if (u-- == 0) { - return -1; - } - word = words[u]; - } - } - - /** - * Returns the index of the nearest bit that is set to {@code false} - * that occurs on or before the specified starting index. - * If no such bit exists, or if {@code -1} is given as the - * starting index, then {@code -1} is returned. - * - * @param fromIndex the index to start checking from (inclusive) - * @return the index of the previous clear bit, or {@code -1} if there - * is no such bit - * @throws IndexOutOfBoundsException if the specified index is less - * than {@code -1} - * @since 1.7 - */ - public int previousClearBit(int fromIndex) { - if (fromIndex < 0) { - if (fromIndex == -1) { - return -1; - } - throw new IndexOutOfBoundsException( - "fromIndex < -1: " + fromIndex); - } - - int u = wordIndex(fromIndex); - long[] words = this.words; - if (u >= words.length) { - return fromIndex; - } - - long word = ~words[u] & WORD_MASK >>> -(fromIndex + 1); - - while (true) { - if (word != 0) { - return (u + 1) * BITS_PER_WORD - 1 - Long.numberOfLeadingZeros(word); - } - if (u-- == 0) { - return -1; - } - word = ~words[u]; - } - } - - /** - * Returns the "logical size" of this {@code BitSet}: the index of - * the highest set bit in the {@code BitSet} plus one. Returns zero - * if the {@code BitSet} contains no set bits. - * - * @return the logical size of this {@code BitSet} - * @since 1.2 - */ - public int length() { - long[] words = this.words; - if (words.length == 0) { - return 0; - } - - return BITS_PER_WORD * (words.length - 1) + - BITS_PER_WORD - Long.numberOfLeadingZeros(words[words.length - 1]); - } - - - /** - * Returns true if the specified {@code BitSet} has any bits set to - * {@code true} that are also set to {@code true} in this {@code BitSet}. - * - * @param set {@code BitSet} to intersect with - * @return boolean indicating whether this {@code BitSet} intersects - * the specified {@code BitSet} - * @since 1.4 - */ - public boolean intersects(ConcurrentBitSet set) { - long[] w = words; - long[] sw = set.words; - for (int i = Math.min(w.length, sw.length) - 1; i >= 0; i--) { - if ((w[i] & sw[i]) != 0) { - return true; - } - } - return false; - } - - /** - * Returns the number of bits set to {@code true} in this {@code BitSet}. - * - * @return the number of bits set to {@code true} in this {@code BitSet} - * @since 1.4 - */ - public int cardinality() { - int sum = 0; - long[] words = this.words; - for (int i = 0; i < words.length; i++) { - sum += Long.bitCount(words[i]); - } - return sum; - } - - - - - - /** - * Returns the hash code value for this bit set. The hash code depends - * only on which bits are set within this {@code BitSet}. - *

- *

The hash code is defined to be the result of the following - * calculation: - *

 {@code
-   * public int hashCode() {
-   *     long h = 1234;
-   *     long[] words = toLongArray();
-   *     for (int i = words.length; --i >= 0; )
-   *         h ^= words[i] * (i + 1);
-   *     return (int)((h >> 32) ^ h);
-   * }}
- * Note that the hash code changes if the set of bits is altered. - * - * @return the hash code value for this bit set - */ + * Returns the hash code value for this bit set. The hash code depends + * only on which bits are set. + *

+ *

The hash code is defined to be the result of the following + * calculation: + *

 {@code
+  * public int hashCode() {
+  *     long h = 1234;
+  *     for (int i = words.length; --i >= 0; )
+  *         h ^= words[i] * (i + 1);
+  *     return (int)((h >> 32) ^ h);
+  * }}
+ * Note that the hash code changes if the set of bits is altered. + * + * @return the hash code value for this bit set + */ public int hashCode() { long h = 1234; - long[] words = this.words; - for (int i = words.length; --i >= 0; ) { - h ^= words[i] * (i + 1); + for (int a = 0; a> 32 ^ h); } + /** - * Returns the number of bits of space actually in use by this - * {@code BitSet} to represent bit values. - * The maximum element in the set is the size - 1st element. - * - * @return the number of bits currently in this bit set - */ + * Returns the number of bits of space actually in use + * + * @return the number of bits currently in this bit set + */ public int size() { - return words.length * BITS_PER_WORD; + int a; + for (a = arrays.length() - 1; a >= 0; a--) { + AtomicLongArray array = arrays.get(a); + if (array != null) break; + } + return ((1<((BitSet)obj).get(k) == this.get(k) - * must be true. The current sizes of the two bit sets are not compared. - * - * @param obj the object to compare with - * @return {@code true} if the objects are the same; - * {@code false} otherwise - * @see #size() - */ + * Compares this object against the specified object. + * The result is {@code true} if and only if the argument is + * not {@code null} and is a {@code ConcurrentBitSet} object that has + * exactly the same set of bits set to {@code true} as this bit + * set. That is, for every nonnegative {@code int} index {@code k}, + *
((ConcurrentBitSet)obj).get(k) == this.get(k)
+ * must be true. The current sizes of the two bit sets are not compared. + * + * @param obj the object to compare with + * @return {@code true} if the objects are the same; + * {@code false} otherwise + * @see #size() + */ public boolean equals(Object obj) { if (!(obj instanceof ConcurrentBitSet)) { return false; @@ -886,16 +363,15 @@ public class ConcurrentBitSet { ConcurrentBitSet set = (ConcurrentBitSet)obj; - long[] words = this.words; - long[] setWords = set.words; - if (words.length != setWords.length) { - return false; - } - - // Check words in use by both BitSets - for (int i = 0; i < words.length; i++) { - if (words[i] != setWords[i]) { - return false; + for (int i = 0; i < arrays.length(); i++) { + AtomicLongArray array1 = arrays.get(i); + AtomicLongArray array2 = set.arrays.get(i); + if (array1 == null && array2 == null) continue; + int size = array1 == null ? array2.length() : array1.length(); + for (int k=0; k - *

Example: - *

-   * BitSet drPepper = new BitSet();
- * Now {@code drPepper.toString()} returns "{@code {}}". - *
-   * drPepper.set(2);
- * Now {@code drPepper.toString()} returns "{@code {2}}". - *
-   * drPepper.set(4);
-   * drPepper.set(10);
- * Now {@code drPepper.toString()} returns "{@code {2, 4, 10}}". - * - * @return a string representation of this bit set - */ + * Returns a string representation of this bit set. For every index + * which contains a bit in the set + * state, the decimal representation of that index is included in + * the result. Such indices are listed in order from lowest to + * highest, separated by ", " (a comma and a space) and + * surrounded by braces, resulting in the usual mathematical + * notation for a set of integers. + * + * @return a string representation of this bit set + */ public String toString() { - - long[] words = this.words; - int numBits = words.length > 128 ? - cardinality() : words.length * BITS_PER_WORD; - StringBuilder b = new StringBuilder(6 * numBits + 2); + StringBuilder b = new StringBuilder(); b.append('{'); int i = nextSetBit(0); diff --git a/platform/util/testSrc/com/intellij/util/containers/ConcurrentBitSetTest.java b/platform/util/testSrc/com/intellij/util/containers/ConcurrentBitSetTest.java new file mode 100644 index 000000000000..a7e315a4099e --- /dev/null +++ b/platform/util/testSrc/com/intellij/util/containers/ConcurrentBitSetTest.java @@ -0,0 +1,124 @@ +/* + * 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.util.containers; + +import junit.framework.TestCase; + +public class ConcurrentBitSetTest extends TestCase { + public void test() { + ConcurrentBitSet bitSet = new ConcurrentBitSet(); + final ConcurrentBitSet emptySet = new ConcurrentBitSet(); + int N = 3000; + assertEquals(0, bitSet.nextClearBit(0)); + assertEquals(bitSet, emptySet); + for (int i=0; i Date: Thu, 20 Mar 2014 13:55:17 +0400 Subject: [PATCH 22/36] cleanup --- .../util/src/com/intellij/util/NewInstanceFactory.java | 7 ++++--- 1 file changed, 4 insertions(+), 3 deletions(-) diff --git a/platform/util/src/com/intellij/util/NewInstanceFactory.java b/platform/util/src/com/intellij/util/NewInstanceFactory.java index 8fc93edace02..cf888f86d88e 100644 --- a/platform/util/src/com/intellij/util/NewInstanceFactory.java +++ b/platform/util/src/com/intellij/util/NewInstanceFactory.java @@ -1,5 +1,5 @@ /* - * Copyright 2000-2013 JetBrains s.r.o. + * 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. @@ -17,6 +17,7 @@ package com.intellij.util; import com.intellij.openapi.diagnostic.Logger; import com.intellij.openapi.util.Factory; +import org.jetbrains.annotations.NotNull; import java.lang.reflect.Constructor; @@ -25,7 +26,7 @@ public class NewInstanceFactory implements Factory { private final Constructor myConstructor; private final Object[] myArgs; - private NewInstanceFactory(Constructor constructor, Object[] args) { + private NewInstanceFactory(@NotNull Constructor constructor, @NotNull Object[] args) { myConstructor = constructor; myArgs = args; } @@ -41,7 +42,7 @@ public class NewInstanceFactory implements Factory { } } - public static Factory fromClass(final Class clazz) { + public static Factory fromClass(@NotNull final Class clazz) { try { return new NewInstanceFactory(clazz.getConstructor(ArrayUtil.EMPTY_CLASS_ARRAY), ArrayUtil.EMPTY_OBJECT_ARRAY); } From 52fba197585af6be2e4e5fcf35e392b1a57a2a61 Mon Sep 17 00:00:00 2001 From: Alexey Kudravtsev Date: Fri, 21 Mar 2014 13:42:59 +0400 Subject: [PATCH 23/36] optimisation: do not allocate list unnecessarily --- .../com/intellij/psi/impl/cache/TypeInfo.java | 31 ++++++++++--------- .../impl/compiled/StubBuildingVisitor.java | 5 ++- .../impl/java/stubs/PsiAnnotationStub.java | 3 +- 3 files changed, 20 insertions(+), 19 deletions(-) diff --git a/java/java-psi-impl/src/com/intellij/psi/impl/cache/TypeInfo.java b/java/java-psi-impl/src/com/intellij/psi/impl/cache/TypeInfo.java index 41a6d35c3e0c..346e80c6eb7a 100644 --- a/java/java-psi-impl/src/com/intellij/psi/impl/cache/TypeInfo.java +++ b/java/java-psi-impl/src/com/intellij/psi/impl/cache/TypeInfo.java @@ -33,7 +33,8 @@ import com.intellij.psi.stubs.StubElement; import com.intellij.psi.stubs.StubInputStream; import com.intellij.psi.stubs.StubOutputStream; import com.intellij.psi.tree.IElementType; -import com.intellij.util.containers.ContainerUtil; +import com.intellij.util.BitUtil; +import com.intellij.util.SmartList; import com.intellij.util.io.StringRef; import gnu.trove.TObjectIntHashMap; import org.jetbrains.annotations.NotNull; @@ -42,8 +43,6 @@ import org.jetbrains.annotations.Nullable; import java.io.IOException; import java.util.List; -import static com.intellij.util.BitUtil.isSet; - /** * @author max */ @@ -81,19 +80,19 @@ public class TypeInfo { private static final int HAS_ARRAY_COUNT = 0x40; private static final int HAS_ELLIPSIS = 0x80; - private static final TypeInfo NULL = new TypeInfo((StringRef)null, (byte)0, false, ContainerUtil.emptyList()); + private static final TypeInfo NULL = new TypeInfo((StringRef)null, (byte)0, false, PsiAnnotationStub.EMPTY_ARRAY); public final StringRef text; public final byte arrayCount; public final boolean isEllipsis; - private final List myAnnotationStubs; + private final PsiAnnotationStub[] myAnnotationStubs; - public TypeInfo(String text, byte arrayCount, boolean ellipsis, @NotNull List annotationStubs) { + public TypeInfo(String text, byte arrayCount, boolean ellipsis, @NotNull PsiAnnotationStub[] annotationStubs) { this(StringRef.fromString(text == null ? null : internFrequentType(text)), arrayCount, ellipsis, annotationStubs); } - private TypeInfo(StringRef text, byte arrayCount, boolean isEllipsis, @NotNull List annotationStubs) { + private TypeInfo(StringRef text, byte arrayCount, boolean isEllipsis, @NotNull PsiAnnotationStub[] annotationStubs) { this.text = text; this.arrayCount = arrayCount; this.isEllipsis = isEllipsis; @@ -105,15 +104,17 @@ public class TypeInfo { PsiModifierListStub modifierList = (PsiModifierListStub)owner.findChildStubByType(JavaStubElementTypes.MODIFIER_LIST); if (modifierList == null) return this; - List annotationStubs = ContainerUtil.newArrayList(); + List annotationStubs = null; for (StubElement child : modifierList.getChildrenStubs()) { if (!(child instanceof PsiAnnotationStub)) continue; PsiAnnotationStub annotationStub = (PsiAnnotationStub)child; if (PsiImplUtil.isTypeAnnotation(annotationStub.getPsiElement())) { + if (annotationStubs == null) annotationStubs = new SmartList(); annotationStubs.add(annotationStub); } } - return new TypeInfo(text, arrayCount, isEllipsis, annotationStubs); + PsiAnnotationStub[] stubs = annotationStubs == null ? PsiAnnotationStub.EMPTY_ARRAY : annotationStubs.toArray(new PsiAnnotationStub[annotationStubs.size()]); + return new TypeInfo(text, arrayCount, isEllipsis, stubs); } @NotNull @@ -185,7 +186,7 @@ public class TypeInfo { text = LightTreeUtil.toFilteredString(tree, typeElement, null); } - return new TypeInfo(text, arrayCount, isEllipsis, ContainerUtil.emptyList()); + return new TypeInfo(text, arrayCount, isEllipsis, PsiAnnotationStub.EMPTY_ARRAY); } @NotNull @@ -198,7 +199,7 @@ public class TypeInfo { typeText = typeText.substring(0, typeText.length() - 2); } - return new TypeInfo(typeText, arrayCount, isEllipsis, ContainerUtil.emptyList()); + return new TypeInfo(typeText, arrayCount, isEllipsis, PsiAnnotationStub.EMPTY_ARRAY); } @NotNull @@ -220,12 +221,12 @@ public class TypeInfo { } int frequentIndex = FREQUENT_INDEX_MASK & flags; - byte arrayCount = isSet(flags, HAS_ARRAY_COUNT) ? record.readByte() : 0; - boolean hasEllipsis = isSet(flags, HAS_ELLIPSIS); + byte arrayCount = BitUtil.isSet(flags, HAS_ARRAY_COUNT) ? record.readByte() : 0; + boolean hasEllipsis = BitUtil.isSet(flags, HAS_ELLIPSIS); StringRef text = frequentIndex == 0 ? record.readName() : StringRef.fromString(ourIndexFrequentType[frequentIndex]); - return new TypeInfo(text, arrayCount, hasEllipsis, ContainerUtil.emptyList()); + return new TypeInfo(text, arrayCount, hasEllipsis, PsiAnnotationStub.EMPTY_ARRAY); } public static void writeTYPE(@NotNull StubOutputStream dataStream, @NotNull TypeInfo typeInfo) throws IOException { @@ -254,7 +255,7 @@ public class TypeInfo { if (typeInfo == NULL || typeInfo.text == null) { return null; } - if (typeInfo.arrayCount == 0 && typeInfo.myAnnotationStubs.isEmpty()) { + if (typeInfo.arrayCount == 0 && typeInfo.myAnnotationStubs.length == 0) { return typeInfo.text.getString(); } diff --git a/java/java-psi-impl/src/com/intellij/psi/impl/compiled/StubBuildingVisitor.java b/java/java-psi-impl/src/com/intellij/psi/impl/compiled/StubBuildingVisitor.java index 3878101a4436..37a1eb60ca3d 100644 --- a/java/java-psi-impl/src/com/intellij/psi/impl/compiled/StubBuildingVisitor.java +++ b/java/java-psi-impl/src/com/intellij/psi/impl/compiled/StubBuildingVisitor.java @@ -1,5 +1,5 @@ /* - * Copyright 2000-2013 JetBrains s.r.o. + * 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. @@ -37,7 +37,6 @@ import java.lang.reflect.Array; import java.text.CharacterIterator; import java.text.StringCharacterIterator; import java.util.ArrayList; -import java.util.Collections; import java.util.List; import java.util.regex.Pattern; @@ -387,7 +386,7 @@ public class StubBuildingVisitor extends ClassVisitor { if (dim > 0) { type = type.getElementType(); } - return new TypeInfo(getTypeText(type), (byte)dim, false, Collections.emptyList()); //todo read annos from .class file + return new TypeInfo(getTypeText(type), (byte)dim, false, PsiAnnotationStub.EMPTY_ARRAY); //todo read annos from .class file } private static final String[] parameterNames = {"p1", "p2", "p3", "p4", "p5", "p6", "p7", "p8", "p9"}; diff --git a/java/java-psi-impl/src/com/intellij/psi/impl/java/stubs/PsiAnnotationStub.java b/java/java-psi-impl/src/com/intellij/psi/impl/java/stubs/PsiAnnotationStub.java index 424ff045a118..558065fbed88 100644 --- a/java/java-psi-impl/src/com/intellij/psi/impl/java/stubs/PsiAnnotationStub.java +++ b/java/java-psi-impl/src/com/intellij/psi/impl/java/stubs/PsiAnnotationStub.java @@ -1,5 +1,5 @@ /* - * Copyright 2000-2012 JetBrains s.r.o. + * 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. @@ -22,6 +22,7 @@ import com.intellij.psi.stubs.StubElement; * @author max */ public interface PsiAnnotationStub extends StubElement { + PsiAnnotationStub[] EMPTY_ARRAY = new PsiAnnotationStub[0]; String getText(); PsiAnnotation getPsiElement(); From 99870ef46ce07ed81d68ad9521b1d569019611d9 Mon Sep 17 00:00:00 2001 From: Alexey Kudravtsev Date: Fri, 21 Mar 2014 13:47:36 +0400 Subject: [PATCH 24/36] optimisation: overload to reduce varargs array allocation --- platform/util/src/com/intellij/util/ReflectionUtil.java | 9 +++++++++ 1 file changed, 9 insertions(+) diff --git a/platform/util/src/com/intellij/util/ReflectionUtil.java b/platform/util/src/com/intellij/util/ReflectionUtil.java index d80d2e0bf129..e930aca65fa9 100644 --- a/platform/util/src/com/intellij/util/ReflectionUtil.java +++ b/platform/util/src/com/intellij/util/ReflectionUtil.java @@ -392,6 +392,15 @@ public class ReflectionUtil { throw new RuntimeException(e); } } + @NotNull + public static T createInstanceViaConstructorAccessor(@NotNull ConstructorAccessor constructorAccessor) { + try { + return (T)constructorAccessor.newInstance(ArrayUtil.EMPTY_OBJECT_ARRAY); + } + catch (Exception e) { + throw new RuntimeException(e); + } + } @NotNull public static T createInstance(@NotNull Constructor constructor, @NotNull Object... args) { From 509a630b1e66f9b3f3f7117f8abf5ffc67bc91ca Mon Sep 17 00:00:00 2001 From: Alexey Kudravtsev Date: Fri, 21 Mar 2014 13:48:06 +0400 Subject: [PATCH 25/36] cleanup --- .../openapi/vfs/newvfs/impl/FileNameCache.java | 10 ++++++---- 1 file changed, 6 insertions(+), 4 deletions(-) diff --git a/platform/platform-impl/src/com/intellij/openapi/vfs/newvfs/impl/FileNameCache.java b/platform/platform-impl/src/com/intellij/openapi/vfs/newvfs/impl/FileNameCache.java index 3f2c4abebf7f..a16886740be6 100644 --- a/platform/platform-impl/src/com/intellij/openapi/vfs/newvfs/impl/FileNameCache.java +++ b/platform/platform-impl/src/com/intellij/openapi/vfs/newvfs/impl/FileNameCache.java @@ -55,8 +55,9 @@ public class FileNameCache { Object rawName = convertToBytesIfAsciiString(name); IntObjectLinkedMap.MapEntry entry = new IntObjectLinkedMap.MapEntry(id, rawName); - synchronized (ourNameCache[stripe]) { - return ourNameCache[stripe].cacheEntry(entry); + IntSLRUCache> cache = ourNameCache[stripe]; + synchronized (cache) { + return cache.cacheEntry(entry); } } @@ -91,8 +92,9 @@ public class FileNameCache { @NotNull private static IntObjectLinkedMap.MapEntry getEntry(int id) { final int stripe = calcStripeIdFromNameId(id); - synchronized (ourNameCache[stripe]) { - IntObjectLinkedMap.MapEntry entry = ourNameCache[stripe].getCachedEntry(id); + IntSLRUCache> cache = ourNameCache[stripe]; + synchronized (cache) { + IntObjectLinkedMap.MapEntry entry = cache.getCachedEntry(id); if (entry != null) { return entry; } From 79aa7418db9a30d785d7b78dbd5a046024400b77 Mon Sep 17 00:00:00 2001 From: nik Date: Fri, 21 Mar 2014 14:19:58 +0400 Subject: [PATCH 26/36] IDEA-122476: Pack JPS distribution into one zip file --- build/scripts/dist.gant | 2 +- build/scripts/layouts.gant | 135 +++++++++++++++++++------------------ 2 files changed, 69 insertions(+), 68 deletions(-) diff --git a/build/scripts/dist.gant b/build/scripts/dist.gant index b4ae0799980d..43af3735db31 100644 --- a/build/scripts/dist.gant +++ b/build/scripts/dist.gant @@ -101,7 +101,7 @@ def layoutAll(Map args, String home, String out, Paths _paths = null, buildJps = layouts.layout_core(home, paths.artifacts_core) notifyArtifactBuilt(paths.artifacts_core) if (buildJps) { - layouts.layoutCommunityJps(home, paths.artifacts_jps) + layouts.layoutJps(home, paths.artifacts_jps, args.buildNumber, {}) notifyArtifactBuilt(paths.artifacts_jps) } diff --git a/build/scripts/layouts.gant b/build/scripts/layouts.gant index 10e21b7c7ee9..ea7d98d24d85 100644 --- a/build/scripts/layouts.gant +++ b/build/scripts/layouts.gant @@ -703,75 +703,76 @@ def layoutAndroid(String androidHome) { } } -def layoutCommunityJps(String home, String target) { - layout(target) { - jar("util.jar") { - module("annotations") - module("util-rt") - module("util") - } - - jar("jps-launcher.jar") { - module("jps-launcher") - } - - jar("jps-model.jar") { - module("jps-model-api") - module("jps-model-impl") - module("jps-model-serialization") - } - jar("jps-builders.jar") { - module("forms_rt") - module("forms-compiler") - module("instrumentation-util") - module("jps-builders") - module("jps-plugin-system") - module("jps-standalone-builder") - module("java-runtime") - } - jar("groovy-jps-plugin.jar") { - module("groovy-jps-plugin") - module("groovy-rt-constants") - } - jar("groovy_rt.jar") { - module("groovy_rt") - } - jar("ui-designer-jps-plugin.jar") { module("ui-designer-jps-plugin") } - - - jar("maven-jps-plugin.jar") { module("maven-jps-plugin") } - fileset(dir: "$home/plugins/maven/maven3-server-impl/lib/maven3/lib") {include(name: "plexus-utils-*.jar")} - - jar("eclipse-jps-plugin.jar") { - module("common-eclipse-util") - module("eclipse-jps-plugin") - } - jar("devkit-jps-plugin.jar") { module("devkit-jps-plugin") } - jar("intellilang-jps-plugin.jar") { module("intellilang-jps-plugin") } - fileset(dir: "$home/lib") { - include(name: "jdom.jar") - include(name: "jna.jar") - include(name: "trove4j.jar") - include(name: "asm4-all.jar") - include(name: "nanoxml-*.jar") - include(name: "protobuf-*.jar") - include(name: "cli-parser-*.jar") - include(name: "log4j.jar") - include(name: "jgoodies-forms.jar") - include(name: "ecj*.jar") - include(name: "jsr166e.jar") - } - fileset(dir: "$home/jps/lib") { - include(name: "optimizedFileManager.jar") - } - dir("test") { - jar("jps-build-test.jar") { - moduleTests("jps-builders") - moduleTests("jps-model-tests") - moduleTests("jps-serialization-tests") +def layoutJps(String home, String targetDir, String buildNumber, Closure additionalJars) { + layout(targetDir) { + zip("standalone-jps-${buildNumber}.zip") { + jar("util.jar") { + module("annotations") + module("util-rt") + module("util") } + + jar("jps-launcher.jar") { + module("jps-launcher") + } + + jar("jps-model.jar") { + module("jps-model-api") + module("jps-model-impl") + module("jps-model-serialization") + } + jar("jps-builders.jar") { + module("forms_rt") + module("forms-compiler") + module("instrumentation-util") + module("jps-builders") + module("jps-plugin-system") + module("jps-standalone-builder") + module("java-runtime") + } + jar("groovy-jps-plugin.jar") { + module("groovy-jps-plugin") + module("groovy-rt-constants") + } + jar("groovy_rt.jar") { + module("groovy_rt") + } + jar("ui-designer-jps-plugin.jar") { module("ui-designer-jps-plugin") } + + + jar("maven-jps-plugin.jar") { module("maven-jps-plugin") } + fileset(dir: "$home/plugins/maven/maven3-server-impl/lib/maven3/lib") {include(name: "plexus-utils-*.jar")} + + jar("eclipse-jps-plugin.jar") { + module("common-eclipse-util") + module("eclipse-jps-plugin") + } + jar("devkit-jps-plugin.jar") { module("devkit-jps-plugin") } + jar("intellilang-jps-plugin.jar") { module("intellilang-jps-plugin") } + fileset(dir: "$home/lib") { + include(name: "jdom.jar") + include(name: "jna.jar") + include(name: "trove4j.jar") + include(name: "asm4-all.jar") + include(name: "nanoxml-*.jar") + include(name: "protobuf-*.jar") + include(name: "cli-parser-*.jar") + include(name: "log4j.jar") + include(name: "jgoodies-forms.jar") + include(name: "ecj*.jar") + include(name: "jsr166e.jar") + } + fileset(dir: "$home/jps/lib") { + include(name: "optimizedFileManager.jar") + } + jar("ant-jps-plugin.jar") { module("ant-jps-plugin") } + additionalJars() + } + jar("jps-build-test-${buildNumber}.jar") { + moduleTests("jps-builders") + moduleTests("jps-model-tests") + moduleTests("jps-serialization-tests") } - jar("ant-jps-plugin.jar") { module("ant-jps-plugin") } } } From e30e9a79251c6c1fdd5994f1dfa852023c534f4e Mon Sep 17 00:00:00 2001 From: Alexander Zolotov Date: Fri, 21 Mar 2014 14:21:25 +0400 Subject: [PATCH 27/36] WEB-11445 AngularJS filters break Emmet - delete key and commit document after key processing --- .../template/emmet/ZenCodingTemplate.java | 17 ++++++++++------- 1 file changed, 10 insertions(+), 7 deletions(-) diff --git a/xml/impl/src/com/intellij/codeInsight/template/emmet/ZenCodingTemplate.java b/xml/impl/src/com/intellij/codeInsight/template/emmet/ZenCodingTemplate.java index 39cf1ed094e6..abebcbbc50e9 100644 --- a/xml/impl/src/com/intellij/codeInsight/template/emmet/ZenCodingTemplate.java +++ b/xml/impl/src/com/intellij/codeInsight/template/emmet/ZenCodingTemplate.java @@ -183,14 +183,11 @@ public class ZenCodingTemplate extends CustomLiveTemplateBase { if (node == null) { return; } - if (surroundedText == null) { - if (node instanceof TemplateNode) { - if (key.equals(((TemplateNode)node).getTemplateToken().getKey()) && callback.findApplicableTemplates(key).size() > 1) { - callback.startTemplate(); - return; - } + if (surroundedText == null && node instanceof TemplateNode) { + if (key.equals(((TemplateNode)node).getTemplateToken().getKey()) && callback.findApplicableTemplates(key).size() > 1) { + callback.startTemplate(); + return; } - callback.deleteTemplateKey(key); } PsiElement context = callback.getContext(); @@ -198,6 +195,12 @@ public class ZenCodingTemplate extends CustomLiveTemplateBase { List filters = getFilters(node, context); filters.addAll(extraFilters); + + if (surroundedText == null) { + callback.deleteTemplateKey(key); + // commit is required. otherwise injections placed after caret will be broken + PsiDocumentManager.getInstance(callback.getProject()).commitDocument(callback.getEditor().getDocument()); + } expand(node, generator, filters, surroundedText, callback, expandPrimitiveAbbreviations); } From 6a860741191aa58fa92503992e229d409bf023f3 Mon Sep 17 00:00:00 2001 From: Alexander Zolotov Date: Fri, 21 Mar 2014 14:38:02 +0400 Subject: [PATCH 28/36] TemplateState: yet another debug info --- .../com/intellij/codeInsight/template/impl/TemplateState.java | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/platform/lang-impl/src/com/intellij/codeInsight/template/impl/TemplateState.java b/platform/lang-impl/src/com/intellij/codeInsight/template/impl/TemplateState.java index ccac27bb3f98..165e2be8b320 100644 --- a/platform/lang-impl/src/com/intellij/codeInsight/template/impl/TemplateState.java +++ b/platform/lang-impl/src/com/intellij/codeInsight/template/impl/TemplateState.java @@ -398,8 +398,8 @@ public class TemplateState implements Disposable { myTemplate.getKey() + "\ntemplateText: " + myTemplate.getTemplateText() + - "\ntemplateText: " + - myTemplate.getTemplateText(); + "\ntemplateString: " + + myTemplate.getString(); } private void doReformat(final TextRange range) { From f1c1d239ceaefaf90719b04160d88866be09d88d Mon Sep 17 00:00:00 2001 From: Dmitry Avdeev Date: Fri, 21 Mar 2014 14:58:40 +0400 Subject: [PATCH 29/36] verbose assertion --- .../src/com/intellij/testFramework/LightPlatformTestCase.java | 3 +-- 1 file changed, 1 insertion(+), 2 deletions(-) diff --git a/platform/testFramework/src/com/intellij/testFramework/LightPlatformTestCase.java b/platform/testFramework/src/com/intellij/testFramework/LightPlatformTestCase.java index 1cdbe4fa91a2..4eb294025dd7 100644 --- a/platform/testFramework/src/com/intellij/testFramework/LightPlatformTestCase.java +++ b/platform/testFramework/src/com/intellij/testFramework/LightPlatformTestCase.java @@ -34,7 +34,6 @@ import com.intellij.idea.IdeaLogger; import com.intellij.idea.IdeaTestApplication; import com.intellij.openapi.actionSystem.CommonDataKeys; import com.intellij.openapi.actionSystem.DataProvider; -import com.intellij.openapi.actionSystem.PlatformDataKeys; import com.intellij.openapi.application.Application; import com.intellij.openapi.application.ApplicationManager; import com.intellij.openapi.application.ex.ApplicationEx; @@ -444,7 +443,7 @@ public abstract class LightPlatformTestCase extends UsefulTestCase implements Da } }); - assertEmpty(unsavedDocuments); + assertEmpty("There are unsaved documents", Arrays.asList(unsavedDocuments)); } } From 0aabc49318dc36ec4a849a870062d307bb1641eb Mon Sep 17 00:00:00 2001 From: nik Date: Fri, 21 Mar 2014 15:02:36 +0400 Subject: [PATCH 30/36] removed obsolete run configuration template from default project settings --- resources/src/idea/RunManager.xml | 5 ----- 1 file changed, 5 deletions(-) diff --git a/resources/src/idea/RunManager.xml b/resources/src/idea/RunManager.xml index 7c5577dd458c..3377352115c5 100644 --- a/resources/src/idea/RunManager.xml +++ b/resources/src/idea/RunManager.xml @@ -44,9 +44,4 @@ - - - localhost - 5050 - From 26688195f37c9eee581163c6d873c748affe9b78 Mon Sep 17 00:00:00 2001 From: Vladimir Krivosheev Date: Fri, 21 Mar 2014 10:51:52 +0100 Subject: [PATCH 31/36] cleanup --- .../intellij/execution/ui/CommonProgramParametersPanel.java | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/platform/lang-impl/src/com/intellij/execution/ui/CommonProgramParametersPanel.java b/platform/lang-impl/src/com/intellij/execution/ui/CommonProgramParametersPanel.java index acd4a017fc1a..7a52248840ad 100644 --- a/platform/lang-impl/src/com/intellij/execution/ui/CommonProgramParametersPanel.java +++ b/platform/lang-impl/src/com/intellij/execution/ui/CommonProgramParametersPanel.java @@ -69,8 +69,6 @@ public class CommonProgramParametersPanel extends JPanel implements PanelWithAnc protected void initComponents() { myProgramParametersComponent = LabeledComponent.create(new RawCommandLineEditor(), ExecutionBundle.message("run.configuration.program.parameters")); - - final JPanel panel = new JPanel(new BorderLayout()); myWorkingDirectoryField = new TextFieldWithBrowseButton(new ActionListener() { @Override public void actionPerformed(ActionEvent e) { @@ -91,6 +89,8 @@ public class CommonProgramParametersPanel extends JPanel implements PanelWithAnc super.installPathCompletion(FileChooserDescriptorFactory.createSingleFolderDescriptor()); } }; + + final JPanel panel = new JPanel(new BorderLayout()); panel.add(myWorkingDirectoryField, BorderLayout.CENTER); final FixedSizeButton button = new FixedSizeButton(myWorkingDirectoryField); @@ -171,7 +171,7 @@ public class CommonProgramParametersPanel extends JPanel implements PanelWithAnc @Override public void setAnchor(JComponent anchor) { - this.myAnchor = anchor; + myAnchor = anchor; myProgramParametersComponent.setAnchor(anchor); myWorkingDirectoryComponent.setAnchor(anchor); myEnvVariablesComponent.setAnchor(anchor); From 99c0991878b1b14e28e1f18e214bbbe40108540b Mon Sep 17 00:00:00 2001 From: Vladimir Krivosheev Date: Fri, 21 Mar 2014 10:58:08 +0100 Subject: [PATCH 32/36] cleanup --- .../execution/util/ProgramParametersConfigurator.java | 8 ++++---- 1 file changed, 4 insertions(+), 4 deletions(-) diff --git a/platform/lang-impl/src/com/intellij/execution/util/ProgramParametersConfigurator.java b/platform/lang-impl/src/com/intellij/execution/util/ProgramParametersConfigurator.java index 0cd5d1677bcb..af2ea11eaea4 100644 --- a/platform/lang-impl/src/com/intellij/execution/util/ProgramParametersConfigurator.java +++ b/platform/lang-impl/src/com/intellij/execution/util/ProgramParametersConfigurator.java @@ -56,12 +56,12 @@ public class ProgramParametersConfigurator { public String getWorkingDir(CommonProgramRunConfigurationParameters configuration, Project project, Module module) { String workingDirectory = configuration.getWorkingDirectory(); String defaultWorkingDir = getDefaultWorkingDir(project); - - if (workingDirectory == null || workingDirectory.trim().length() == 0) { + if (StringUtil.isEmptyOrSpaces(workingDirectory)) { workingDirectory = defaultWorkingDir; + if (workingDirectory == null) { + return null; + } } - if (workingDirectory == null) - return null; workingDirectory = expandPath(workingDirectory, module, project); if (!FileUtil.isAbsolute(workingDirectory) && defaultWorkingDir != null) { if (("$" + PathMacroUtil.MODULE_DIR_MACRO_NAME + "$").equals(workingDirectory)) { From e8fa6ae4dece699299249841d1f277e93b599834 Mon Sep 17 00:00:00 2001 From: Aleksey Pivovarov Date: Fri, 21 Mar 2014 15:03:04 +0400 Subject: [PATCH 33/36] IDEA-122626 Github: try to reuse existing access token Github allows to create only one token with the same "Note" --- .../plugins/github/api/GithubApiUtil.java | 105 +++++++++++++++--- .../github/api/GithubAuthorization.java | 16 ++- ... => GithubAuthorizationCreateRequest.java} | 4 +- .../github/api/GithubAuthorizationRaw.java | 2 +- .../api/GithubAuthorizationUpdateRequest.java | 32 ++++++ .../github/tasks/GithubRepositoryEditor.java | 2 +- 6 files changed, 142 insertions(+), 19 deletions(-) rename plugins/github/src/org/jetbrains/plugins/github/api/{GithubAuthorizationRequest.java => GithubAuthorizationCreateRequest.java} (86%) create mode 100644 plugins/github/src/org/jetbrains/plugins/github/api/GithubAuthorizationUpdateRequest.java diff --git a/plugins/github/src/org/jetbrains/plugins/github/api/GithubApiUtil.java b/plugins/github/src/org/jetbrains/plugins/github/api/GithubApiUtil.java index bf2ba08de4f8..486b5ac2da2a 100644 --- a/plugins/github/src/org/jetbrains/plugins/github/api/GithubApiUtil.java +++ b/plugins/github/src/org/jetbrains/plugins/github/api/GithubApiUtil.java @@ -66,7 +66,7 @@ public class GithubApiUtil { } private enum HttpVerb { - GET, POST, DELETE, HEAD + GET, POST, DELETE, HEAD, PATCH } @Nullable @@ -77,6 +77,14 @@ public class GithubApiUtil { return request(auth, path, requestBody, Arrays.asList(headers), HttpVerb.POST).getJsonElement(); } + @Nullable + private static JsonElement patchRequest(@NotNull GithubAuthData auth, + @NotNull String path, + @Nullable String requestBody, + @NotNull Header... headers) throws IOException { + return request(auth, path, requestBody, Arrays.asList(headers), HttpVerb.PATCH).getJsonElement(); + } + @Nullable private static JsonElement deleteRequest(@NotNull GithubAuthData auth, @NotNull String path, @NotNull Header... headers) throws IOException { @@ -95,7 +103,7 @@ public class GithubApiUtil { @NotNull Collection
headers, @NotNull HttpVerb verb) throws IOException { if (EventQueue.isDispatchThread() && !ApplicationManager.getApplication().isUnitTestMode()) { - LOG.warn("Network operation in EDT"); + LOG.warn("Network operation in EDT"); // TODO: fix } HttpMethod method = null; @@ -152,6 +160,17 @@ public class GithubApiUtil { ((PostMethod)method).setRequestEntity(new StringRequestEntity(requestBody, "application/json", "UTF-8")); } break; + case PATCH: + method = new PostMethod(uri) { // TODO: httpclient 4.x + @Override + public String getName() { + return "PATCH"; + } + }; + if (requestBody != null) { + ((PostMethod)method).setRequestEntity(new StringRequestEntity(requestBody, "application/json", "UTF-8")); + } + break; case GET: method = new GetMethod(uri); break; @@ -408,7 +427,8 @@ public class GithubApiUtil { public static void askForTwoFactorCodeSMS(@NotNull GithubAuthData auth) { try { postRequest(auth, "/authorizations", null, ACCEPT_V3_JSON); - } catch (IOException e) { + } + catch (IOException e) { LOG.info(e); } } @@ -441,25 +461,78 @@ public class GithubApiUtil { } @NotNull - public static String getScopedToken(@NotNull GithubAuthData auth, @NotNull Collection scopes, @Nullable String note) + public static String getScopedToken(@NotNull GithubAuthData auth, @NotNull Collection scopes, @NotNull String note) throws IOException { + GithubAuthorization token = findToken(auth, note); + if (token == null) { + return getNewScopedToken(auth, scopes, note).getToken(); + } + if (token.getScopes().containsAll(scopes)) { + return token.getToken(); + } + return updateTokenScopes(auth, token, scopes).getToken(); + } + + @NotNull + private static GithubAuthorization updateTokenScopes(@NotNull GithubAuthData auth, + @NotNull GithubAuthorization token, + @NotNull Collection scopes) throws IOException { try { - String path = "/authorizations"; + String path = "/authorizations/" + token.getId(); - GithubAuthorizationRequest request = new GithubAuthorizationRequest(new ArrayList(scopes), note, null); - GithubAuthorization response = - createDataFromRaw(fromJson(postRequest(auth, path, gson.toJson(request)), GithubAuthorizationRaw.class), GithubAuthorization.class); + GithubAuthorizationUpdateRequest request = new GithubAuthorizationUpdateRequest(new ArrayList(scopes)); - return response.getToken(); + return createDataFromRaw(fromJson(patchRequest(auth, path, gson.toJson(request), ACCEPT_V3_JSON), GithubAuthorizationRaw.class), + GithubAuthorization.class); } catch (GithubConfusingException e) { - e.setDetails("Can't get token: scopes - " + scopes); + e.setDetails("Can't update token: scopes - " + scopes); throw e; } } @NotNull - public static String getMasterToken(@NotNull GithubAuthData auth, @Nullable String note) throws IOException { + private static GithubAuthorization getNewScopedToken(@NotNull GithubAuthData auth, + @NotNull Collection scopes, + @NotNull String note) + throws IOException { + try { + String path = "/authorizations"; + + GithubAuthorizationCreateRequest request = new GithubAuthorizationCreateRequest(new ArrayList(scopes), note, null); + + return createDataFromRaw(fromJson(postRequest(auth, path, gson.toJson(request), ACCEPT_V3_JSON), GithubAuthorizationRaw.class), + GithubAuthorization.class); + } + catch (GithubConfusingException e) { + e.setDetails("Can't create token: scopes - " + scopes + " - note " + note); + throw e; + } + } + + @Nullable + private static GithubAuthorization findToken(@NotNull GithubAuthData auth, @NotNull String note) throws IOException { + try { + String path = "/authorizations"; + + PagedRequest request = + new PagedRequest(path, GithubAuthorization.class, GithubAuthorizationRaw[].class, ACCEPT_V3_JSON); + + List tokens = request.getAll(auth); + + for (GithubAuthorization token : tokens) { + if (note.equals(token.getNote())) return token; + } + return null; + } + catch (GithubConfusingException e) { + e.setDetails("Can't get available tokens"); + throw e; + } + } + + @NotNull + public static String getMasterToken(@NotNull GithubAuthData auth, @NotNull String note) throws IOException { // "repo" - read/write access to public/private repositories // "gist" - create/delete gists List scopes = Arrays.asList("repo", "gist"); @@ -468,7 +541,7 @@ public class GithubApiUtil { } @NotNull - public static String getReadOnlyToken(@NotNull GithubAuthData auth, @NotNull String user, @NotNull String repo, @Nullable String note) + public static String getReadOnlyToken(@NotNull GithubAuthData auth, @NotNull String user, @NotNull String repo, @NotNull String note) throws IOException { GithubRepo repository = getDetailedRepoInfo(auth, user, repo); @@ -543,10 +616,14 @@ public class GithubApiUtil { // One of this may not exist in GitHub enterprise try { repos.addAll(getMembershipRepos(auth)); - } catch (GithubStatusCodeException ignore) {} + } + catch (GithubStatusCodeException ignore) { + } try { repos.addAll(getWatchedRepos(auth)); - } catch (GithubStatusCodeException ignore) {} + } + catch (GithubStatusCodeException ignore) { + } return repos; } diff --git a/plugins/github/src/org/jetbrains/plugins/github/api/GithubAuthorization.java b/plugins/github/src/org/jetbrains/plugins/github/api/GithubAuthorization.java index ad34cbd7865f..d5ac4275152f 100644 --- a/plugins/github/src/org/jetbrains/plugins/github/api/GithubAuthorization.java +++ b/plugins/github/src/org/jetbrains/plugins/github/api/GithubAuthorization.java @@ -16,6 +16,7 @@ package org.jetbrains.plugins.github.api; import org.jetbrains.annotations.NotNull; +import org.jetbrains.annotations.Nullable; import java.util.List; @@ -23,12 +24,16 @@ import java.util.List; * @author Aleksey Pivovarov */ public class GithubAuthorization { + private final long myId; + @Nullable private final String myNote; @NotNull private final String myToken; @NotNull private final List myScopes; - public GithubAuthorization(@NotNull String token, @NotNull List scopes) { + public GithubAuthorization(long id, @NotNull String token, @NotNull List scopes, @Nullable String note) { + myId = id; myToken = token; myScopes = scopes; + myNote = note; } @NotNull @@ -40,4 +45,13 @@ public class GithubAuthorization { public List getScopes() { return myScopes; } + + @Nullable + public String getNote() { + return myNote; + } + + public long getId() { + return myId; + } } diff --git a/plugins/github/src/org/jetbrains/plugins/github/api/GithubAuthorizationRequest.java b/plugins/github/src/org/jetbrains/plugins/github/api/GithubAuthorizationCreateRequest.java similarity index 86% rename from plugins/github/src/org/jetbrains/plugins/github/api/GithubAuthorizationRequest.java rename to plugins/github/src/org/jetbrains/plugins/github/api/GithubAuthorizationCreateRequest.java index 705cdbd950e7..6f6d28b0de85 100644 --- a/plugins/github/src/org/jetbrains/plugins/github/api/GithubAuthorizationRequest.java +++ b/plugins/github/src/org/jetbrains/plugins/github/api/GithubAuthorizationCreateRequest.java @@ -24,13 +24,13 @@ import java.util.List; * @author Aleksey Pivovarov */ @SuppressWarnings({"FieldCanBeLocal", "UnusedDeclaration"}) -class GithubAuthorizationRequest { +class GithubAuthorizationCreateRequest { @NotNull private final List scopes; @Nullable private final String note; @Nullable private final String noteUrl; - public GithubAuthorizationRequest(@NotNull List scopes, @Nullable String note, @Nullable String noteUrl) { + public GithubAuthorizationCreateRequest(@NotNull List scopes, @Nullable String note, @Nullable String noteUrl) { this.scopes = scopes; this.note = note; this.noteUrl = noteUrl; diff --git a/plugins/github/src/org/jetbrains/plugins/github/api/GithubAuthorizationRaw.java b/plugins/github/src/org/jetbrains/plugins/github/api/GithubAuthorizationRaw.java index 0af5a6e24d33..3abddbd00aa2 100644 --- a/plugins/github/src/org/jetbrains/plugins/github/api/GithubAuthorizationRaw.java +++ b/plugins/github/src/org/jetbrains/plugins/github/api/GithubAuthorizationRaw.java @@ -34,7 +34,7 @@ class GithubAuthorizationRaw implements DataConstructor { @SuppressWarnings("ConstantConditions") public GithubAuthorization createAuthorization() { - return new GithubAuthorization(token, scopes); + return new GithubAuthorization(id, token, scopes, note); } @SuppressWarnings("unchecked") diff --git a/plugins/github/src/org/jetbrains/plugins/github/api/GithubAuthorizationUpdateRequest.java b/plugins/github/src/org/jetbrains/plugins/github/api/GithubAuthorizationUpdateRequest.java new file mode 100644 index 000000000000..8173d5a95345 --- /dev/null +++ b/plugins/github/src/org/jetbrains/plugins/github/api/GithubAuthorizationUpdateRequest.java @@ -0,0 +1,32 @@ +/* + * Copyright 2000-2013 JetBrains s.r.o. + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ +package org.jetbrains.plugins.github.api; + +import org.jetbrains.annotations.NotNull; + +import java.util.List; + +/** + * @author Aleksey Pivovarov + */ +@SuppressWarnings({"FieldCanBeLocal", "UnusedDeclaration"}) +class GithubAuthorizationUpdateRequest { + @NotNull private final List addScopes; + + public GithubAuthorizationUpdateRequest(@NotNull List newScopes) { + this.addScopes = newScopes; + } +} diff --git a/plugins/github/src/org/jetbrains/plugins/github/tasks/GithubRepositoryEditor.java b/plugins/github/src/org/jetbrains/plugins/github/tasks/GithubRepositoryEditor.java index 059be25cb7e3..400be7248f87 100644 --- a/plugins/github/src/org/jetbrains/plugins/github/tasks/GithubRepositoryEditor.java +++ b/plugins/github/src/org/jetbrains/plugins/github/tasks/GithubRepositoryEditor.java @@ -131,7 +131,7 @@ public class GithubRepositoryEditor extends BaseRepositoryEditor Date: Fri, 21 Mar 2014 12:31:39 +0100 Subject: [PATCH 34/36] CR-IC-4915 (cleanup) --- .../src/com/intellij/psi/impl/cache/TypeInfo.java | 13 ++++++++----- .../psi/impl/java/stubs/PsiAnnotationStub.java | 1 + 2 files changed, 9 insertions(+), 5 deletions(-) diff --git a/java/java-psi-impl/src/com/intellij/psi/impl/cache/TypeInfo.java b/java/java-psi-impl/src/com/intellij/psi/impl/cache/TypeInfo.java index 346e80c6eb7a..9a078bbc9573 100644 --- a/java/java-psi-impl/src/com/intellij/psi/impl/cache/TypeInfo.java +++ b/java/java-psi-impl/src/com/intellij/psi/impl/cache/TypeInfo.java @@ -33,7 +33,6 @@ import com.intellij.psi.stubs.StubElement; import com.intellij.psi.stubs.StubInputStream; import com.intellij.psi.stubs.StubOutputStream; import com.intellij.psi.tree.IElementType; -import com.intellij.util.BitUtil; import com.intellij.util.SmartList; import com.intellij.util.io.StringRef; import gnu.trove.TObjectIntHashMap; @@ -43,6 +42,8 @@ import org.jetbrains.annotations.Nullable; import java.io.IOException; import java.util.List; +import static com.intellij.util.BitUtil.isSet; + /** * @author max */ @@ -113,8 +114,10 @@ public class TypeInfo { annotationStubs.add(annotationStub); } } - PsiAnnotationStub[] stubs = annotationStubs == null ? PsiAnnotationStub.EMPTY_ARRAY : annotationStubs.toArray(new PsiAnnotationStub[annotationStubs.size()]); - return new TypeInfo(text, arrayCount, isEllipsis, stubs); + + PsiAnnotationStub[] stubArray = PsiAnnotationStub.EMPTY_ARRAY; + if (annotationStubs != null) stubArray = annotationStubs.toArray(new PsiAnnotationStub[annotationStubs.size()]); + return new TypeInfo(text, arrayCount, isEllipsis, stubArray); } @NotNull @@ -221,8 +224,8 @@ public class TypeInfo { } int frequentIndex = FREQUENT_INDEX_MASK & flags; - byte arrayCount = BitUtil.isSet(flags, HAS_ARRAY_COUNT) ? record.readByte() : 0; - boolean hasEllipsis = BitUtil.isSet(flags, HAS_ELLIPSIS); + byte arrayCount = isSet(flags, HAS_ARRAY_COUNT) ? record.readByte() : 0; + boolean hasEllipsis = isSet(flags, HAS_ELLIPSIS); StringRef text = frequentIndex == 0 ? record.readName() : StringRef.fromString(ourIndexFrequentType[frequentIndex]); diff --git a/java/java-psi-impl/src/com/intellij/psi/impl/java/stubs/PsiAnnotationStub.java b/java/java-psi-impl/src/com/intellij/psi/impl/java/stubs/PsiAnnotationStub.java index 558065fbed88..27e3f0bdd9c3 100644 --- a/java/java-psi-impl/src/com/intellij/psi/impl/java/stubs/PsiAnnotationStub.java +++ b/java/java-psi-impl/src/com/intellij/psi/impl/java/stubs/PsiAnnotationStub.java @@ -23,6 +23,7 @@ import com.intellij.psi.stubs.StubElement; */ public interface PsiAnnotationStub extends StubElement { PsiAnnotationStub[] EMPTY_ARRAY = new PsiAnnotationStub[0]; + String getText(); PsiAnnotation getPsiElement(); From da5b8f3d7838c9275b3b9006b4f9c4e74bc9d73e Mon Sep 17 00:00:00 2001 From: Andrey Vokin Date: Fri, 21 Mar 2014 15:39:01 +0400 Subject: [PATCH 35/36] Slim injection directly in the tree --- .../src/META-INF/XmlPlugin.xml | 1 + .../lexer/EmbeddedTokenTypesProvider.java | 30 +++++++++++++++++++ 2 files changed, 31 insertions(+) create mode 100644 xml/xml-psi-impl/src/com/intellij/lexer/EmbeddedTokenTypesProvider.java diff --git a/platform/platform-resources/src/META-INF/XmlPlugin.xml b/platform/platform-resources/src/META-INF/XmlPlugin.xml index 898b55aae3ea..37464e9f8c15 100644 --- a/platform/platform-resources/src/META-INF/XmlPlugin.xml +++ b/platform/platform-resources/src/META-INF/XmlPlugin.xml @@ -67,6 +67,7 @@ + diff --git a/xml/xml-psi-impl/src/com/intellij/lexer/EmbeddedTokenTypesProvider.java b/xml/xml-psi-impl/src/com/intellij/lexer/EmbeddedTokenTypesProvider.java new file mode 100644 index 000000000000..b009726e3a6f --- /dev/null +++ b/xml/xml-psi-impl/src/com/intellij/lexer/EmbeddedTokenTypesProvider.java @@ -0,0 +1,30 @@ +/* + * 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.lexer; + +import com.intellij.openapi.extensions.ExtensionPointName; +import com.intellij.psi.tree.IElementType; + +/** + * User: avokin + * Date: 14/03/14 + */ +public interface EmbeddedTokenTypesProvider { + ExtensionPointName EXTENSION_POINT_NAME = ExtensionPointName.create("com.intellij.embeddedTokenTypesProvider"); + + String getName(); + IElementType getElementType(); +} From 7fd26d1da0bc23377e19e9d081c2507956904d78 Mon Sep 17 00:00:00 2001 From: Roman Shevchenko Date: Fri, 21 Mar 2014 12:54:16 +0100 Subject: [PATCH 36/36] CR-IC-4877 (cleanup) --- .../platform-impl/src/com/intellij/ui/ExpansionHint.java | 7 ------- 1 file changed, 7 deletions(-) diff --git a/platform/platform-impl/src/com/intellij/ui/ExpansionHint.java b/platform/platform-impl/src/com/intellij/ui/ExpansionHint.java index edff33c28ae7..0746b54312a1 100644 --- a/platform/platform-impl/src/com/intellij/ui/ExpansionHint.java +++ b/platform/platform-impl/src/com/intellij/ui/ExpansionHint.java @@ -37,9 +37,6 @@ public class ExpansionHint implements Hint { myListeners = ContainerUtil.newSmartList(); } - /** - * Shows the hint as the window. - */ @Override public void show(@NotNull JComponent parentComponent, int x, int y, @Nullable JComponent focusBackComponent, @Nullable HintHint hh) { myPopup = JBPopupFactory.getInstance().createComponentPopupBuilder(myComponent, null) @@ -63,10 +60,6 @@ public class ExpansionHint implements Hint { return myComponent.isShowing(); } - public JComponent getComponent() { - return myComponent; - } - @Override public void hide() { if (myPopup != null) {