From af732e301997989f9d980f96c36185f71e227ee9 Mon Sep 17 00:00:00 2001 From: Eugene Zhuravlev Date: Wed, 15 Dec 2010 18:32:12 +0300 Subject: [PATCH 01/54] do not discard step request in a particular thread when stepping in another thread occurs (IDEA-63007) --- .../intellij/debugger/engine/DebugProcessEvents.java | 2 +- .../intellij/debugger/engine/DebugProcessImpl.java | 11 ++++++----- .../intellij/debugger/engine/SuspendManagerImpl.java | 3 ++- 3 files changed, 9 insertions(+), 7 deletions(-) diff --git a/java/debugger/impl/src/com/intellij/debugger/engine/DebugProcessEvents.java b/java/debugger/impl/src/com/intellij/debugger/engine/DebugProcessEvents.java index 5d12ced33651..efff8ab5787a 100644 --- a/java/debugger/impl/src/com/intellij/debugger/engine/DebugProcessEvents.java +++ b/java/debugger/impl/src/com/intellij/debugger/engine/DebugProcessEvents.java @@ -351,7 +351,7 @@ public class DebugProcessEvents extends DebugProcessImpl { //noinspection HardCodedStringLiteral RequestHint hint = (RequestHint)event.request().getProperty("hint"); - deleteStepRequests(); + deleteStepRequests(event.thread()); boolean shouldResume = false; diff --git a/java/debugger/impl/src/com/intellij/debugger/engine/DebugProcessImpl.java b/java/debugger/impl/src/com/intellij/debugger/engine/DebugProcessImpl.java index 0e907ad96f1f..c88999862fdc 100644 --- a/java/debugger/impl/src/com/intellij/debugger/engine/DebugProcessImpl.java +++ b/java/debugger/impl/src/com/intellij/debugger/engine/DebugProcessImpl.java @@ -353,12 +353,13 @@ public abstract class DebugProcessImpl implements DebugProcess { return; } try { + final ThreadReference stepThreadReference = stepThread.getThreadReference(); if (LOG.isDebugEnabled()) { - LOG.debug("DO_STEP: creating step request for " + stepThread.getThreadReference()); + LOG.debug("DO_STEP: creating step request for " + stepThreadReference); } - deleteStepRequests(); + deleteStepRequests(stepThreadReference); EventRequestManager requestManager = getVirtualMachineProxy().eventRequestManager(); - StepRequest stepRequest = requestManager.createStepRequest(stepThread.getThreadReference(), StepRequest.STEP_LINE, depth); + StepRequest stepRequest = requestManager.createStepRequest(stepThreadReference, StepRequest.STEP_LINE, depth); DebuggerSettings settings = DebuggerSettings.getInstance(); if (!(hint != null && hint.isIgnoreFilters()) /*&& depth == StepRequest.STEP_INTO*/) { final List activeFilters = new ArrayList(); @@ -404,7 +405,7 @@ public abstract class DebugProcessImpl implements DebugProcess { } } - void deleteStepRequests() { + void deleteStepRequests(@Nullable final ThreadReference stepThread) { EventRequestManager requestManager = getVirtualMachineProxy().eventRequestManager(); List stepRequests = requestManager.stepRequests(); if (stepRequests.size() > 0) { @@ -412,7 +413,7 @@ public abstract class DebugProcessImpl implements DebugProcess { for (final StepRequest request : stepRequests) { ThreadReference threadReference = request.thread(); // [jeka] on attempt to delete a request assigned to a thread with unknown status, a JDWP error occures - if (threadReference.status() != ThreadReference.THREAD_STATUS_UNKNOWN) { + if (threadReference.status() != ThreadReference.THREAD_STATUS_UNKNOWN && (stepThread == null || stepThread.equals(threadReference))) { toDelete.add(request); } } diff --git a/java/debugger/impl/src/com/intellij/debugger/engine/SuspendManagerImpl.java b/java/debugger/impl/src/com/intellij/debugger/engine/SuspendManagerImpl.java index 07bed88ea199..110d70270f5d 100644 --- a/java/debugger/impl/src/com/intellij/debugger/engine/SuspendManagerImpl.java +++ b/java/debugger/impl/src/com/intellij/debugger/engine/SuspendManagerImpl.java @@ -298,7 +298,8 @@ public class SuspendManagerImpl implements SuspendManager { } myDebugProcess.logThreads(); myDebugProcess.cancelRunToCursorBreakpoint(); - myDebugProcess.deleteStepRequests(); + final ThreadReferenceProxyImpl thread = suspendContext.getThread(); + myDebugProcess.deleteStepRequests(thread != null? thread.getThreadReference() : null); notifyPaused(suspendContext); } } From e457bfc0214e8c35d98734919db7986cce909ef7 Mon Sep 17 00:00:00 2001 From: "peter.gromov" Date: Wed, 15 Dec 2010 15:06:51 +0300 Subject: [PATCH 02/54] more info in the assertion --- .../completion/CodeCompletionHandlerBase.java | 9 ++++++++- 1 file changed, 8 insertions(+), 1 deletion(-) diff --git a/platform/lang-impl/src/com/intellij/codeInsight/completion/CodeCompletionHandlerBase.java b/platform/lang-impl/src/com/intellij/codeInsight/completion/CodeCompletionHandlerBase.java index 6ea31eb29fba..5fdad4454373 100644 --- a/platform/lang-impl/src/com/intellij/codeInsight/completion/CodeCompletionHandlerBase.java +++ b/platform/lang-impl/src/com/intellij/codeInsight/completion/CodeCompletionHandlerBase.java @@ -34,6 +34,7 @@ import com.intellij.openapi.application.ApplicationAdapter; import com.intellij.openapi.application.ApplicationManager; import com.intellij.openapi.application.Result; import com.intellij.openapi.application.ex.ApplicationEx; +import com.intellij.openapi.application.ex.ApplicationManagerEx; import com.intellij.openapi.command.CommandProcessor; import com.intellij.openapi.command.WriteCommandAction; import com.intellij.openapi.diagnostic.Logger; @@ -157,7 +158,13 @@ public class CodeCompletionHandlerBase implements CodeInsightActionHandler { EditorUtil.fillVirtualSpaceUntilCaret(editor); documentManager.commitAllDocuments(); - assert editor.getDocument().getTextLength() == psiFile.getTextLength() : "unsuccessful commit"; + if (editor.getDocument().getTextLength() != psiFile.getTextLength()) { + if (ApplicationManagerEx.getApplicationEx().isInternal()) { + throw new AssertionError("unsuccessful commit: docText=" + editor.getDocument().getText() + "; fileText=" + psiFile.getText() + "; injected=" + (editor instanceof EditorWindow)); + } + + throw new AssertionError("unsuccessful commit: injected=" + (editor instanceof EditorWindow)); + } final Ref current = Ref.create(null); initializationContext[0] = new CompletionInitializationContext(editor, psiFile, myCompletionType) { From c09bf152d64f0adbf504046d632cb595c13e0a01 Mon Sep 17 00:00:00 2001 From: "peter.gromov" Date: Wed, 15 Dec 2010 18:52:06 +0300 Subject: [PATCH 03/54] IDEA-62753 Completing method call with ';' when pair bracket autoinsertion is off --- .../completion/JavaCompletionUtil.java | 59 +++++++------------ .../completion/JavaMethodCallElement.java | 3 - .../MethodWithLeftParTailType2_after.java | 2 +- ...ConstructorNoPairBracketSemicolon-out.java | 5 ++ .../ConstructorNoPairBracketSemicolon.java | 5 ++ .../MethodNoPairBracketComma-out.java | 8 +++ .../smartType/MethodNoPairBracketComma.java | 8 +++ .../completion/SmartTypeCompletionTest.java | 20 +++---- 8 files changed, 58 insertions(+), 52 deletions(-) create mode 100644 java/java-tests/testData/codeInsight/completion/smartType/ConstructorNoPairBracketSemicolon-out.java create mode 100644 java/java-tests/testData/codeInsight/completion/smartType/ConstructorNoPairBracketSemicolon.java create mode 100644 java/java-tests/testData/codeInsight/completion/smartType/MethodNoPairBracketComma-out.java create mode 100644 java/java-tests/testData/codeInsight/completion/smartType/MethodNoPairBracketComma.java diff --git a/java/java-impl/src/com/intellij/codeInsight/completion/JavaCompletionUtil.java b/java/java-impl/src/com/intellij/codeInsight/completion/JavaCompletionUtil.java index 89a09e685c17..c1955ee5df1d 100644 --- a/java/java-impl/src/com/intellij/codeInsight/completion/JavaCompletionUtil.java +++ b/java/java-impl/src/com/intellij/codeInsight/completion/JavaCompletionUtil.java @@ -923,14 +923,21 @@ public class JavaCompletionUtil { public static void insertParentheses(final InsertionContext context, final LookupElement item, boolean overloadsMatter, boolean hasParams) { final Editor editor = context.getEditor(); - final TailType tailType = getTailType(item, context); + final char completionChar = context.getCompletionChar(); final PsiFile file = context.getFile(); + final TailType tailType = completionChar == '(' ? TailType.NONE : LookupItem.handleCompletionChar(context.getEditor(), item, completionChar); + final boolean hasTail = tailType != TailType.NONE && tailType != TailType.UNKNOWN; + final boolean smart = completionChar == Lookup.COMPLETE_STATEMENT_SELECT_CHAR; + + final boolean addCompletionChar = context.shouldAddCompletionChar(); context.setAddCompletionChar(false); - final boolean needLeftParenth = isToInsertParenth(file.findElementAt(context.getStartOffset())); - final boolean needRightParenth = tailType != TailType.SMART_COMPLETION && CodeInsightSettings.getInstance().AUTOINSERT_PAIR_BRACKET; + final boolean needRightParenth = !smart && (CodeInsightSettings.getInstance().AUTOINSERT_PAIR_BRACKET || hasTail); + if (hasTail) { + hasParams = false; + } if (needLeftParenth) { final CodeStyleSettings styleSettings = CodeStyleSettingsManager.getSettings(context.getProject()); @@ -947,42 +954,20 @@ public class JavaCompletionUtil { AutoPopupController.getInstance(file.getProject()).autoPopupParameterInfo(editor, overloadsMatter ? null : (PsiElement)item.getObject()); } - if (tailType == TailType.SEMICOLON) { - if (!needRightParenth) { - return; - } - - PsiDocumentManager.getInstance(file.getProject()).commitAllDocuments(); - if (psiElement().beforeLeaf(psiElement().withText(".")).accepts(file.findElementAt(context.getTailOffset() - 1))) { - return; + if (smart || needLeftParenth && needRightParenth && addCompletionChar) { + TailType toInsert = tailType; + LookupItem lookupItem = item.as(LookupItem.class); + if (lookupItem == null || lookupItem.getAttribute(LookupItem.TAIL_TYPE_ATTR) != TailType.UNKNOWN) { + if (!hasTail && item.getObject() instanceof PsiMethod && ((PsiMethod)item.getObject()).getReturnType() == PsiType.VOID) { + PsiDocumentManager.getInstance(file.getProject()).commitAllDocuments(); + if (psiElement().beforeLeaf(psiElement().withText(".")).accepts(file.findElementAt(context.getTailOffset() - 1))) { + return; + } + toInsert = TailType.SEMICOLON; + } } + toInsert.processTail(editor, context.getTailOffset()); } - - if (tailType == TailType.SMART_COMPLETION || needLeftParenth && needRightParenth) { - tailType.processTail(editor, context.getTailOffset()); - } - } - - @NotNull - public static TailType getTailType(final LookupElement item, InsertionContext context) { - final char completionChar = context.getCompletionChar(); - if (completionChar == '!') return item instanceof LookupItem ? ((LookupItem)item).getTailType() : TailType.NONE; - if (completionChar == '(') { - final Object o = item.getObject(); - if (o instanceof PsiMethod) { - final PsiMethod psiMethod = (PsiMethod)o; - return psiMethod.getParameterList().getParameters().length > 0 || psiMethod.getReturnType() != PsiType.VOID - ? TailType.NONE : TailType.SEMICOLON; - } else if (o instanceof PsiClass) { // it may be a constructor - return TailType.NONE; - } - } - if (completionChar == Lookup.COMPLETE_STATEMENT_SELECT_CHAR) return TailType.SMART_COMPLETION; - if (!context.shouldAddCompletionChar()) { - return TailType.NONE; - } - - return LookupItem.handleCompletionChar(context.getEditor(), item, completionChar); } public static boolean isToInsertParenth(PsiElement place){ diff --git a/java/java-impl/src/com/intellij/codeInsight/completion/JavaMethodCallElement.java b/java/java-impl/src/com/intellij/codeInsight/completion/JavaMethodCallElement.java index a6a754150700..00a0ac458506 100644 --- a/java/java-impl/src/com/intellij/codeInsight/completion/JavaMethodCallElement.java +++ b/java/java-impl/src/com/intellij/codeInsight/completion/JavaMethodCallElement.java @@ -17,7 +17,6 @@ package com.intellij.codeInsight.completion; import com.intellij.codeInsight.ExpectedTypeInfo; import com.intellij.codeInsight.ExpectedTypesProvider; -import com.intellij.codeInsight.TailType; import com.intellij.codeInsight.completion.util.MethodParenthesesHandler; import com.intellij.codeInsight.lookup.*; import com.intellij.codeInsight.lookup.impl.JavaElementLookupRenderer; @@ -57,8 +56,6 @@ public class JavaMethodCallElement extends LookupItem implements Type LOG.error(method.getName()); } myCanImportStatic = canImportStatic; - PsiType type = method.getReturnType(); - setTailType(PsiType.VOID.equals(type) ? TailType.SEMICOLON : TailType.NONE); } public PsiType getType() { diff --git a/java/java-tests/testData/codeInsight/completion/normal/MethodWithLeftParTailType2_after.java b/java/java-tests/testData/codeInsight/completion/normal/MethodWithLeftParTailType2_after.java index 82b0a037822d..b4b5c16848e6 100644 --- a/java/java-tests/testData/codeInsight/completion/normal/MethodWithLeftParTailType2_after.java +++ b/java/java-tests/testData/codeInsight/completion/normal/MethodWithLeftParTailType2_after.java @@ -3,6 +3,6 @@ class MyClass { void foo(int a) {} { - foo() + foo(); } } \ No newline at end of file diff --git a/java/java-tests/testData/codeInsight/completion/smartType/ConstructorNoPairBracketSemicolon-out.java b/java/java-tests/testData/codeInsight/completion/smartType/ConstructorNoPairBracketSemicolon-out.java new file mode 100644 index 000000000000..b1b9a92a066c --- /dev/null +++ b/java/java-tests/testData/codeInsight/completion/smartType/ConstructorNoPairBracketSemicolon-out.java @@ -0,0 +1,5 @@ +class A { + { + String c = new String(); + } +} \ No newline at end of file diff --git a/java/java-tests/testData/codeInsight/completion/smartType/ConstructorNoPairBracketSemicolon.java b/java/java-tests/testData/codeInsight/completion/smartType/ConstructorNoPairBracketSemicolon.java new file mode 100644 index 000000000000..f05c0210cb13 --- /dev/null +++ b/java/java-tests/testData/codeInsight/completion/smartType/ConstructorNoPairBracketSemicolon.java @@ -0,0 +1,5 @@ +class A { + { + String c = new Stri + } +} \ No newline at end of file diff --git a/java/java-tests/testData/codeInsight/completion/smartType/MethodNoPairBracketComma-out.java b/java/java-tests/testData/codeInsight/completion/smartType/MethodNoPairBracketComma-out.java new file mode 100644 index 000000000000..883ef9b8a8f8 --- /dev/null +++ b/java/java-tests/testData/codeInsight/completion/smartType/MethodNoPairBracketComma-out.java @@ -0,0 +1,8 @@ +class A { + void foo(String bar, int a) {} + String zoo(int b) {} + + { + foo(zoo(), ) + } +} \ No newline at end of file diff --git a/java/java-tests/testData/codeInsight/completion/smartType/MethodNoPairBracketComma.java b/java/java-tests/testData/codeInsight/completion/smartType/MethodNoPairBracketComma.java new file mode 100644 index 000000000000..ab1e7d370306 --- /dev/null +++ b/java/java-tests/testData/codeInsight/completion/smartType/MethodNoPairBracketComma.java @@ -0,0 +1,8 @@ +class A { + void foo(String bar, int a) {} + String zoo(int b) {} + + { + foo(zo) + } +} \ No newline at end of file diff --git a/java/java-tests/testSrc/com/intellij/codeInsight/completion/SmartTypeCompletionTest.java b/java/java-tests/testSrc/com/intellij/codeInsight/completion/SmartTypeCompletionTest.java index d00328d0b1b7..156c4d9f8b4f 100644 --- a/java/java-tests/testSrc/com/intellij/codeInsight/completion/SmartTypeCompletionTest.java +++ b/java/java-tests/testSrc/com/intellij/codeInsight/completion/SmartTypeCompletionTest.java @@ -477,28 +477,26 @@ public class SmartTypeCompletionTest extends LightFixtureCompletionTestCase { public void testSameNamedFieldAndLocal() throws Throwable { doTest(); } - public void testNoTailWhenNoPairBracket() throws Throwable { - doTestNoPairBracket(); - } + public void testNoTailWhenNoPairBracket() throws Throwable { doTestNoPairBracket(Lookup.NORMAL_SELECT_CHAR); } - public void testNoTailWhenNoPairBracket2() throws Throwable { - doTestNoPairBracket(); - } + public void testNoTailWhenNoPairBracket2() throws Throwable { doTestNoPairBracket(Lookup.NORMAL_SELECT_CHAR); } - private void doTestNoPairBracket() throws Exception { + private void doTestNoPairBracket(final char c) throws Exception { boolean old = CodeInsightSettings.getInstance().AUTOINSERT_PAIR_BRACKET; CodeInsightSettings.getInstance().AUTOINSERT_PAIR_BRACKET = false; try { - doTest(); + doTest(c); } finally { CodeInsightSettings.getInstance().AUTOINSERT_PAIR_BRACKET = old; } } - public void testNoConstructorTailWhenNoPairBracket() throws Throwable { - doTestNoPairBracket(); - } + public void testNoConstructorTailWhenNoPairBracket() throws Throwable { doTestNoPairBracket(Lookup.NORMAL_SELECT_CHAR); } + + public void testConstructorNoPairBracketSemicolon() throws Throwable { doTestNoPairBracket(';'); } + + public void testMethodNoPairBracketComma() throws Throwable { doTestNoPairBracket(','); } public void testAbstractClassTwice() throws Throwable { configureByTestName(); From 161781d59d349b803d0d0b4452d8d96bffdf6df1 Mon Sep 17 00:00:00 2001 From: Gregory Shrago Date: Tue, 14 Dec 2010 22:24:26 +0300 Subject: [PATCH 04/54] handle empty targets case: no "navigate to" icon & nice tooltip --- .../NavigationGutterIconBuilder.java | 22 ++++++++++++++----- 1 file changed, 16 insertions(+), 6 deletions(-) diff --git a/xml/dom-openapi/src/com/intellij/codeInsight/navigation/NavigationGutterIconBuilder.java b/xml/dom-openapi/src/com/intellij/codeInsight/navigation/NavigationGutterIconBuilder.java index 93fea8af882c..0fa0015bd239 100644 --- a/xml/dom-openapi/src/com/intellij/codeInsight/navigation/NavigationGutterIconBuilder.java +++ b/xml/dom-openapi/src/com/intellij/codeInsight/navigation/NavigationGutterIconBuilder.java @@ -162,7 +162,7 @@ public class NavigationGutterIconBuilder { renderer.getIcon(), Pass.UPDATE_OVERRIDEN_MARKERS, tooltip == null ? null : new ConstantFunction(tooltip), - renderer, + renderer.isNavigateAction()? renderer : null, renderer.getAlignment()); } @@ -185,9 +185,7 @@ public class NavigationGutterIconBuilder { } }; - if (!myLazy) { - pointers.getValue(); - } + final boolean empty = !myLazy && pointers.getValue().isEmpty(); if (myTooltipText == null && !myLazy) { final SortedSet names = new TreeSet(); @@ -212,19 +210,31 @@ public class NavigationGutterIconBuilder { myCellRenderer = new DefaultPsiElementCellRenderer(); } - return new MyNavigationGutterIconRenderer(this, myAlignment, myIcon, myTooltipText, pointers); + return new MyNavigationGutterIconRenderer(this, myAlignment, myIcon, myTooltipText, pointers, empty); } private static class MyNavigationGutterIconRenderer extends NavigationGutterIconRenderer { private final Alignment myAlignment; private final Icon myIcon; private final String myTooltipText; + private final boolean myEmpty; - public MyNavigationGutterIconRenderer(final NavigationGutterIconBuilder builder, final Alignment alignment, final Icon icon, final String tooltipText, final NotNullLazyValue> pointers) { + public MyNavigationGutterIconRenderer(final NavigationGutterIconBuilder builder, + final Alignment alignment, + final Icon icon, + final String tooltipText, + final NotNullLazyValue> pointers, + boolean empty) { super(builder.myPopupTitle, builder.myEmptyText, builder.myCellRenderer, pointers); myAlignment = alignment; myIcon = icon; myTooltipText = tooltipText; + myEmpty = empty; + } + + @Override + public boolean isNavigateAction() { + return !myEmpty; } @NotNull From ecc71ac0b70b17854f5fd28057c95b576ee71ef3 Mon Sep 17 00:00:00 2001 From: Bas Leijdekkers Date: Wed, 15 Dec 2010 17:30:26 +0100 Subject: [PATCH 05/54] IDEA-63138 ("Split into declaration and assignment" intention breaks code on for loop initialization) --- .../intention/impl/SplitDeclarationAction.java | 12 +++++++++++- 1 file changed, 11 insertions(+), 1 deletion(-) diff --git a/java/java-impl/src/com/intellij/codeInsight/intention/impl/SplitDeclarationAction.java b/java/java-impl/src/com/intellij/codeInsight/intention/impl/SplitDeclarationAction.java index 521756db08eb..da5558d9c490 100644 --- a/java/java-impl/src/com/intellij/codeInsight/intention/impl/SplitDeclarationAction.java +++ b/java/java-impl/src/com/intellij/codeInsight/intention/impl/SplitDeclarationAction.java @@ -145,8 +145,18 @@ public class SplitDeclarationAction extends PsiElementBaseIntentionAction { } } - block.getParent().addBefore(varDeclStatement, block); + final PsiElement parent = block.getParent(); decl.replace(statement); + if (!(parent instanceof PsiCodeBlock)) { + final PsiBlockStatement blockStatement = + (PsiBlockStatement)JavaPsiFacade.getElementFactory(project).createStatementFromText("{}", null); + final PsiCodeBlock codeBlock = blockStatement.getCodeBlock(); + codeBlock.add(varDeclStatement); + codeBlock.add(block); + block.replace(blockStatement); + } else { + parent.addBefore(varDeclStatement, block); + } } else { block.addAfter(statement, decl); } From 56c31d80e5529ab57fe7927250afdd035a80a8a0 Mon Sep 17 00:00:00 2001 From: Dmitry Jemerov Date: Wed, 15 Dec 2010 19:42:00 +0300 Subject: [PATCH 06/54] EA-24687 - NPE: LocalFileSystemBase.getCanonicallyCasedName --- .../openapi/vfs/impl/local/LocalFileSystemBase.java | 10 ++++++---- 1 file changed, 6 insertions(+), 4 deletions(-) diff --git a/platform/platform-impl/src/com/intellij/openapi/vfs/impl/local/LocalFileSystemBase.java b/platform/platform-impl/src/com/intellij/openapi/vfs/impl/local/LocalFileSystemBase.java index eaa418ecc099..535555f728f1 100644 --- a/platform/platform-impl/src/com/intellij/openapi/vfs/impl/local/LocalFileSystemBase.java +++ b/platform/platform-impl/src/com/intellij/openapi/vfs/impl/local/LocalFileSystemBase.java @@ -565,10 +565,12 @@ public abstract class LocalFileSystemBase extends LocalFileSystem { if (parentFile != null) { // I hope ls works fast on Unix final String[] canonicalFileNames = parentFile.list(); - for (String name : canonicalFileNames) { - // if names are equals - if (name.compareToIgnoreCase(originalFileName) == 0) { - return name; + if (canonicalFileNames != null) { + for (String name : canonicalFileNames) { + // if names are equals + if (name.compareToIgnoreCase(originalFileName) == 0) { + return name; + } } } } From 86af3298df1c4b3d3394aa6616e55574840bc932 Mon Sep 17 00:00:00 2001 From: Dmitry Jemerov Date: Wed, 15 Dec 2010 20:05:16 +0300 Subject: [PATCH 07/54] fix tests --- .../com/intellij/openapi/roots/impl/OrderEnumeratorBase.java | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/platform/lang-impl/src/com/intellij/openapi/roots/impl/OrderEnumeratorBase.java b/platform/lang-impl/src/com/intellij/openapi/roots/impl/OrderEnumeratorBase.java index c70c5a9a947f..84ebcdf91b7e 100644 --- a/platform/lang-impl/src/com/intellij/openapi/roots/impl/OrderEnumeratorBase.java +++ b/platform/lang-impl/src/com/intellij/openapi/roots/impl/OrderEnumeratorBase.java @@ -61,8 +61,8 @@ abstract class OrderEnumeratorBase extends OrderEnumerator { } myCustomHandlers.add(handler); } - if (myCustomHandlers == null) myCustomHandlers = Collections.emptyList(); } + if (myCustomHandlers == null) myCustomHandlers = Collections.emptyList(); } @Override From 07c10df4ec59bb0478e8d0cee2b698ad236f061f Mon Sep 17 00:00:00 2001 From: "peter.gromov" Date: Wed, 15 Dec 2010 19:45:44 +0300 Subject: [PATCH 08/54] EA-24745 --- .../intellij/codeInsight/editorActions/UnSelectWordHandler.java | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/platform/lang-impl/src/com/intellij/codeInsight/editorActions/UnSelectWordHandler.java b/platform/lang-impl/src/com/intellij/codeInsight/editorActions/UnSelectWordHandler.java index 7627fcaf7e49..a56ea16499ad 100644 --- a/platform/lang-impl/src/com/intellij/codeInsight/editorActions/UnSelectWordHandler.java +++ b/platform/lang-impl/src/com/intellij/codeInsight/editorActions/UnSelectWordHandler.java @@ -67,7 +67,7 @@ public class UnSelectWordHandler extends EditorActionHandler { int caretOffset = editor.getCaretModel().getOffset(); - if (caretOffset > 0 && + if (caretOffset > 0 && caretOffset < text.length() && !Character.isJavaIdentifierPart(text.charAt(caretOffset)) && Character.isJavaIdentifierPart(text.charAt(caretOffset - 1))) { caretOffset--; From 2ebb843bc32f84fcf96995af0f6c509a60919358 Mon Sep 17 00:00:00 2001 From: "peter.gromov" Date: Wed, 15 Dec 2010 20:01:19 +0300 Subject: [PATCH 09/54] fix NPE --- .../openapi/roots/impl/OrderEnumeratorBase.java | 11 ++++++----- 1 file changed, 6 insertions(+), 5 deletions(-) diff --git a/platform/lang-impl/src/com/intellij/openapi/roots/impl/OrderEnumeratorBase.java b/platform/lang-impl/src/com/intellij/openapi/roots/impl/OrderEnumeratorBase.java index 84ebcdf91b7e..579272d74eb0 100644 --- a/platform/lang-impl/src/com/intellij/openapi/roots/impl/OrderEnumeratorBase.java +++ b/platform/lang-impl/src/com/intellij/openapi/roots/impl/OrderEnumeratorBase.java @@ -48,21 +48,22 @@ abstract class OrderEnumeratorBase extends OrderEnumerator { protected boolean myRecursivelyExportedOnly; private boolean myExportedOnly; private Condition myCondition; - private List myCustomHandlers; + private final List myCustomHandlers; protected ModulesProvider myModulesProvider; private OrderRootsCache myCache; public OrderEnumeratorBase(@Nullable Module module, @NotNull Project project, @Nullable OrderRootsCache cache) { myCache = cache; + List customHandlers = null; for (OrderEnumerationHandler handler : OrderEnumerationHandler.EP_NAME.getExtensions()) { if (handler.isApplicable(project) && (module == null || handler.isApplicable(module))) { - if (myCustomHandlers == null) { - myCustomHandlers = new SmartList(); + if (customHandlers == null) { + customHandlers = new SmartList(); } - myCustomHandlers.add(handler); + customHandlers.add(handler); } } - if (myCustomHandlers == null) myCustomHandlers = Collections.emptyList(); + this.myCustomHandlers = customHandlers == null ? Collections.emptyList() : customHandlers; } @Override From a2177bcee78437655ab779e2abc94c8417fae9bb Mon Sep 17 00:00:00 2001 From: "peter.gromov" Date: Wed, 15 Dec 2010 20:06:08 +0300 Subject: [PATCH 10/54] more PSI/document/commit assertions --- .../psi/impl/PsiDocumentManagerImpl.java | 19 +++++++++++++++++++ 1 file changed, 19 insertions(+) diff --git a/platform/lang-impl/src/com/intellij/psi/impl/PsiDocumentManagerImpl.java b/platform/lang-impl/src/com/intellij/psi/impl/PsiDocumentManagerImpl.java index 6ea3c5b79d57..1e6c8a78cfe3 100644 --- a/platform/lang-impl/src/com/intellij/psi/impl/PsiDocumentManagerImpl.java +++ b/platform/lang-impl/src/com/intellij/psi/impl/PsiDocumentManagerImpl.java @@ -451,6 +451,25 @@ public class PsiDocumentManagerImpl extends PsiDocumentManager implements Projec int psiEndOffset = textBlock.getPsiEndOffset(); endOffset = psiEndOffset; lengthShift = textBlock.getTextEndOffset() - psiEndOffset; + + if (oldText != null) { + String psiPrefix = oldText.substring(0, startOffset); + String docPrefix = chars.subSequence(0, startOffset).toString(); + String psiSuffix = oldText.substring(psiEndOffset); + String docSuffix = chars.subSequence(textBlock.getTextEndOffset(), chars.length()).toString(); + if (!psiPrefix.equals(docPrefix) || !psiSuffix.equals(docSuffix)) { + String msg = "PSI/document inconsistency before reparse: "; + if (!psiPrefix.equals(docPrefix)) { + msg = msg + "psiPrefix=" + psiPrefix + "; docPrefix=" + docPrefix + ";"; + } + if (!psiSuffix.equals(docSuffix)) { + msg = msg + "psiSuffix=" + psiSuffix + "; docSuffix=" + docSuffix + ";"; + } + throw new AssertionError(msg); + } + } else if (document.getTextLength() - textBlock.getTextEndOffset() != file.getTextLength() - psiEndOffset) { + throw new AssertionError("PSI/document inconsistency before reparse: file=" + file); + } } else { startOffset = 0; From b7eee6dd7ef2c6537644a01049b99f83055c64c8 Mon Sep 17 00:00:00 2001 From: Maxim Shafirov Date: Wed, 15 Dec 2010 20:18:11 +0300 Subject: [PATCH 11/54] CIDR-224: Support for unexpandable fold regions. --- .../lang/folding/FoldingDescriptor.java | 29 +++++++++++++++++-- .../impl/UpdateFoldRegionsOperation.java | 7 +++-- .../execution/impl/ConsoleViewImpl.java | 4 +-- .../injected/editor/FoldingModelWindow.java | 6 ++-- .../injected/editor/FoldingRegionWindow.java | 5 ++++ .../intellij/openapi/editor/FoldRegion.java | 2 ++ .../openapi/editor/ex/FoldingModelEx.java | 2 +- .../openapi/editor/impl/FoldRegionImpl.java | 14 ++++++++- .../openapi/editor/impl/FoldingModelImpl.java | 8 ++--- .../src/com/intellij/mock/MockFoldRegion.java | 5 ++++ 10 files changed, 67 insertions(+), 15 deletions(-) diff --git a/platform/lang-api/src/com/intellij/lang/folding/FoldingDescriptor.java b/platform/lang-api/src/com/intellij/lang/folding/FoldingDescriptor.java index 47593ec2449f..5833f4621267 100644 --- a/platform/lang-api/src/com/intellij/lang/folding/FoldingDescriptor.java +++ b/platform/lang-api/src/com/intellij/lang/folding/FoldingDescriptor.java @@ -41,6 +41,7 @@ public class FoldingDescriptor { private final TextRange myRange; @Nullable private final FoldingGroup myGroup; private Set myDependencies; + private final boolean myNeverExpands; /** * Creates a folding region related to the specified AST node and covering the specified @@ -66,14 +67,33 @@ public class FoldingDescriptor { * Creates a folding region related to the specified AST node and covering the specified * text range. * @param node The node to which the folding region is related. The node is then passed to - * {@link FoldingBuilder#getPlaceholderText(com.intellij.lang.ASTNode)} and - * {@link FoldingBuilder#isCollapsedByDefault(com.intellij.lang.ASTNode)}. + * {@link com.intellij.lang.folding.FoldingBuilder#getPlaceholderText(com.intellij.lang.ASTNode)} and + * {@link com.intellij.lang.folding.FoldingBuilder#isCollapsedByDefault(com.intellij.lang.ASTNode)}. * @param range The folded text range. * @param group Regions with the same group instance expand and collapse together. * @param dependencies folding dependencies: other files or elements that could change * folding description */ public FoldingDescriptor(@NotNull ASTNode node, @NotNull TextRange range, @Nullable FoldingGroup group, Set dependencies) { + this(node, range, group, dependencies, false); + } + + /** + * Creates a folding region related to the specified AST node and covering the specified + * text range. + * @param node The node to which the folding region is related. The node is then passed to + * {@link com.intellij.lang.folding.FoldingBuilder#getPlaceholderText(com.intellij.lang.ASTNode)} and + * {@link com.intellij.lang.folding.FoldingBuilder#isCollapsedByDefault(com.intellij.lang.ASTNode)}. + * @param range The folded text range. + * @param group Regions with the same group instance expand and collapse together. + * @param dependencies folding dependencies: other files or elements that could change + * @param neverExpands shall be true for fold regions that must not be ever expanded. + */ + public FoldingDescriptor(@NotNull ASTNode node, + @NotNull TextRange range, + @Nullable FoldingGroup group, + Set dependencies, + boolean neverExpands) { assert range.getStartOffset() + 1 < range.getEndOffset() : range; myElement = node; ProperTextRange.assertProperRange(range); @@ -81,6 +101,7 @@ public class FoldingDescriptor { myGroup = group; assert getRange().getLength() >= 2 : "range:" + getRange(); myDependencies = dependencies; + myNeverExpands = neverExpands; } /** @@ -122,4 +143,8 @@ public class FoldingDescriptor { public Set getDependencies() { return myDependencies; } + + public boolean isNonExpandable() { + return myNeverExpands; + } } diff --git a/platform/lang-impl/src/com/intellij/codeInsight/folding/impl/UpdateFoldRegionsOperation.java b/platform/lang-impl/src/com/intellij/codeInsight/folding/impl/UpdateFoldRegionsOperation.java index dd07ca494886..6189e527742c 100644 --- a/platform/lang-impl/src/com/intellij/codeInsight/folding/impl/UpdateFoldRegionsOperation.java +++ b/platform/lang-impl/src/com/intellij/codeInsight/folding/impl/UpdateFoldRegionsOperation.java @@ -95,7 +95,10 @@ class UpdateFoldRegionsOperation implements Runnable { FoldingGroup group = descriptor.getGroup(); TextRange range = descriptor.getRange(); String placeholder = descriptor.getPlaceholderText(); - FoldRegion region = foldingModel.createFoldRegion(range.getStartOffset(), range.getEndOffset(), placeholder == null ? "..." : placeholder, group); + FoldRegion region = foldingModel.createFoldRegion(range.getStartOffset(), range.getEndOffset(), + placeholder == null ? "..." : placeholder, + group, + descriptor.isNonExpandable()); if (region == null) continue; if (!foldingModel.addFoldRegion(region)) { @@ -106,7 +109,7 @@ class UpdateFoldRegionsOperation implements Runnable { info.addRegion(region, smartPointerManager.createSmartPsiElementPointer(descriptor.getElement().getPsi())); newRegions.add(region); - boolean expandStatus = shouldExpandNewRegion(element, range, rangeToExpandStatusMap); + boolean expandStatus = !descriptor.isNonExpandable() && shouldExpandNewRegion(element, range, rangeToExpandStatusMap); if (group == null) { shouldExpand.put(region, expandStatus); } diff --git a/platform/lang-impl/src/com/intellij/execution/impl/ConsoleViewImpl.java b/platform/lang-impl/src/com/intellij/execution/impl/ConsoleViewImpl.java index 0bc22bbeea7c..00ee4db4b203 100644 --- a/platform/lang-impl/src/com/intellij/execution/impl/ConsoleViewImpl.java +++ b/platform/lang-impl/src/com/intellij/execution/impl/ConsoleViewImpl.java @@ -1185,7 +1185,7 @@ public class ConsoleViewImpl extends JPanel implements ConsoleView, ObservableCo String commandLinePlaceholder = myCommandLineFolding.getPlaceholder(line); if (commandLinePlaceholder != null) { FoldRegion region = ((FoldingModelEx)myEditor.getFoldingModel()).createFoldRegion( - document.getLineStartOffset(line), document.getLineEndOffset(line), commandLinePlaceholder, null + document.getLineStartOffset(line), document.getLineEndOffset(line), commandLinePlaceholder, null, false ); toAdd.add(region); return; @@ -1218,7 +1218,7 @@ public class ConsoleViewImpl extends JPanel implements ConsoleView, ObservableCo int oEnd = CharArrayUtil.shiftBackward(chars, document.getLineEndOffset(lEnd) - 1, " \t") + 1; FoldRegion region = - ((FoldingModelEx)myEditor.getFoldingModel()).createFoldRegion(oStart, oEnd, prevFolding.getPlaceholderText(toFold), null); + ((FoldingModelEx)myEditor.getFoldingModel()).createFoldRegion(oStart, oEnd, prevFolding.getPlaceholderText(toFold), null, false); if (region != null) { toAdd.add(region); } diff --git a/platform/lang-impl/src/com/intellij/injected/editor/FoldingModelWindow.java b/platform/lang-impl/src/com/intellij/injected/editor/FoldingModelWindow.java index 6e880586fcac..9128fbb58f92 100644 --- a/platform/lang-impl/src/com/intellij/injected/editor/FoldingModelWindow.java +++ b/platform/lang-impl/src/com/intellij/injected/editor/FoldingModelWindow.java @@ -63,7 +63,7 @@ public class FoldingModelWindow implements FoldingModelEx{ } public FoldRegion addFoldRegion(int startOffset, int endOffset, @NotNull String placeholderText) { - FoldRegion region = createFoldRegion(startOffset, endOffset, placeholderText, null); + FoldRegion region = createFoldRegion(startOffset, endOffset, placeholderText, null, false); if (region == null) return null; if (!addFoldRegion(region)) { region.dispose(); @@ -129,10 +129,10 @@ public class FoldingModelWindow implements FoldingModelEx{ } private static final Key FOLD_REGION_WINDOW = Key.create("FOLD_REGION_WINDOW"); - public FoldRegion createFoldRegion(int startOffset, int endOffset, @NotNull String placeholder, FoldingGroup group) { + public FoldRegion createFoldRegion(int startOffset, int endOffset, @NotNull String placeholder, FoldingGroup group, boolean neverExpands) { TextRange hostRange = myDocumentWindow.injectedToHost(new TextRange(startOffset, endOffset)); if (hostRange.getLength() < 2) return null; - FoldRegion hostRegion = myDelegate.createFoldRegion(hostRange.getStartOffset(), hostRange.getEndOffset(), placeholder, group); + FoldRegion hostRegion = myDelegate.createFoldRegion(hostRange.getStartOffset(), hostRange.getEndOffset(), placeholder, group, false); FoldingRegionWindow window = new FoldingRegionWindow(myDocumentWindow, myEditorWindow, (FoldRegionImpl)hostRegion); hostRegion.putUserData(FOLD_REGION_WINDOW, window); return window; diff --git a/platform/lang-impl/src/com/intellij/injected/editor/FoldingRegionWindow.java b/platform/lang-impl/src/com/intellij/injected/editor/FoldingRegionWindow.java index adf45f9ec76b..41c6994b95fe 100644 --- a/platform/lang-impl/src/com/intellij/injected/editor/FoldingRegionWindow.java +++ b/platform/lang-impl/src/com/intellij/injected/editor/FoldingRegionWindow.java @@ -56,6 +56,11 @@ public class FoldingRegionWindow extends RangeMarkerWindow implements FoldRegion return myHostRegion.getGroup(); } + @Override + public boolean shouldNeverExpand() { + return false; + } + public FoldRegionImpl getDelegate() { return myHostRegion; } diff --git a/platform/platform-api/src/com/intellij/openapi/editor/FoldRegion.java b/platform/platform-api/src/com/intellij/openapi/editor/FoldRegion.java index 13bd2e1941fd..819e87c84639 100644 --- a/platform/platform-api/src/com/intellij/openapi/editor/FoldRegion.java +++ b/platform/platform-api/src/com/intellij/openapi/editor/FoldRegion.java @@ -53,4 +53,6 @@ public interface FoldRegion extends RangeMarker { @Nullable FoldingGroup getGroup(); + + boolean shouldNeverExpand(); } diff --git a/platform/platform-impl/src/com/intellij/openapi/editor/ex/FoldingModelEx.java b/platform/platform-impl/src/com/intellij/openapi/editor/ex/FoldingModelEx.java index 82a35ca5b52d..efdeae2a7a2c 100644 --- a/platform/platform-impl/src/com/intellij/openapi/editor/ex/FoldingModelEx.java +++ b/platform/platform-impl/src/com/intellij/openapi/editor/ex/FoldingModelEx.java @@ -44,7 +44,7 @@ public interface FoldingModelEx extends FoldingModel { FoldRegion[] fetchTopLevel(); @Nullable - FoldRegion createFoldRegion(int startOffset, int endOffset, @NotNull String placeholder, FoldingGroup group); + FoldRegion createFoldRegion(int startOffset, int endOffset, @NotNull String placeholder, FoldingGroup group, boolean neverExpands); boolean addListener(@NotNull FoldingListener listener); diff --git a/platform/platform-impl/src/com/intellij/openapi/editor/impl/FoldRegionImpl.java b/platform/platform-impl/src/com/intellij/openapi/editor/impl/FoldRegionImpl.java index 94a6b9b2c6c8..903ce99efcc1 100644 --- a/platform/platform-impl/src/com/intellij/openapi/editor/impl/FoldRegionImpl.java +++ b/platform/platform-impl/src/com/intellij/openapi/editor/impl/FoldRegionImpl.java @@ -36,10 +36,17 @@ public class FoldRegionImpl extends RangeMarkerImpl implements FoldRegion { private final Editor myEditor; private final String myPlaceholderText; private final FoldingGroup myGroup; + private final boolean myShouldNeverExpand; - FoldRegionImpl(@NotNull Editor editor, int startOffset, int endOffset, @NotNull String placeholder, FoldingGroup group) { + FoldRegionImpl(@NotNull Editor editor, + int startOffset, + int endOffset, + @NotNull String placeholder, + FoldingGroup group, + boolean shouldNeverExpand) { super((DocumentEx)editor.getDocument(), startOffset, endOffset); myGroup = group; + myShouldNeverExpand = shouldNeverExpand; myIsExpanded = true; myEditor = editor; myPlaceholderText = placeholder; @@ -91,6 +98,11 @@ public class FoldRegionImpl extends RangeMarkerImpl implements FoldRegion { return myGroup; } + @Override + public boolean shouldNeverExpand() { + return myShouldNeverExpand; + } + public String toString() { return "FoldRegion " + (isExpanded() ? "-" : "+") + "(" + getStartOffset() + ":" + getEndOffset() + ")" + (isValid() ? "" : "(invalid)"); diff --git a/platform/platform-impl/src/com/intellij/openapi/editor/impl/FoldingModelImpl.java b/platform/platform-impl/src/com/intellij/openapi/editor/impl/FoldingModelImpl.java index 2053ec7846fb..e2921401f901 100644 --- a/platform/platform-impl/src/com/intellij/openapi/editor/impl/FoldingModelImpl.java +++ b/platform/platform-impl/src/com/intellij/openapi/editor/impl/FoldingModelImpl.java @@ -142,7 +142,7 @@ public class FoldingModelImpl implements FoldingModelEx, PrioritizedDocumentList } public FoldRegion addFoldRegion(int startOffset, int endOffset, @NotNull String placeholderText) { - FoldRegion region = createFoldRegion(startOffset, endOffset, placeholderText, null); + FoldRegion region = createFoldRegion(startOffset, endOffset, placeholderText, null, false); if (region == null) return null; if (!addFoldRegion(region)) { region.dispose(); @@ -267,7 +267,7 @@ public class FoldingModelImpl implements FoldingModelEx, PrioritizedDocumentList public void expandFoldRegion(FoldRegion region) { assertIsDispatchThread(); - if (region.isExpanded()) return; + if (region.isExpanded() || region.shouldNeverExpand()) return; if (!myIsBatchFoldingProcessing) { LOG.error("Fold regions must be collapsed or expanded inside batchFoldProcessing() only."); @@ -456,8 +456,8 @@ public class FoldingModelImpl implements FoldingModelEx, PrioritizedDocumentList return EditorDocumentPriorities.FOLD_MODEL; } - public FoldRegion createFoldRegion(int startOffset, int endOffset, @NotNull String placeholder, FoldingGroup group) { - FoldRegionImpl region = new FoldRegionImpl(myEditor, startOffset, endOffset, placeholder, group); + public FoldRegion createFoldRegion(int startOffset, int endOffset, @NotNull String placeholder, FoldingGroup group, boolean neverExpands) { + FoldRegionImpl region = new FoldRegionImpl(myEditor, startOffset, endOffset, placeholder, group, neverExpands); region.registerInDocument(); LOG.assertTrue(region.isValid()); return region; diff --git a/platform/testFramework/src/com/intellij/mock/MockFoldRegion.java b/platform/testFramework/src/com/intellij/mock/MockFoldRegion.java index 51b2e051ea5a..2c9c77c11cc3 100644 --- a/platform/testFramework/src/com/intellij/mock/MockFoldRegion.java +++ b/platform/testFramework/src/com/intellij/mock/MockFoldRegion.java @@ -67,6 +67,11 @@ public class MockFoldRegion extends UserDataHolderBase implements FoldRegion { throw new UnsupportedOperationException("FoldRegion.getGroup() is not implemented yet at " + getClass()); } + @Override + public boolean shouldNeverExpand() { + return false; + } + @NotNull @Override public Document getDocument() { From cc2653da20907c44a70ca28db7b488bbbe4abddb Mon Sep 17 00:00:00 2001 From: "peter.gromov" Date: Wed, 15 Dec 2010 20:16:13 +0300 Subject: [PATCH 12/54] more diagnostics for tailOffset<0 --- .../codeInsight/completion/AllClassesGetter.java | 1 + .../completion/JavaClassNameInsertHandler.java | 12 ++++++++++++ 2 files changed, 13 insertions(+) diff --git a/java/java-impl/src/com/intellij/codeInsight/completion/AllClassesGetter.java b/java/java-impl/src/com/intellij/codeInsight/completion/AllClassesGetter.java index 91d283bba58d..1f7c36f5a010 100644 --- a/java/java-impl/src/com/intellij/codeInsight/completion/AllClassesGetter.java +++ b/java/java-impl/src/com/intellij/codeInsight/completion/AllClassesGetter.java @@ -132,6 +132,7 @@ public class AllClassesGetter { start--; } context.getDocument().replaceString(start + 1, context.getTailOffset(), qName); + LOG.assertTrue(context.getTailOffset() >= 0); } } }; diff --git a/java/java-impl/src/com/intellij/codeInsight/completion/JavaClassNameInsertHandler.java b/java/java-impl/src/com/intellij/codeInsight/completion/JavaClassNameInsertHandler.java index 1ad49a9ddbdf..1e4e1a6bb2fb 100644 --- a/java/java-impl/src/com/intellij/codeInsight/completion/JavaClassNameInsertHandler.java +++ b/java/java-impl/src/com/intellij/codeInsight/completion/JavaClassNameInsertHandler.java @@ -19,6 +19,7 @@ import com.intellij.codeInsight.AutoPopupController; import com.intellij.codeInsight.ExpectedTypeInfo; import com.intellij.codeInsight.ExpectedTypesProvider; import com.intellij.codeInsight.lookup.LookupElement; +import com.intellij.openapi.application.ex.ApplicationManagerEx; import com.intellij.openapi.diagnostic.Logger; import com.intellij.openapi.editor.Document; import com.intellij.openapi.editor.Editor; @@ -94,7 +95,18 @@ class JavaClassNameInsertHandler implements InsertHandler= 0); + String docText = context.getDocument().getText(); DefaultInsertHandler.addImportForItem(context.getFile(), context.getStartOffset(), item); + if (context.getTailOffset() < 0) { + if (ApplicationManagerEx.getApplicationEx().isInternal()) { + LOG.error("Tail offset degraded: " + context.getStartOffset() + "; " + docText); + } else { + LOG.error("Tail offset degraded after insertion"); + } + } + if (annotation) { // Check if someone inserts annotation class that require @ From 1227fba52368ea45f89a1602d71aa42c4f1cc1df Mon Sep 17 00:00:00 2001 From: "peter.gromov" Date: Wed, 15 Dec 2010 20:36:42 +0300 Subject: [PATCH 13/54] a more telling LookupElementBuilder toString() (useful for tailOffset<0 diagnostics) --- .../intellij/codeInsight/lookup/LookupElementBuilder.java | 5 +++++ 1 file changed, 5 insertions(+) diff --git a/platform/lang-api/src/com/intellij/codeInsight/lookup/LookupElementBuilder.java b/platform/lang-api/src/com/intellij/codeInsight/lookup/LookupElementBuilder.java index f49c58ced67c..c67700f607a4 100644 --- a/platform/lang-api/src/com/intellij/codeInsight/lookup/LookupElementBuilder.java +++ b/platform/lang-api/src/com/intellij/codeInsight/lookup/LookupElementBuilder.java @@ -235,6 +235,11 @@ public class LookupElementBuilder extends LookupElement { return true; } + @Override + public String toString() { + return "LookupElementBuilder: handler=" + myInsertHandler; + } + @Override public int hashCode() { int result = 0; From c95ef12074b26d10fc92e6b98f2e843fe2369814 Mon Sep 17 00:00:00 2001 From: Dmitry Jemerov Date: Wed, 15 Dec 2010 20:10:38 +0300 Subject: [PATCH 14/54] EA-24523 - NPE: UIDesignerToolWindowManager.updateComponentTree --- .../propertyInspector/UIDesignerToolWindowManager.java | 5 ++++- 1 file changed, 4 insertions(+), 1 deletion(-) diff --git a/plugins/ui-designer/src/com/intellij/uiDesigner/propertyInspector/UIDesignerToolWindowManager.java b/plugins/ui-designer/src/com/intellij/uiDesigner/propertyInspector/UIDesignerToolWindowManager.java index d48c3bb39441..e5176107d6bf 100644 --- a/plugins/ui-designer/src/com/intellij/uiDesigner/propertyInspector/UIDesignerToolWindowManager.java +++ b/plugins/ui-designer/src/com/intellij/uiDesigner/propertyInspector/UIDesignerToolWindowManager.java @@ -203,7 +203,10 @@ public class UIDesignerToolWindowManager implements ProjectComponent { } public void updateComponentTree() { - myComponentTreeBuilder.updateFromRoot(); + final ComponentTreeBuilder builder = myComponentTreeBuilder; + if (builder != null) { + builder.queueUpdate(); + } } public void addComponentSelectionListener(TreeSelectionListener treeSelectionListener) { From 8e18cdc09710cef4cb8b4de5e7bd0c250acc27e2 Mon Sep 17 00:00:00 2001 From: Dmitry Jemerov Date: Wed, 15 Dec 2010 20:13:32 +0300 Subject: [PATCH 15/54] EA-24515 - NPE: GuiDesignerConfigurable.isModified --- .../src/com/intellij/uiDesigner/GuiDesignerConfigurable.java | 4 ++++ 1 file changed, 4 insertions(+) diff --git a/plugins/ui-designer/src/com/intellij/uiDesigner/GuiDesignerConfigurable.java b/plugins/ui-designer/src/com/intellij/uiDesigner/GuiDesignerConfigurable.java index 17d3eb4dc3e4..4a21256dfc9c 100644 --- a/plugins/ui-designer/src/com/intellij/uiDesigner/GuiDesignerConfigurable.java +++ b/plugins/ui-designer/src/com/intellij/uiDesigner/GuiDesignerConfigurable.java @@ -80,6 +80,10 @@ public final class GuiDesignerConfigurable implements SearchableConfigurable { public boolean isModified() { final GuiDesignerConfiguration configuration = GuiDesignerConfiguration.getInstance(myProject); + if (myGeneralUI == null) { + return false; + } + if (myGeneralUI.myChkCopyFormsRuntime.isSelected() != configuration.COPY_FORMS_RUNTIME_TO_OUTPUT) { return true; } From a26d9551717d9df692cd69c618cc23a5454157d5 Mon Sep 17 00:00:00 2001 From: Dmitry Jemerov Date: Wed, 15 Dec 2010 20:26:36 +0300 Subject: [PATCH 16/54] EA-23870 - IE: UpdateChecker$2.run --- .../com/intellij/openapi/updateSettings/impl/UpdateChecker.java | 2 ++ 1 file changed, 2 insertions(+) diff --git a/platform/platform-impl/src/com/intellij/openapi/updateSettings/impl/UpdateChecker.java b/platform/platform-impl/src/com/intellij/openapi/updateSettings/impl/UpdateChecker.java index 5087a4875bbe..96dd3cfe0ad3 100644 --- a/platform/platform-impl/src/com/intellij/openapi/updateSettings/impl/UpdateChecker.java +++ b/platform/platform-impl/src/com/intellij/openapi/updateSettings/impl/UpdateChecker.java @@ -354,6 +354,8 @@ public final class UpdateChecker { } catch (Exception ignored) { } + catch (InternalError ignored) { + } propertiesComponent.setValue(INSTALLATION_UID, uid); } else { From 521e0766ebd39773ef5a87ae127df60b17aa1ed7 Mon Sep 17 00:00:00 2001 From: Dmitry Jemerov Date: Wed, 15 Dec 2010 20:29:41 +0300 Subject: [PATCH 17/54] EA-24531 - IDDOE: PsiCopyPasteManager.getElements --- .../src/com/intellij/ide/PsiCopyPasteManager.java | 10 ++++++++-- 1 file changed, 8 insertions(+), 2 deletions(-) diff --git a/platform/lang-impl/src/com/intellij/ide/PsiCopyPasteManager.java b/platform/lang-impl/src/com/intellij/ide/PsiCopyPasteManager.java index a0a56ba13ab2..55a430574e62 100644 --- a/platform/lang-impl/src/com/intellij/ide/PsiCopyPasteManager.java +++ b/platform/lang-impl/src/com/intellij/ide/PsiCopyPasteManager.java @@ -32,6 +32,7 @@ import java.awt.datatransfer.DataFlavor; import java.awt.datatransfer.StringSelection; import java.awt.datatransfer.Transferable; import java.awt.datatransfer.UnsupportedFlavorException; +import java.awt.dnd.InvalidDnDOperationException; import java.io.File; import java.io.IOException; import java.util.ArrayList; @@ -89,9 +90,14 @@ public class PsiCopyPasteManager { Object transferData; try { transferData = content.getTransferData(ourDataFlavor); - } catch (UnsupportedFlavorException e) { + } + catch (UnsupportedFlavorException e) { return null; - } catch (IOException e) { + } + catch (IOException e) { + return null; + } + catch (InvalidDnDOperationException e) { return null; } From ae63307d9bfe7d4e8bd4c09f3edfe981e162bece Mon Sep 17 00:00:00 2001 From: Dmitry Jemerov Date: Wed, 15 Dec 2010 20:49:58 +0300 Subject: [PATCH 18/54] move initial configuration dialog to platform --- .../options/InitialConfigurationDialog.form | 70 +++++++ .../options/InitialConfigurationDialog.java | 172 ++++++++++++++++++ 2 files changed, 242 insertions(+) create mode 100644 platform/lang-impl/src/com/intellij/application/options/InitialConfigurationDialog.form create mode 100644 platform/lang-impl/src/com/intellij/application/options/InitialConfigurationDialog.java diff --git a/platform/lang-impl/src/com/intellij/application/options/InitialConfigurationDialog.form b/platform/lang-impl/src/com/intellij/application/options/InitialConfigurationDialog.form new file mode 100644 index 000000000000..55892db1d279 --- /dev/null +++ b/platform/lang-impl/src/com/intellij/application/options/InitialConfigurationDialog.form @@ -0,0 +1,70 @@ + +
+ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +
diff --git a/platform/lang-impl/src/com/intellij/application/options/InitialConfigurationDialog.java b/platform/lang-impl/src/com/intellij/application/options/InitialConfigurationDialog.java new file mode 100644 index 000000000000..5b4122ff63c1 --- /dev/null +++ b/platform/lang-impl/src/com/intellij/application/options/InitialConfigurationDialog.java @@ -0,0 +1,172 @@ +package com.intellij.application.options; + +import com.intellij.application.options.colors.ColorAndFontOptions; +import com.intellij.application.options.colors.NewColorAndFontPanel; +import com.intellij.application.options.colors.SimpleEditorPreview; +import com.intellij.ide.todo.TodoConfiguration; +import com.intellij.ide.ui.ListCellRendererWrapper; +import com.intellij.openapi.application.ApplicationNamesInfo; +import com.intellij.openapi.editor.colors.EditorColorsManager; +import com.intellij.openapi.editor.colors.EditorColorsScheme; +import com.intellij.openapi.keymap.Keymap; +import com.intellij.openapi.keymap.KeymapManager; +import com.intellij.openapi.keymap.impl.KeymapManagerImpl; +import com.intellij.openapi.ui.DialogWrapper; +import com.intellij.openapi.util.SystemInfo; + +import javax.swing.*; +import java.awt.*; +import java.awt.event.ActionEvent; +import java.awt.event.ActionListener; +import java.util.ArrayList; + +/** + * @author yole + */ +public class InitialConfigurationDialog extends DialogWrapper { + private JPanel myMainPanel; + private JComboBox myKeymapComboBox; + private JComboBox myColorSchemeComboBox; + private JButton myPreviewButton; + private String myColorSettingsPage; + + public InitialConfigurationDialog(Component parent, String colorSettingsPage) { + super(parent, true); + myColorSettingsPage = colorSettingsPage; + setTitle(ApplicationNamesInfo.getInstance().getFullProductName() + " Initial Configuration"); + + final ArrayList keymaps = new ArrayList(); + for (Keymap keymap : ((KeymapManagerImpl)KeymapManager.getInstance()).getAllKeymaps()) { + if (matchesPlatform(keymap)) { + keymaps.add(keymap); + } + } + + myKeymapComboBox.setModel(new DefaultComboBoxModel(keymaps.toArray(new Keymap[keymaps.size()]))); + myKeymapComboBox.setRenderer(new ListCellRendererWrapper(myKeymapComboBox.getRenderer()) { + @Override + public void customize(final JList list, final Object value, final int index, final boolean selected, final boolean cellHasFocus) { + Keymap keymap = (Keymap)value; + if (keymap == null) { + return; + } + if (KeymapManager.DEFAULT_IDEA_KEYMAP.equals(keymap.getName())) { + setText("IntelliJ IDEA Classic"); + } + else if ("Mac OS X".equals(keymap.getName())) { + setText("IntelliJ IDEA Classic - Mac OS X"); + } + else { + setText(keymap.getPresentableName()); + } + } + + }); + preselectKeyMap(keymaps); + + final EditorColorsScheme[] colorSchemes = EditorColorsManager.getInstance().getAllSchemes(); + myColorSchemeComboBox.setModel(new DefaultComboBoxModel(colorSchemes)); + myColorSchemeComboBox.setRenderer(new ListCellRendererWrapper(myColorSchemeComboBox.getRenderer()) { + @Override + public void customize(JList list, Object value, int index, boolean selected, boolean cellHasFocus) { + setText(((EditorColorsScheme)value).getName()); + } + + }); + + init(); + myPreviewButton.addActionListener(new ActionListener() { + public void actionPerformed(final ActionEvent e) { + showColorSchemePreviewDialog(); + } + }); + } + + private void preselectKeyMap(ArrayList keymaps) { + if (SystemInfo.isMac) { + for (Keymap keymap : keymaps) { + if (keymap.getName().equals("Default for Mac OS X")) { + myKeymapComboBox.setSelectedItem(keymap); + break; + } + } + } + } + + private static boolean matchesPlatform(Keymap keymap) { + if (keymap.getName().equals(KeymapManager.DEFAULT_IDEA_KEYMAP)) { + return !SystemInfo.isMac; + } + else if (keymap.getName().equals(KeymapManager.MAC_OS_X_KEYMAP)) { + return SystemInfo.isMac; + } + else if (keymap.getName().equals("Default for GNOME") || keymap.getName().equals("Default for KDE") || + keymap.getName().equals("Default for XWin")) { + return SystemInfo.isLinux; + } + return true; + } + + private void showColorSchemePreviewDialog() { + showColorSchemePreviewDialog(ColorAndFontOptions.getColorAndFontsInstance()); + } + + private void showColorSchemePreviewDialog(final ColorAndFontOptions options) { + final NewColorAndFontPanel page = options.findPage(myColorSettingsPage); + assert page != null; + options.reset(); + final String selectedScheme = ((EditorColorsScheme)myColorSchemeComboBox.getSelectedItem()).getName(); + options.selectScheme(selectedScheme); + final SimpleEditorPreview preview = new SimpleEditorPreview(options, page.getSettingsPage()); + preview.updateView(); + DialogWrapper wrapper = new PreviewDialog(preview, selectedScheme); + wrapper.show(); + preview.disposeUIResources(); + options.disposeUIResources(); + } + + protected JComponent createCenterPanel() { + return myMainPanel; + } + + @Override + protected void doOKAction() { + super.doOKAction(); + // set keymap + ((KeymapManagerImpl)KeymapManager.getInstance()).setActiveKeymap((Keymap)myKeymapComboBox.getSelectedItem()); + // set color scheme + EditorColorsManager.getInstance().setGlobalScheme((EditorColorsScheme)myColorSchemeComboBox.getSelectedItem()); + // create default todo_pattern for color scheme + TodoConfiguration.getInstance().resetToDefaultTodoPatterns(); + } + + private class PreviewDialog extends DialogWrapper { + private final SimpleEditorPreview myPreview; + + public PreviewDialog(final SimpleEditorPreview preview, final String selectedScheme) { + super(myMainPanel, true); + myPreview = preview; + setTitle("Preview for " + selectedScheme); + init(); + } + + @Override + protected JComponent createCenterPanel() { + JPanel panel = new JPanel(new BorderLayout()) { + @Override + public Dimension getPreferredSize() { + return new Dimension(400, 300); + } + }; + panel.add(myPreview.getPanel(), BorderLayout.CENTER); + return panel; + } + + @Override + protected Action[] createActions() { + final Action action = getOKAction(); + action.putValue(Action.NAME, "Close"); + return new Action[]{action}; + } + } +} From c33d36737f0d63151a1d9500706df63f77ec9e40 Mon Sep 17 00:00:00 2001 From: "sergey.vasiliev" Date: Fri, 10 Dec 2010 15:26:14 +0300 Subject: [PATCH 19/54] IDEA-57790 --- java/java-impl/src/com/intellij/util/xml/PsiClassConverter.java | 2 +- java/openapi/src/com/intellij/util/xml/DomJavaUtil.java | 2 +- 2 files changed, 2 insertions(+), 2 deletions(-) diff --git a/java/java-impl/src/com/intellij/util/xml/PsiClassConverter.java b/java/java-impl/src/com/intellij/util/xml/PsiClassConverter.java index df16f85a8abd..32785e7a44c3 100644 --- a/java/java-impl/src/com/intellij/util/xml/PsiClassConverter.java +++ b/java/java-impl/src/com/intellij/util/xml/PsiClassConverter.java @@ -97,7 +97,7 @@ public class PsiClassConverter extends Converter implements CustomRefe @Nullable protected GlobalSearchScope getScope(final GenericDomValue domValue) { final Module module = domValue.getModule(); - return module == null ? null : GlobalSearchScope.moduleWithDependenciesAndLibrariesScope(module); + return module == null ? null : GlobalSearchScope.moduleWithDependenciesAndLibrariesScope(module, false); } public static class AnnotationType extends PsiClassConverter { diff --git a/java/openapi/src/com/intellij/util/xml/DomJavaUtil.java b/java/openapi/src/com/intellij/util/xml/DomJavaUtil.java index 47171693c07d..c21fd2278d4f 100644 --- a/java/openapi/src/com/intellij/util/xml/DomJavaUtil.java +++ b/java/openapi/src/com/intellij/util/xml/DomJavaUtil.java @@ -41,7 +41,7 @@ public class DomJavaUtil { if (searchScope == null) { if (module != null) { - scope = GlobalSearchScope.moduleWithDependenciesAndLibrariesScope(module); + scope = GlobalSearchScope.moduleWithDependenciesAndLibrariesScope(module, false); } else { scope = file.getResolveScope(); From 36521637d87d4310b0a6663647309e41ae706ca6 Mon Sep 17 00:00:00 2001 From: "sergey.vasiliev" Date: Tue, 14 Dec 2010 14:47:56 +0300 Subject: [PATCH 20/54] statistics for plugins and vcs --- .../ide/plugins/PluginsUsagesCollector.java | 45 ++++++ .../src/META-INF/PlatformExtensions.xml | 1 + .../statistics/VcsStatisticsPersistence.java | 42 +++++ .../VcsStatisticsPersistenceComponent.java | 147 ++++++++++++++++++ .../vcs/statistics/VcsUsagesCollector.java | 98 ++++++++++++ 5 files changed, 333 insertions(+) create mode 100644 platform/platform-impl/src/com/intellij/ide/plugins/PluginsUsagesCollector.java create mode 100644 platform/vcs-impl/src/com/intellij/openapi/vcs/statistics/VcsStatisticsPersistence.java create mode 100644 platform/vcs-impl/src/com/intellij/openapi/vcs/statistics/VcsStatisticsPersistenceComponent.java create mode 100644 platform/vcs-impl/src/com/intellij/openapi/vcs/statistics/VcsUsagesCollector.java diff --git a/platform/platform-impl/src/com/intellij/ide/plugins/PluginsUsagesCollector.java b/platform/platform-impl/src/com/intellij/ide/plugins/PluginsUsagesCollector.java new file mode 100644 index 000000000000..560fac29c488 --- /dev/null +++ b/platform/platform-impl/src/com/intellij/ide/plugins/PluginsUsagesCollector.java @@ -0,0 +1,45 @@ +/* + * Copyright 2000-2010 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.ide.plugins; + +import com.intellij.openapi.project.Project; +import com.intellij.statistic.UsagesCollector; +import com.intellij.statistic.beans.GroupDescriptor; +import com.intellij.statistic.beans.UsageDescriptor; +import com.intellij.util.Function; +import com.intellij.util.containers.ContainerUtil; +import org.jetbrains.annotations.NotNull; +import org.jetbrains.annotations.Nullable; + +import java.util.Set; + +public class PluginsUsagesCollector extends UsagesCollector { + private static final String GROUP_ID = "plugins"; + + public static GroupDescriptor getGroupId() { + return GroupDescriptor.create(GROUP_ID, GroupDescriptor.HIGHER_PRIORITY); + } + + @NotNull + public Set getUsages(@Nullable Project project) { + return ContainerUtil.map2Set(PluginManager.getPlugins(), new Function() { + @Override + public UsageDescriptor fun(IdeaPluginDescriptor descriptor) { + return new UsageDescriptor(getGroupId(), descriptor.getName(), 1); + } + }); + } +} diff --git a/platform/platform-resources/src/META-INF/PlatformExtensions.xml b/platform/platform-resources/src/META-INF/PlatformExtensions.xml index 799d7cb0a1cc..caa86f0b81a0 100644 --- a/platform/platform-resources/src/META-INF/PlatformExtensions.xml +++ b/platform/platform-resources/src/META-INF/PlatformExtensions.xml @@ -204,5 +204,6 @@ + diff --git a/platform/vcs-impl/src/com/intellij/openapi/vcs/statistics/VcsStatisticsPersistence.java b/platform/vcs-impl/src/com/intellij/openapi/vcs/statistics/VcsStatisticsPersistence.java new file mode 100644 index 000000000000..0850d38c3749 --- /dev/null +++ b/platform/vcs-impl/src/com/intellij/openapi/vcs/statistics/VcsStatisticsPersistence.java @@ -0,0 +1,42 @@ +/* + * Copyright 2000-2010 JetBrains s.r.o. + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +package com.intellij.openapi.vcs.statistics; + +import com.intellij.openapi.project.Project; +import com.intellij.statistic.beans.UsageDescriptor; +import com.intellij.util.containers.HashMap; +import org.jetbrains.annotations.NotNull; + +import java.util.Map; +import java.util.Set; + +public abstract class VcsStatisticsPersistence { + private Map> myVcsUsagesMap = new HashMap>(); + + public VcsStatisticsPersistence() { + } + + public void persist(@NotNull Project project, @NotNull Set vcs) { + myVcsUsagesMap.put(project.getName(), vcs); + } + + @NotNull + public Map> getVcsUsageMap() { + return myVcsUsagesMap; + } + +} diff --git a/platform/vcs-impl/src/com/intellij/openapi/vcs/statistics/VcsStatisticsPersistenceComponent.java b/platform/vcs-impl/src/com/intellij/openapi/vcs/statistics/VcsStatisticsPersistenceComponent.java new file mode 100644 index 000000000000..3cff5584312c --- /dev/null +++ b/platform/vcs-impl/src/com/intellij/openapi/vcs/statistics/VcsStatisticsPersistenceComponent.java @@ -0,0 +1,147 @@ +/* + * Copyright 2000-2010 JetBrains s.r.o. + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +package com.intellij.openapi.vcs.statistics; + +import com.intellij.openapi.application.ApplicationManager; +import com.intellij.openapi.application.PathManager; +import com.intellij.openapi.components.ApplicationComponent; +import com.intellij.openapi.components.PersistentStateComponent; +import com.intellij.openapi.components.State; +import com.intellij.openapi.components.Storage; +import com.intellij.openapi.project.Project; +import com.intellij.openapi.project.ProjectManager; +import com.intellij.openapi.project.ProjectManagerListener; +import com.intellij.openapi.util.text.StringUtil; +import com.intellij.statistic.beans.UsageDescriptor; +import com.intellij.util.Function; +import com.intellij.util.containers.HashSet; +import org.jdom.Element; +import org.jetbrains.annotations.NonNls; +import org.jetbrains.annotations.NotNull; + +import java.io.File; +import java.util.List; +import java.util.Map; +import java.util.Set; + +@State( + name = "VcsUsages", + storages = { + @Storage( + id = "vcs", + file = "$APP_CONFIG$/vcs.usages.xml" + )} +) +//todo !!! register this ApplicationComponent !!!! +public class VcsStatisticsPersistenceComponent extends VcsStatisticsPersistence + implements ApplicationComponent, PersistentStateComponent { + private static final String TOKENIZER = ","; + + @NonNls private static final String PROJECT_TAG = "project"; + @NonNls private static final String PROJECT_ID_ATTR = "id"; + @NonNls private static final String USAGES_ATTR = "usages"; + + public VcsStatisticsPersistenceComponent() { + } + + public static VcsStatisticsPersistenceComponent getInstance() { + return ApplicationManager.getApplication().getComponent(VcsStatisticsPersistenceComponent.class); + } + + public void loadState(final Element element) { + List projectsList = element.getChildren(PROJECT_TAG); + for (Object project : projectsList) { + Element projectElement = (Element)project; + String projectId = projectElement.getAttributeValue(PROJECT_ID_ATTR); + String vcs = projectElement.getAttributeValue(USAGES_ATTR); + if (!StringUtil.isEmptyOrSpaces(projectId) && !StringUtil.isEmptyOrSpaces(vcs)) { + Set vcsDescriptors = new HashSet(); + for (String key : StringUtil.split(vcs, TOKENIZER)) { + vcsDescriptors.add(new UsageDescriptor(VcsUsagesCollector.getGroupId(), key, 1)); + } + getVcsUsageMap().put(projectId, vcsDescriptors); + } + } + } + + public Element getState() { + Element element = new Element("state"); + + for (Map.Entry> vcsUsageEntry : getVcsUsageMap().entrySet()) { + Element projectElement = new Element(PROJECT_TAG); + projectElement.setAttribute(PROJECT_ID_ATTR, vcsUsageEntry.getKey()); + projectElement.setAttribute(USAGES_ATTR, joinUsages(vcsUsageEntry.getValue())); + + element.addContent(projectElement); + } + + return element; + } + + private static String joinUsages(@NotNull Set usages) { + return StringUtil.join(usages, new Function() { + @Override + public String fun(UsageDescriptor usageDescriptor) { + return usageDescriptor.getKey(); + } + }, TOKENIZER); + } + + @NotNull + @NonNls + public File[] getExportFiles() { + return new File[]{PathManager.getOptionsFile("vcs.usages")}; + } + + @NotNull + public String getPresentableName() { + return "Vcs Usages"; + } + + @NonNls + @NotNull + public String getComponentName() { + return "VcsStatisticsPersistenceComponent"; + } + + public void initComponent() { + ProjectManager.getInstance().addProjectManagerListener(new ProjectManagerListener() { + @Override + public void projectOpened(Project project) { + } + + @Override + public boolean canCloseProject(Project project) { + return true; + } + + @Override + public void projectClosed(Project project) { + } + + @Override + public void projectClosing(Project project) { + if (project != null) { + VcsUsagesCollector.persistProjectUsages(project); + } + } + }); + } + + public void disposeComponent() { + } +} diff --git a/platform/vcs-impl/src/com/intellij/openapi/vcs/statistics/VcsUsagesCollector.java b/platform/vcs-impl/src/com/intellij/openapi/vcs/statistics/VcsUsagesCollector.java new file mode 100644 index 000000000000..b534312e3b82 --- /dev/null +++ b/platform/vcs-impl/src/com/intellij/openapi/vcs/statistics/VcsUsagesCollector.java @@ -0,0 +1,98 @@ +/* + * Copyright 2000-2010 JetBrains s.r.o. + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ +package com.intellij.openapi.vcs.statistics; + +import com.intellij.openapi.project.Project; +import com.intellij.openapi.vcs.ProjectLevelVcsManager; +import com.intellij.openapi.vcs.impl.VcsDescriptor; +import com.intellij.statistic.UsagesCollector; +import com.intellij.statistic.beans.GroupDescriptor; +import com.intellij.statistic.beans.UsageDescriptor; +import com.intellij.util.Function; +import com.intellij.util.containers.ContainerUtil; +import com.intellij.util.containers.hash.HashMap; +import org.jetbrains.annotations.NotNull; +import org.jetbrains.annotations.Nullable; + +import java.util.Map; +import java.util.Set; + +// todo !!! this "statistics.usagesCollector" extension !!! +public class VcsUsagesCollector extends UsagesCollector { + private static final String GROUP_ID = "vcs"; + + public static void persistProjectUsages(@NotNull Project project) { + persistProjectUsages(project, getProjectUsages(project)); + } + + public static void persistProjectUsages(@NotNull Project project, @NotNull Set usages) { + persistProjectUsages(project, usages, VcsStatisticsPersistenceComponent.getInstance()); + } + + public static void persistProjectUsages(@NotNull Project project, + @NotNull Set usages, + @NotNull VcsStatisticsPersistenceComponent persistence) { + persistence.persist(project, usages); + } + + @NotNull + public static Set getApplicationUsages() { + return getApplicationUsages(VcsStatisticsPersistenceComponent.getInstance()); + } + + @NotNull + public static Set getApplicationUsages(@NotNull final VcsStatisticsPersistenceComponent persistence) { + final Map vcsUsagesMap = new HashMap(); + + for (Set descriptors : persistence.getVcsUsageMap().values()) { + for (UsageDescriptor descriptor : descriptors) { + final String key = descriptor.getKey(); + final Integer count = vcsUsagesMap.get(key); + vcsUsagesMap.put(key, count == null ? 1 : count.intValue() + 1); + } + } + + return ContainerUtil.map2Set(vcsUsagesMap.entrySet(), new Function, UsageDescriptor>() { + @Override + public UsageDescriptor fun(Map.Entry vcsUsage) { + return new UsageDescriptor(getGroupId(), vcsUsage.getKey(), vcsUsage.getValue()); + } + }); + } + + public static GroupDescriptor getGroupId() { + return GroupDescriptor.create(GROUP_ID, GroupDescriptor.HIGHER_PRIORITY); + } + + @NotNull + public Set getUsages(@Nullable Project project) { + if (project != null) { + persistProjectUsages(project, getProjectUsages(project)); + } + + return getApplicationUsages(); + } + + public static Set getProjectUsages(@NotNull Project project) { + return ContainerUtil.map2Set(ProjectLevelVcsManager.getInstance(project).getAllVcss(), new Function() { + @Override + public UsageDescriptor fun(VcsDescriptor descriptor) { + return new UsageDescriptor(getGroupId(), descriptor.getName(), 1); + } + }); + } +} + From 148351b430134fc7b3a4fcb1cbbe8f3a2318fc78 Mon Sep 17 00:00:00 2001 From: "sergey.vasiliev" Date: Wed, 15 Dec 2010 18:22:02 +0300 Subject: [PATCH 21/54] added async comboBox for versions and refactored spring versions facet --- .../LibrariesDownloadAssistant.java | 9 +- .../ui/LibrariesDownloadUiUtil.java | 95 +++++++++++++++++++ 2 files changed, 103 insertions(+), 1 deletion(-) create mode 100644 platform/lang-api/src/com/intellij/facet/frameworks/ui/LibrariesDownloadUiUtil.java diff --git a/platform/lang-api/src/com/intellij/facet/frameworks/LibrariesDownloadAssistant.java b/platform/lang-api/src/com/intellij/facet/frameworks/LibrariesDownloadAssistant.java index 5d1676e0e255..61340ad030c0 100644 --- a/platform/lang-api/src/com/intellij/facet/frameworks/LibrariesDownloadAssistant.java +++ b/platform/lang-api/src/com/intellij/facet/frameworks/LibrariesDownloadAssistant.java @@ -11,6 +11,7 @@ import com.intellij.openapi.util.text.StringUtil; import com.intellij.util.Function; import com.intellij.util.containers.ContainerUtil; import com.intellij.util.containers.HashSet; +import com.intellij.util.net.HttpConfigurable; import com.intellij.util.xmlb.XmlSerializationException; import com.intellij.util.xmlb.XmlSerializer; import org.jetbrains.annotations.NotNull; @@ -46,11 +47,17 @@ public class LibrariesDownloadAssistant { final String serviceUrl = LibrariesDownloadConnectionService.getInstance().getServiceUrl(); if (StringUtil.isNotEmpty(serviceUrl)) { try { - return new URL(serviceUrl + "/" + id + "/"); + final String url = serviceUrl + "/" + id + "/"; + HttpConfigurable.getInstance().prepareURL(url); + + return new URL(url); } catch (MalformedURLException e) { LOG.error(e); } + catch (IOException e) { + LOG.error(e); + } } return null; diff --git a/platform/lang-api/src/com/intellij/facet/frameworks/ui/LibrariesDownloadUiUtil.java b/platform/lang-api/src/com/intellij/facet/frameworks/ui/LibrariesDownloadUiUtil.java new file mode 100644 index 000000000000..1dc9652b80d3 --- /dev/null +++ b/platform/lang-api/src/com/intellij/facet/frameworks/ui/LibrariesDownloadUiUtil.java @@ -0,0 +1,95 @@ +/* + * Copyright 2000-2010 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.facet.frameworks.ui; + +import com.intellij.facet.frameworks.LibrariesDownloadAssistant; +import com.intellij.openapi.application.ApplicationManager; +import com.intellij.openapi.application.ModalityState; +import com.intellij.ui.CollectionComboBoxModel; +import com.intellij.util.ui.update.Activatable; +import com.intellij.util.ui.update.UiNotifyConnector; +import org.jetbrains.annotations.NotNull; + +import javax.swing.*; +import java.net.URL; +import java.util.ArrayList; +import java.util.Arrays; +import java.util.List; + +public class LibrariesDownloadUiUtil { + + private LibrariesDownloadUiUtil() { + } + + public static JComboBox createVersionsCombobox(@NotNull final String groupId, final URL... localUrls) { + final JComboBox jComboBox = new JComboBox(); + + initAsyncComboBoxModel(jComboBox, groupId, localUrls); + + return jComboBox; + } + + public static void initAsyncComboBoxModel(@NotNull final JComboBox jComboBox, + @NotNull final String groupId, + final URL... localUrls) { + final List items = new ArrayList(); + + new UiNotifyConnector.Once(jComboBox, new Activatable() { + @Override + public void showNotify() { + loadItems(jComboBox, items, groupId, localUrls); + } + + @Override + public void hideNotify() { + } + }); + + items.add("loading..."); + jComboBox.setModel(new CollectionComboBoxModel(items, items.get(0))); + jComboBox.setEnabled(false); + } + + private static void loadItems(@NotNull final JComboBox jComboBox, + final List items, + final String groupId, + final URL... localUrls) { + final ModalityState state = ModalityState.current(); + ApplicationManager.getApplication().executeOnPooledThread(new Runnable() { + @Override + public void run() { + final List newItems = new ArrayList(); + newItems.addAll(Arrays.asList(LibrariesDownloadAssistant.getVersions(groupId, localUrls))); + + ApplicationManager.getApplication().invokeLater(new Runnable() { + @Override + public void run() { + items.clear(); + if (!newItems.isEmpty()) { + items.addAll(newItems); + final CollectionComboBoxModel model = (CollectionComboBoxModel)jComboBox.getModel(); + model.update(); + jComboBox.setSelectedIndex(0); + } + jComboBox.setEnabled(true); + } + }, state); + } + } + + ); + } +} From 62505fdf49040b025087b0e6e5a76026b585eca8 Mon Sep 17 00:00:00 2001 From: Denis Zhdanov Date: Wed, 15 Dec 2010 16:47:47 +0300 Subject: [PATCH 22/54] The contract is clarified for 'destructor' method that is necessary to call for correct de-initialization (that contract just follows current design of hints stuff) --- platform/platform-impl/src/com/intellij/ui/Hint.java | 10 ++++++++++ 1 file changed, 10 insertions(+) diff --git a/platform/platform-impl/src/com/intellij/ui/Hint.java b/platform/platform-impl/src/com/intellij/ui/Hint.java index 4acbb0c639a2..451ee6fbffd9 100644 --- a/platform/platform-impl/src/com/intellij/ui/Hint.java +++ b/platform/platform-impl/src/com/intellij/ui/Hint.java @@ -20,6 +20,9 @@ import org.jetbrains.annotations.NotNull; import javax.swing.*; +/** + * @see #hide() + */ public interface Hint { /** * @param parentComponent defines coordinate system where hint will be shown. @@ -36,6 +39,13 @@ public interface Hint { */ boolean isVisible(); + /** + * Hides current hint object. + *

+ * Note: this method is also used as a destruction callback, i.e. it performs necessary de-initialization when + * current hint is not necessary to use anymore. Hence, it's necessary to call it from place where you definitely + * now that current hint will not be used. + */ void hide(); void addHintListener(HintListener listener); From 8d5862ce7c46b7d2d5ca819dba2a23045b51477c Mon Sep 17 00:00:00 2001 From: Denis Zhdanov Date: Thu, 16 Dec 2010 11:59:54 +0300 Subject: [PATCH 23/54] IDEA-63036 Fold selection/code block produces visual artifacts Soft wraps cache is recalculated after fold regions recalculation now in order to work with consistent data --- .../editor/impl/EditorDocumentPriorities.java | 4 ++-- .../openapi/editor/impl/FoldingModelImpl.java | 6 ++--- .../editor/impl/SoftWrapModelImpl.java | 23 +++++++++++++++---- .../mapping/SoftWrapApplianceManager.java | 18 ++++----------- 4 files changed, 29 insertions(+), 22 deletions(-) diff --git a/platform/platform-impl/src/com/intellij/openapi/editor/impl/EditorDocumentPriorities.java b/platform/platform-impl/src/com/intellij/openapi/editor/impl/EditorDocumentPriorities.java index 79cf1924369c..991248350268 100644 --- a/platform/platform-impl/src/com/intellij/openapi/editor/impl/EditorDocumentPriorities.java +++ b/platform/platform-impl/src/com/intellij/openapi/editor/impl/EditorDocumentPriorities.java @@ -32,8 +32,8 @@ public class EditorDocumentPriorities { */ public static final int RANGE_MARKER = 40; - public static final int SOFT_WRAP_MODEL = 60; - public static final int FOLD_MODEL = 80; + public static final int FOLD_MODEL = 60; + public static final int SOFT_WRAP_MODEL = 80; public static final int LEXER_EDITOR = 100; public static final int CARET_MODEL = 120; public static final int SELECTION_MODEL = 140; diff --git a/platform/platform-impl/src/com/intellij/openapi/editor/impl/FoldingModelImpl.java b/platform/platform-impl/src/com/intellij/openapi/editor/impl/FoldingModelImpl.java index e2921401f901..f46d773a9f57 100644 --- a/platform/platform-impl/src/com/intellij/openapi/editor/impl/FoldingModelImpl.java +++ b/platform/platform-impl/src/com/intellij/openapi/editor/impl/FoldingModelImpl.java @@ -167,9 +167,9 @@ public class FoldingModelImpl implements FoldingModelEx, PrioritizedDocumentList final FoldingGroup group = region.getGroup(); if (group != null) { myGroups.putValue(group, region); - for (FoldingListener listener : myListeners) { - listener.onFoldRegionStateChange(region); - } + } + for (FoldingListener listener : myListeners) { + listener.onFoldRegionStateChange(region); } return true; } diff --git a/platform/platform-impl/src/com/intellij/openapi/editor/impl/SoftWrapModelImpl.java b/platform/platform-impl/src/com/intellij/openapi/editor/impl/SoftWrapModelImpl.java index af88b5231bd8..a2a1975a9759 100644 --- a/platform/platform-impl/src/com/intellij/openapi/editor/impl/SoftWrapModelImpl.java +++ b/platform/platform-impl/src/com/intellij/openapi/editor/impl/SoftWrapModelImpl.java @@ -76,6 +76,17 @@ public class SoftWrapModelImpl implements SoftWrapModelEx, PrioritizedDocumentLi private int myActive; private boolean myUseSoftWraps; + /** + * Soft wraps need to be kept up-to-date on all editor modification (changing text, adding/removing/expanding/collapsing fold + * regions etc). Hence, we need to react to all types of target changes. However, soft wraps processing uses various information + * provided by editor and there is a possible case that that information is inconsistent during update time (e.g. fold model + * advances fold region offsets when end-user types before it, hence, fold regions data is inconsistent between the moment + * when text changes are applied to the document and fold data is actually updated). + *

+ * Current field serves as a flag that indicates if all preliminary actions necessary for successful soft wraps processing is done. + */ + private boolean myUpdateInProgress; + public SoftWrapModelImpl(@NotNull EditorEx editor) { this(editor, new SoftWrapsStorage(), new CompositeSoftWrapPainter(editor)); } @@ -271,7 +282,7 @@ public class SoftWrapModelImpl implements SoftWrapModelEx, PrioritizedDocumentLi @NotNull @Override public LogicalPosition visualToLogicalPosition(@NotNull VisualPosition visual) { - if (!prepareToMapping()) { + if (myUpdateInProgress || !prepareToMapping()) { return myEditor.visualToLogicalPosition(visual, false); } myActive++; @@ -287,7 +298,7 @@ public class SoftWrapModelImpl implements SoftWrapModelEx, PrioritizedDocumentLi @NotNull @Override public LogicalPosition offsetToLogicalPosition(int offset) { - if (!prepareToMapping()) { + if (myUpdateInProgress || !prepareToMapping()) { return myEditor.offsetToLogicalPosition(offset, false); } myActive++; @@ -302,7 +313,7 @@ public class SoftWrapModelImpl implements SoftWrapModelEx, PrioritizedDocumentLi @NotNull public LogicalPosition adjustLogicalPosition(LogicalPosition defaultLogical, int offset) { - if (!prepareToMapping()) { + if (myUpdateInProgress || !prepareToMapping()) { return defaultLogical; } @@ -318,7 +329,7 @@ public class SoftWrapModelImpl implements SoftWrapModelEx, PrioritizedDocumentLi @NotNull public VisualPosition adjustVisualPosition(@NotNull LogicalPosition logical, @NotNull VisualPosition defaultVisual) { - if (!prepareToMapping()) { + if (myUpdateInProgress || !prepareToMapping()) { return defaultVisual; } @@ -477,6 +488,7 @@ public class SoftWrapModelImpl implements SoftWrapModelEx, PrioritizedDocumentLi @Override public void beforeDocumentChange(DocumentEvent event) { + myUpdateInProgress = true; if (!isSoftWrappingEnabled()) { return; } @@ -487,6 +499,7 @@ public class SoftWrapModelImpl implements SoftWrapModelEx, PrioritizedDocumentLi @Override public void documentChanged(DocumentEvent event) { + myUpdateInProgress = false; if (!isSoftWrappingEnabled()) { return; } @@ -497,6 +510,7 @@ public class SoftWrapModelImpl implements SoftWrapModelEx, PrioritizedDocumentLi @Override public void onFoldRegionStateChange(@NotNull FoldRegion region) { + myUpdateInProgress = true; if (!isSoftWrappingEnabled() || !region.isValid()) { return; } @@ -507,6 +521,7 @@ public class SoftWrapModelImpl implements SoftWrapModelEx, PrioritizedDocumentLi @Override public void onFoldProcessingEnd() { + myUpdateInProgress = false; if (!isSoftWrappingEnabled()) { return; } diff --git a/platform/platform-impl/src/com/intellij/openapi/editor/impl/softwrap/mapping/SoftWrapApplianceManager.java b/platform/platform-impl/src/com/intellij/openapi/editor/impl/softwrap/mapping/SoftWrapApplianceManager.java index 6c6da2a5a619..518b073d1c14 100644 --- a/platform/platform-impl/src/com/intellij/openapi/editor/impl/softwrap/mapping/SoftWrapApplianceManager.java +++ b/platform/platform-impl/src/com/intellij/openapi/editor/impl/softwrap/mapping/SoftWrapApplianceManager.java @@ -199,7 +199,7 @@ public class SoftWrapApplianceManager implements FoldingListener, DocumentListen processNonFoldToken(); } else { - boolean continueProcessing = processCollapsedFoldRegion(currentFold, event); + boolean continueProcessing = processCollapsedFoldRegion(currentFold); if (!continueProcessing) { return false; } @@ -224,11 +224,10 @@ public class SoftWrapApplianceManager implements FoldingListener, DocumentListen * Encapsulates logic of processing given collapsed fold region. * * @param foldRegion target collapsed fold region to process - * @param event change event that triggered the processing * @return true if processing should be continued; false otherwise */ - private boolean processCollapsedFoldRegion(FoldRegion foldRegion, IncrementalCacheUpdateEvent event) { - if (processOutOfDateFoldRegion(foldRegion, event)) { + private boolean processCollapsedFoldRegion(FoldRegion foldRegion) { + if (processOutOfDateFoldRegion(foldRegion)) { return false; } @@ -298,11 +297,10 @@ public class SoftWrapApplianceManager implements FoldingListener, DocumentListen * This method encapsulates logic for checking and reacting on such a situation. * * @param foldRegion fold region that may be out-of-date - * @param event change event that triggered the processing * @return true if given fold region is really out-of-date and processing should be stopped; * false otherwise; */ - private boolean processOutOfDateFoldRegion(FoldRegion foldRegion, IncrementalCacheUpdateEvent event) { + private boolean processOutOfDateFoldRegion(FoldRegion foldRegion) { Document document = myEditor.getDocument(); @@ -310,17 +308,11 @@ public class SoftWrapApplianceManager implements FoldingListener, DocumentListen // case that offsets of the trailing fold regions should be updated as well. IncrementalCacheUpdateEvent newEvent = new IncrementalCacheUpdateEvent(document); - // We assume here that fold model is processed after soft wrap (as it needs to perform document dimensions mapping). - // So, there is a possible case that user performed modifications at particular fold region but fold model is not updated yet - // and IterationState returns valid fold region. Hence, we introduce a dedicated check here. - if (!foldRegion.isValid() || (event.getExactOffsetsDiff() != 0 && foldRegion.getStartOffset() < event.getOldExactEndOffset() - && foldRegion.getEndOffset() > event.getOldExactStartOffset()) || myContext.tokenStartOffset != foldRegion.getStartOffset()) - { + if (!foldRegion.isValid() || myContext.tokenStartOffset != foldRegion.getStartOffset()) { myEventsStorage.add(document, newEvent); return true; } - if (foldRegion.getEndOffset() <= document.getTextLength()) { return false; } From a01c7c75c71af52273cc2311ac6ad9fedaec6b96 Mon Sep 17 00:00:00 2001 From: Denis Zhdanov Date: Thu, 16 Dec 2010 12:00:40 +0300 Subject: [PATCH 24/54] IDEA-62421 Extra underline of indent space on soft-wrapped text Don't draw text effects for soft wraps-introduced virtual space --- .../src/com/intellij/openapi/editor/impl/EditorImpl.java | 9 ++++----- 1 file changed, 4 insertions(+), 5 deletions(-) diff --git a/platform/platform-impl/src/com/intellij/openapi/editor/impl/EditorImpl.java b/platform/platform-impl/src/com/intellij/openapi/editor/impl/EditorImpl.java index 97c7f27a0238..90a56ca7cea2 100644 --- a/platform/platform-impl/src/com/intellij/openapi/editor/impl/EditorImpl.java +++ b/platform/platform-impl/src/com/intellij/openapi/editor/impl/EditorImpl.java @@ -2356,7 +2356,7 @@ public final class EditorImpl extends UserDataHolderBase implements EditorEx, Hi if (i < softWrapChars.length - 1) { position.x = 0; // Soft wrap starts new visual line position.x = drawString( - g, softWrapChars, i + 1, softWrapChars.length, position, clip, effectColor, effectType, fontType, fontColor + g, softWrapChars, i + 1, softWrapChars.length, position, clip, null, null, fontType, fontColor ); } position.x += mySoftWrapModel.paint(g, SoftWrapDrawingType.AFTER_SOFT_WRAP, position.x, position.y, getLineHeight()); @@ -2367,7 +2367,7 @@ public final class EditorImpl extends UserDataHolderBase implements EditorEx, Hi // Draw token text before the wrap. if (softWrap.getStart() > startToUse) { position.x = drawString( - g, text, startToUse, softWrap.getStart(), position, clip, effectColor, effectType, fontType, fontColor + g, text, startToUse, softWrap.getStart(), position, clip, null, null, fontType, fontColor ); } @@ -2385,7 +2385,7 @@ public final class EditorImpl extends UserDataHolderBase implements EditorEx, Hi // Draw soft wrap symbols on current visual line if any. if (i - softWrapSegmentStartIndex > 0) { drawString( - g, softWrapChars, softWrapSegmentStartIndex, i, position, clip, effectColor, effectType, fontType, fontColor + g, softWrapChars, softWrapSegmentStartIndex, i, position, clip, null, null, fontType, fontColor ); } mySoftWrapModel.paint(g, SoftWrapDrawingType.BEFORE_SOFT_WRAP_LINE_FEED, position.x, position.y, getLineHeight()); @@ -2405,8 +2405,7 @@ public final class EditorImpl extends UserDataHolderBase implements EditorEx, Hi // Draw remaining soft wrap symbols from its last line if any. if (softWrapSegmentStartIndex < softWrapChars.length) { position.x += drawString( - g, softWrapChars, softWrapSegmentStartIndex, softWrapChars.length, position, clip, effectColor, effectType, - fontType, fontColor + g, softWrapChars, softWrapSegmentStartIndex, softWrapChars.length, position, clip, null, null, fontType, fontColor ); } position.x += mySoftWrapModel.paint(g, SoftWrapDrawingType.AFTER_SOFT_WRAP, position.x, position.y, getLineHeight()); From e6eb6d0e20d6d01aae63af20be06bf81e7e57053 Mon Sep 17 00:00:00 2001 From: "Rustam.Vishnyakov" Date: Thu, 16 Dec 2010 11:53:59 +0300 Subject: [PATCH 25/54] JS library documentation provider UI for standalone products (WebStorm, etc.) [r=K.Safonov] --- .../ui/EditLibraryDialog.form | 77 ++++++++++-- .../ui/EditLibraryDialog.java | 113 ++++++++++++++++++ .../ui/ScriptingLibrariesPanel.java | 6 +- .../src/messages/IdeBundle.properties | 5 + 4 files changed, 191 insertions(+), 10 deletions(-) diff --git a/platform/lang-impl/src/com/intellij/ide/scriptingContext/ui/EditLibraryDialog.form b/platform/lang-impl/src/com/intellij/ide/scriptingContext/ui/EditLibraryDialog.form index e58c238c7c25..e6ca688989ca 100644 --- a/platform/lang-impl/src/com/intellij/ide/scriptingContext/ui/EditLibraryDialog.form +++ b/platform/lang-impl/src/com/intellij/ide/scriptingContext/ui/EditLibraryDialog.form @@ -1,9 +1,9 @@

- - + + - + @@ -29,18 +29,19 @@ - + + - + - + @@ -52,7 +53,7 @@ - + @@ -72,7 +73,7 @@ - + @@ -83,6 +84,66 @@ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + diff --git a/platform/lang-impl/src/com/intellij/ide/scriptingContext/ui/EditLibraryDialog.java b/platform/lang-impl/src/com/intellij/ide/scriptingContext/ui/EditLibraryDialog.java index 182a0561cc31..32cc32ee5981 100644 --- a/platform/lang-impl/src/com/intellij/ide/scriptingContext/ui/EditLibraryDialog.java +++ b/platform/lang-impl/src/com/intellij/ide/scriptingContext/ui/EditLibraryDialog.java @@ -20,16 +20,21 @@ import com.intellij.ide.scriptingContext.LangScriptingContextProvider; import com.intellij.openapi.fileChooser.FileChooser; import com.intellij.openapi.fileChooser.FileChooserDescriptor; import com.intellij.openapi.project.Project; +import com.intellij.openapi.projectRoots.ui.Util; import com.intellij.openapi.roots.OrderRootType; import com.intellij.openapi.roots.libraries.scripting.ScriptingLibraryTable; import com.intellij.openapi.ui.DialogWrapper; import com.intellij.openapi.ui.Messages; import com.intellij.openapi.vfs.VirtualFile; +import com.intellij.ui.components.JBList; import com.intellij.ui.table.JBTable; +import com.intellij.util.ArrayUtil; import com.intellij.util.containers.HashSet; import org.jetbrains.annotations.Nullable; import javax.swing.*; +import javax.swing.event.ListDataEvent; +import javax.swing.event.ListDataListener; import javax.swing.event.ListSelectionEvent; import javax.swing.event.ListSelectionListener; import javax.swing.table.AbstractTableModel; @@ -52,10 +57,14 @@ public class EditLibraryDialog extends DialogWrapper { private JButton myAddFileButton; private JButton myRemoveFileButton; private JBTable myFileTable; + private JButton myAddDocUrlButton; + private JButton myRemoveDocUrlButton; + private JBList myDocUrlList; private Project myProject; private FileTableModel myFileTableModel; private VirtualFile mySelectedFile; private LangScriptingContextProvider myProvider; + private MyDocUrlListModel myDocUrlListModel; public EditLibraryDialog(String title, LangScriptingContextProvider provider, Project project) { super(true); @@ -87,6 +96,44 @@ public class EditLibraryDialog extends DialogWrapper { updateSelection(); } }); + + myDocUrlListModel = new MyDocUrlListModel(); + myDocUrlList.setModel(myDocUrlListModel); + myDocUrlListModel.addListDataListener(new ListDataListener() { + @Override + public void intervalAdded(ListDataEvent e) { + myRemoveDocUrlButton.setEnabled(true); + } + + @Override + public void intervalRemoved(ListDataEvent e) { + Object source = e.getSource(); + if (source instanceof MyDocUrlListModel && ((MyDocUrlListModel)source).getDocUrls().length == 0) { + myRemoveDocUrlButton.setEnabled(false); + } + } + + @Override + public void contentsChanged(ListDataEvent e) { + // do nothing + } + }); + + myAddDocUrlButton.addActionListener(new ActionListener() { + @Override + public void actionPerformed(ActionEvent e) { + specifyDocUrl(); + } + }); + + myRemoveDocUrlButton.addActionListener(new ActionListener() { + @Override + public void actionPerformed(ActionEvent e) { + removeDocUrl(); + } + }); + myRemoveDocUrlButton.setEnabled(false); + init(); TableColumn typeCol = myFileTable.getColumnModel().getColumn(FILE_TYPE_COL); @@ -99,6 +146,11 @@ public class EditLibraryDialog extends DialogWrapper { this(title, provider, project); myLibName.setText(lib.getName()); myFileTableModel.setFiles(lib.getSourceFiles(), lib.getCompactFiles()); + String[] docUrls = lib.getDocUrls(); + myDocUrlListModel.setDocUrls(docUrls); + if (docUrls.length > 0) { + myRemoveDocUrlButton.setEnabled(true); + } } private class MyTableCellEditor extends DefaultCellEditor { @@ -311,6 +363,10 @@ public class EditLibraryDialog extends DialogWrapper { public VirtualFile[] getCompactFiles() { return myFileTableModel.getCompactFiles(); } + + public String[] getDocUrls() { + return myDocUrlListModel.getDocUrls(); + } @Override protected void doOKAction() { @@ -324,4 +380,61 @@ public class EditLibraryDialog extends DialogWrapper { private static boolean isLibNameValid(String libName) { return libName != null && libName.matches("\\w[\\w\\d\\._\\-\\d]*"); } + + private static class MyDocUrlListModel extends AbstractListModel { + + private ArrayList myDocUrls = new ArrayList(); + + public void setDocUrls(String[] urls) { + if (urls != null && urls.length > 0) { + myDocUrls.addAll(Arrays.asList(urls)); + } + } + + @Override + public int getSize() { + return myDocUrls.size(); + } + + @Override + public Object getElementAt(int index) { + return myDocUrls.get(index); + } + + public int addUrl(String url) { + myDocUrls.add(url); + int newIndex = myDocUrls.indexOf(url); + fireIntervalAdded(this, newIndex, newIndex); + return newIndex; + } + + public int indexOf(String url) { + return myDocUrls.indexOf(url); + } + + public void remove(String url) { + if (url == null || !myDocUrls.contains(url)) return; + int index = myDocUrls.indexOf(url); + myDocUrls.remove(url); + fireIntervalRemoved(this, index, index); + } + + public String[] getDocUrls() { + return ArrayUtil.toStringArray(myDocUrls); + } + } + + private void specifyDocUrl() { + VirtualFile vf = Util.showSpecifyJavadocUrlDialog(contentPane); + if (vf != null && vf.isValid()) { + String url = vf.getUrl(); + int index = myDocUrlListModel.addUrl(url); + myDocUrlList.ensureIndexIsVisible(index); + myDocUrlList.setSelectedIndex(index); + } + } + + private void removeDocUrl() { + myDocUrlListModel.remove((String)myDocUrlList.getSelectedValue()); + } } diff --git a/platform/lang-impl/src/com/intellij/ide/scriptingContext/ui/ScriptingLibrariesPanel.java b/platform/lang-impl/src/com/intellij/ide/scriptingContext/ui/ScriptingLibrariesPanel.java index 603dd4088551..b41ea3e2ff23 100644 --- a/platform/lang-impl/src/com/intellij/ide/scriptingContext/ui/ScriptingLibrariesPanel.java +++ b/platform/lang-impl/src/com/intellij/ide/scriptingContext/ui/ScriptingLibrariesPanel.java @@ -96,7 +96,8 @@ public class ScriptingLibrariesPanel extends ScriptingLibrariesPanelStub { EditLibraryDialog editLibDialog = new EditLibraryDialog("New Library", myProvider, myProject); editLibDialog.show(); if (editLibDialog.isOK()) { - myLibTableModel.createLibrary(editLibDialog.getLibName(), editLibDialog.getSourceFiles(), editLibDialog.getCompactFiles(), null); + myLibTableModel.createLibrary(editLibDialog.getLibName(), editLibDialog.getSourceFiles(), editLibDialog.getCompactFiles(), + editLibDialog.getDocUrls()); } } @@ -129,7 +130,8 @@ public class ScriptingLibrariesPanel extends ScriptingLibrariesPanelStub { editLibDialog.show(); if (editLibDialog.isOK()) { myLibTableModel - .updateLibrary(libName, editLibDialog.getLibName(), editLibDialog.getSourceFiles(), editLibDialog.getCompactFiles(), null); + .updateLibrary(libName, editLibDialog.getLibName(), editLibDialog.getSourceFiles(), editLibDialog.getCompactFiles(), + editLibDialog.getDocUrls()); } } } diff --git a/platform/platform-resources-en/src/messages/IdeBundle.properties b/platform/platform-resources-en/src/messages/IdeBundle.properties index 97b83f71b0d1..b32905628a95 100644 --- a/platform/platform-resources-en/src/messages/IdeBundle.properties +++ b/platform/platform-resources-en/src/messages/IdeBundle.properties @@ -1081,6 +1081,8 @@ goto.inspection.action.text=&Run Inspection by Name... label.no.inspections.found=No inspections found #Scripting library management +scripting.lib.name=&Name +scripting.lib.file.title=Files scripting.lib.file.location=Location scripting.lib.file.type=Type scripting.lib.select.root=Select library file or directory @@ -1090,6 +1092,9 @@ scripting.lib.detach=&Detach scripting.lib.add=&Add... scripting.lib.edit=&Edit... scripting.lib.remove=&Remove +scripting.lib.docUrl.specify=&Specify... +scripting.lib.docUrl.remove=&Remove +scripting.lib.docUrl.title=Documentation URLs scripting.lib.usageScope=Usage Scope scripting.lib.usageScope.caption=Specify which libraries are used in specific files and/or directories. scripting.lib.usageScope.tableTitle=Library From 8c9ab14438ef7d9f8f66d61c02528087dc693c3a Mon Sep 17 00:00:00 2001 From: Anton Makeev Date: Thu, 16 Dec 2010 13:04:45 +0300 Subject: [PATCH 26/54] undo: npe on application-level undo --- .../com/intellij/openapi/command/impl/UndoManagerImpl.java | 7 +++++-- 1 file changed, 5 insertions(+), 2 deletions(-) diff --git a/platform/platform-impl/src/com/intellij/openapi/command/impl/UndoManagerImpl.java b/platform/platform-impl/src/com/intellij/openapi/command/impl/UndoManagerImpl.java index 4bfd0229c027..1ec7ae1ea7c7 100644 --- a/platform/platform-impl/src/com/intellij/openapi/command/impl/UndoManagerImpl.java +++ b/platform/platform-impl/src/com/intellij/openapi/command/impl/UndoManagerImpl.java @@ -59,7 +59,7 @@ public class UndoManagerImpl extends UndoManager implements ProjectComponent, Ap private static final int COMMAND_TO_RUN_COMPACT = 20; private static final int FREE_QUEUES_LIMIT = 30; - private final ProjectEx myProject; + @Nullable private final ProjectEx myProject; private final CommandProcessor myCommandProcessor; private final StartupManager myStartupManager; @@ -110,6 +110,7 @@ public class UndoManagerImpl extends UndoManager implements ProjectComponent, Ap return "UndoManager"; } + @Nullable public Project getProject() { return myProject; } @@ -337,7 +338,9 @@ public class UndoManagerImpl extends UndoManager implements ProjectComponent, Ap Runnable executeUndoOrRedoAction = new Runnable() { public void run() { try { - PsiDocumentManager.getInstance(myProject).commitAllDocuments(); + if (myProject != null) { + PsiDocumentManager.getInstance(myProject).commitAllDocuments(); + } myMerger.undoOrRedo(editor, isUndo); } catch (RuntimeException ex) { From 6f8574f2903452861ef736acb81df91ba4002884 Mon Sep 17 00:00:00 2001 From: "peter.gromov" Date: Thu, 16 Dec 2010 13:40:22 +0300 Subject: [PATCH 27/54] even in a scrolled down editor, lookup shouldn't appear on another monitor --- .../src/com/intellij/codeInsight/hint/HintManagerImpl.java | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/platform/platform-impl/src/com/intellij/codeInsight/hint/HintManagerImpl.java b/platform/platform-impl/src/com/intellij/codeInsight/hint/HintManagerImpl.java index a4e841865565..f84f2d0a337e 100644 --- a/platform/platform-impl/src/com/intellij/codeInsight/hint/HintManagerImpl.java +++ b/platform/platform-impl/src/com/intellij/codeInsight/hint/HintManagerImpl.java @@ -368,7 +368,7 @@ public class HintManagerImpl extends HintManager implements Disposable { Dimension size = hint.getComponent().getPreferredSize(); if (hint.isRealPopup()) { - final Point editorCorner = editor.getContentComponent().getLocation(); + final Point editorCorner = editor.getComponent().getLocation(); SwingUtilities.convertPointToScreen(editorCorner, layeredPane); final Rectangle editorScreen = ScreenUtil.getScreenRectangle(editorCorner.x, editorCorner.y); From 69dc53a13976c785fd1e65057d43d6650b054103 Mon Sep 17 00:00:00 2001 From: "peter.gromov" Date: Thu, 16 Dec 2010 13:42:31 +0300 Subject: [PATCH 28/54] a better toString() --- .../com/intellij/codeInsight/lookup/LookupElementBuilder.java | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/platform/lang-api/src/com/intellij/codeInsight/lookup/LookupElementBuilder.java b/platform/lang-api/src/com/intellij/codeInsight/lookup/LookupElementBuilder.java index c67700f607a4..14fa3f686dc3 100644 --- a/platform/lang-api/src/com/intellij/codeInsight/lookup/LookupElementBuilder.java +++ b/platform/lang-api/src/com/intellij/codeInsight/lookup/LookupElementBuilder.java @@ -237,7 +237,7 @@ public class LookupElementBuilder extends LookupElement { @Override public String toString() { - return "LookupElementBuilder: handler=" + myInsertHandler; + return "LookupElementBuilder: string=" + getLookupString() + "; handler=" + myInsertHandler; } @Override From 74aef9c7f4b5d54dc4ca73d0638d662144e7429f Mon Sep 17 00:00:00 2001 From: Alexey Kudravtsev Date: Wed, 15 Dec 2010 13:24:11 +0300 Subject: [PATCH 29/54] performance --- .../source/tree/injected/InjectedLanguageUtil.java | 11 +++++------ 1 file changed, 5 insertions(+), 6 deletions(-) diff --git a/platform/lang-impl/src/com/intellij/psi/impl/source/tree/injected/InjectedLanguageUtil.java b/platform/lang-impl/src/com/intellij/psi/impl/source/tree/injected/InjectedLanguageUtil.java index 76472f3e5eb9..b6290097e660 100644 --- a/platform/lang-impl/src/com/intellij/psi/impl/source/tree/injected/InjectedLanguageUtil.java +++ b/platform/lang-impl/src/com/intellij/psi/impl/source/tree/injected/InjectedLanguageUtil.java @@ -60,10 +60,9 @@ public class InjectedLanguageUtil { }); } - private static PsiElement loadTree(PsiElement host) { - PsiFile file = host.getContainingFile(); - if (file instanceof DummyHolder) { - PsiElement context = file.getContext(); + private static PsiElement loadTree(PsiElement host, PsiFile containingFile) { + if (containingFile instanceof DummyHolder) { + PsiElement context = containingFile.getContext(); if (context != null) { PsiFile topFile = context.getContainingFile(); topFile.getNode(); //load tree @@ -81,7 +80,7 @@ public class InjectedLanguageUtil { @Nullable public static List> getInjectedPsiFiles(@NotNull final PsiElement host) { - final PsiElement inTree = loadTree(host); + final PsiElement inTree = loadTree(host, host.getContainingFile()); final List> result = new SmartList>(); enumerate(inTree, new PsiLanguageInjectionHost.InjectedPsiVisitor() { public void visit(@NotNull PsiFile injectedPsi, @NotNull List places) { @@ -125,7 +124,7 @@ public class InjectedLanguageUtil { if (file == null || !file.isPhysical() && file.getOriginalFile() == file) return; } - PsiElement inTree = loadTree(host); + PsiElement inTree = loadTree(host, containingFile); if (inTree != host) { host = inTree; containingFile = host.getContainingFile(); From 5c602a2d5cceacd660cca336fe996de1fe175d09 Mon Sep 17 00:00:00 2001 From: Alexey Kudravtsev Date: Wed, 15 Dec 2010 18:27:15 +0300 Subject: [PATCH 30/54] assertion text --- .../com/intellij/psi/impl/source/tree/CompositeElement.java | 4 +++- 1 file changed, 3 insertions(+), 1 deletion(-) diff --git a/platform/lang-impl/src/com/intellij/psi/impl/source/tree/CompositeElement.java b/platform/lang-impl/src/com/intellij/psi/impl/source/tree/CompositeElement.java index 4765185d4220..b4318b65923b 100644 --- a/platform/lang-impl/src/com/intellij/psi/impl/source/tree/CompositeElement.java +++ b/platform/lang-impl/src/com/intellij/psi/impl/source/tree/CompositeElement.java @@ -23,6 +23,7 @@ import com.intellij.openapi.application.ApplicationManager; import com.intellij.openapi.application.ex.ApplicationManagerEx; import com.intellij.openapi.diagnostic.Logger; import com.intellij.openapi.progress.ProgressManager; +import com.intellij.openapi.util.text.StringUtil; import com.intellij.pom.tree.events.ChangeInfo; import com.intellij.pom.tree.events.TreeChangeEvent; import com.intellij.pom.tree.events.impl.ChangeInfoImpl; @@ -388,7 +389,8 @@ public class CompositeElement extends TreeElement { } catch (AssertionError e) { myCachedLength = NOT_CACHED; - LOG.error("===\n"+PerformanceWatcher.dumpThreadsToString()+"\n===\n", e); + String assertion = StringUtil.getThrowableText(e); + LOG.error("Walking failure: ===\n"+assertion+"\n=== Thread dump:\n"+PerformanceWatcher.dumpThreadsToString()+"\n===\n"); } return myCachedLength; } From 3870d8cce6bac50e0d8532309d46f4bd138d9d1f Mon Sep 17 00:00:00 2001 From: Alexey Kudravtsev Date: Wed, 15 Dec 2010 19:42:01 +0300 Subject: [PATCH 31/54] recursion elimination --- .../intellij/psi/impl/source/PsiFileImpl.java | 38 +++++++++++-------- 1 file changed, 22 insertions(+), 16 deletions(-) diff --git a/platform/lang-impl/src/com/intellij/psi/impl/source/PsiFileImpl.java b/platform/lang-impl/src/com/intellij/psi/impl/source/PsiFileImpl.java index ee68ffffac2e..4dcc859f131b 100644 --- a/platform/lang-impl/src/com/intellij/psi/impl/source/PsiFileImpl.java +++ b/platform/lang-impl/src/com/intellij/psi/impl/source/PsiFileImpl.java @@ -909,24 +909,30 @@ public abstract class PsiFileImpl extends ElementBase implements PsiFileEx, PsiF } private void bindStubs(final ASTNode tree, final Iterator> stubs, final StubBuilder builder) { - final IElementType type = tree.getElementType(); + ((TreeElement)tree).acceptTree(new RecursiveTreeElementWalkingVisitor() { + @Override + protected void visitNode(TreeElement root) { + CompositeElement parent = root.getTreeParent(); + IElementType parentType = parent == null ? null : parent.getElementType(); + final IElementType type = root.getElementType(); + if (parentType != null && builder.skipChildProcessingWhenBuildingStubs(parentType, type)) { + return; + } - if (type instanceof IStubElementType && ((IStubElementType) type).shouldCreateStub(tree)) { - final StubElement stub = stubs.hasNext() ? stubs.next() : null; - if (stub == null || stub.getStubType() != tree.getElementType()) { - rebuildStub(); - assert false : "Stub and PSI element type mismatch in " + getName() + ": stub:" + stub + ", AST:" + tree.getElementType(); + if (type instanceof IStubElementType && ((IStubElementType) type).shouldCreateStub(root)) { + final StubElement stub = stubs.hasNext() ? stubs.next() : null; + if (stub == null || stub.getStubType() != type) { + rebuildStub(); + assert false : "Stub and PSI element type mismatch in " + getName() + ": stub:" + stub + ", AST:" + type; + } + + //noinspection unchecked + ((StubBase)stub).setPsi(root.getPsi()); + } + + super.visitNode(root); } - - //noinspection unchecked - ((StubBase)stub).setPsi(tree.getPsi()); - } - - for (ASTNode node : tree.getChildren(null)) { - if (!builder.skipChildProcessingWhenBuildingStubs(type, node.getElementType())) { - bindStubs(node, stubs, builder); - } - } + }); } private void rebuildStub() { From cd1f7108a7c41b2d75afaba4691c37b06c84048e Mon Sep 17 00:00:00 2001 From: Alexey Kudravtsev Date: Wed, 15 Dec 2010 19:45:44 +0300 Subject: [PATCH 32/54] memleaks in tests --- .../intellij/openapi/module/impl/ModuleImpl.java | 13 +++++-------- .../openapi/application/impl/ApplicationImpl.java | 5 +++++ .../intellij/openapi/project/impl/ProjectImpl.java | 1 + .../intellij/util/messages/impl/MessageBusImpl.java | 2 +- 4 files changed, 12 insertions(+), 9 deletions(-) diff --git a/platform/lang-impl/src/com/intellij/openapi/module/impl/ModuleImpl.java b/platform/lang-impl/src/com/intellij/openapi/module/impl/ModuleImpl.java index a02cc0d7afd5..b272e9bf6a52 100644 --- a/platform/lang-impl/src/com/intellij/openapi/module/impl/ModuleImpl.java +++ b/platform/lang-impl/src/com/intellij/openapi/module/impl/ModuleImpl.java @@ -37,6 +37,7 @@ import com.intellij.openapi.module.impl.scopes.ModuleWithDependentsScope; import com.intellij.openapi.project.Project; import com.intellij.openapi.roots.impl.storage.ClasspathStorage; import com.intellij.openapi.util.Comparing; +import com.intellij.openapi.util.text.StringUtil; import com.intellij.openapi.vfs.*; import com.intellij.psi.search.GlobalSearchScope; import com.intellij.util.PathUtil; @@ -322,16 +323,12 @@ public class ModuleImpl extends ComponentManagerImpl implements Module { @SuppressWarnings({"HardCodedStringLiteral"}) public String toString() { - return "Module:" + getName() + " path:" + getModuleFilePath(); + if (myName == null) return "Module"; // was called before initialized + return "Module: '" + getName() + "' path: '" + getModuleFilePath()+"'"; } - private static String moduleNameByFileName(String fileName) { - if (fileName.endsWith(ModuleFileType.DOT_DEFAULT_EXTENSION)) { - return fileName.substring(0, fileName.length() - ModuleFileType.DOT_DEFAULT_EXTENSION.length()); - } - else { - return fileName; - } + private static String moduleNameByFileName(@NotNull String fileName) { + return StringUtil.trimEnd(fileName, ModuleFileType.DOT_DEFAULT_EXTENSION); } public T[] getExtensions(final ExtensionPointName extensionPointName) { diff --git a/platform/platform-impl/src/com/intellij/openapi/application/impl/ApplicationImpl.java b/platform/platform-impl/src/com/intellij/openapi/application/impl/ApplicationImpl.java index 3c97e046ecc8..f318d33732ec 100644 --- a/platform/platform-impl/src/com/intellij/openapi/application/impl/ApplicationImpl.java +++ b/platform/platform-impl/src/com/intellij/openapi/application/impl/ApplicationImpl.java @@ -1196,4 +1196,9 @@ public class ApplicationImpl extends ComponentManagerImpl implements Application return false; } + + @Override + public String toString() { + return "Application"; + } } diff --git a/platform/platform-impl/src/com/intellij/openapi/project/impl/ProjectImpl.java b/platform/platform-impl/src/com/intellij/openapi/project/impl/ProjectImpl.java index baf26ab22705..3eef1133d039 100644 --- a/platform/platform-impl/src/com/intellij/openapi/project/impl/ProjectImpl.java +++ b/platform/platform-impl/src/com/intellij/openapi/project/impl/ProjectImpl.java @@ -220,6 +220,7 @@ public class ProjectImpl extends ComponentManagerImpl implements ProjectEx { @Nullable @NonNls public String getLocation() { + if (myName == null) return null; // was called before initialized return isDisposed() ? null : getStateStore().getLocation(); } diff --git a/platform/util/src/com/intellij/util/messages/impl/MessageBusImpl.java b/platform/util/src/com/intellij/util/messages/impl/MessageBusImpl.java index 98a732c49eaa..16e35551f9ba 100644 --- a/platform/util/src/com/intellij/util/messages/impl/MessageBusImpl.java +++ b/platform/util/src/com/intellij/util/messages/impl/MessageBusImpl.java @@ -64,7 +64,7 @@ public class MessageBusImpl implements MessageBus { } public MessageBusImpl(final Object owner, MessageBus parentBus) { - myOwner = owner; + myOwner = owner == null ? null : owner.toString(); myParentBus = (MessageBusImpl)parentBus; if (myParentBus != null) { myParentBus.notifyChildBusCreated(this); From e6ede72a4ff78a61a39669b3fea77cef4da48625 Mon Sep 17 00:00:00 2001 From: Alexey Kudravtsev Date: Thu, 16 Dec 2010 12:42:51 +0300 Subject: [PATCH 33/54] faster performance tests --- .../daemon/DaemonAnalyzerTestCase.java | 26 +++++++++++++++++++ 1 file changed, 26 insertions(+) diff --git a/java/testFramework/src/com/intellij/codeInsight/daemon/DaemonAnalyzerTestCase.java b/java/testFramework/src/com/intellij/codeInsight/daemon/DaemonAnalyzerTestCase.java index 3b45c626de31..e60ee0a4902a 100644 --- a/java/testFramework/src/com/intellij/codeInsight/daemon/DaemonAnalyzerTestCase.java +++ b/java/testFramework/src/com/intellij/codeInsight/daemon/DaemonAnalyzerTestCase.java @@ -22,6 +22,7 @@ import com.intellij.codeInsight.daemon.impl.DaemonCodeAnalyzerImpl; import com.intellij.codeInsight.daemon.impl.HighlightInfo; import com.intellij.codeInsight.daemon.quickFix.LightQuickFixTestCase; import com.intellij.codeInsight.intention.IntentionAction; +import com.intellij.codeInsight.intention.IntentionManager; import com.intellij.codeInsight.intention.impl.ShowIntentionActionsHandler; import com.intellij.codeInspection.InspectionProfileEntry; import com.intellij.codeInspection.InspectionToolProvider; @@ -33,13 +34,19 @@ import com.intellij.codeInspection.ex.LocalInspectionToolWrapper; import com.intellij.codeInspection.ex.ToolsImpl; import com.intellij.ide.startup.StartupManagerEx; import com.intellij.ide.startup.impl.StartupManagerImpl; +import com.intellij.lang.ExternalAnnotatorsFilter; +import com.intellij.lang.LanguageAnnotators; +import com.intellij.lang.StdLanguages; import com.intellij.lang.annotation.HighlightSeverity; +import com.intellij.lang.injection.InjectedLanguageManager; import com.intellij.openapi.Disposable; import com.intellij.openapi.application.ApplicationManager; import com.intellij.openapi.application.Result; +import com.intellij.openapi.application.ex.PathManagerEx; import com.intellij.openapi.command.WriteCommandAction; import com.intellij.openapi.editor.Document; import com.intellij.openapi.editor.Editor; +import com.intellij.openapi.extensions.Extensions; import com.intellij.openapi.module.Module; import com.intellij.openapi.roots.ModuleRootManager; import com.intellij.openapi.startup.StartupManager; @@ -57,15 +64,19 @@ import com.intellij.profile.codeInspection.InspectionProfileManager; import com.intellij.profile.codeInspection.InspectionProjectProfileManager; import com.intellij.psi.*; import com.intellij.psi.impl.JavaPsiFacadeEx; +import com.intellij.psi.impl.search.IndexPatternBuilder; +import com.intellij.psi.impl.source.resolve.reference.ReferenceProvidersRegistry; import com.intellij.psi.impl.source.tree.TreeElement; import com.intellij.psi.impl.source.tree.TreeUtil; import com.intellij.psi.search.GlobalSearchScope; import com.intellij.psi.search.UsageSearchContext; +import com.intellij.psi.xml.XmlFileNSInfoProvider; import com.intellij.testFramework.ExpectedHighlightingData; import com.intellij.testFramework.FileTreeAccessFilter; import com.intellij.testFramework.LightPlatformTestCase; import com.intellij.testFramework.fixtures.impl.CodeInsightTestFixtureImpl; import com.intellij.util.IncorrectOperationException; +import com.intellij.xml.XmlSchemaProvider; import gnu.trove.THashMap; import gnu.trove.TIntArrayList; import org.jetbrains.annotations.NonNls; @@ -160,6 +171,21 @@ public abstract class DaemonAnalyzerTestCase extends CodeInsightTestCase { DaemonCodeAnalyzerSettings.getInstance().setImportHintEnabled(false); myRunCommandForTest = !annotatedWith(DoNotWrapInCommand.class); + + if (isPerformanceTest()) { + IntentionManager.getInstance().getAvailableIntentionActions(); // hack to avoid slowdowns in PyExtensionFactory + PathManagerEx.getTestDataPath(); // to cache stuff + ReferenceProvidersRegistry.getInstance(getProject()); // preload tons of classes + InjectedLanguageManager.getInstance(getProject()); // zillion of Dom Sem classes + LanguageAnnotators.INSTANCE.allForLanguage(StdLanguages.JAVA); // pile of annotator classes loads + LanguageAnnotators.INSTANCE.allForLanguage(StdLanguages.XML); + ProblemHighlightFilter.EP_NAME.getExtensions(); + Extensions.getExtensions(ImplicitUsageProvider.EP_NAME); + Extensions.getExtensions(XmlSchemaProvider.EP_NAME); + Extensions.getExtensions(XmlFileNSInfoProvider.EP_NAME); + Extensions.getExtensions(ExternalAnnotatorsFilter.EXTENSION_POINT_NAME); + Extensions.getExtensions(IndexPatternBuilder.EP_NAME); + } } @Override From 7b84fd94d23b17d71934d0f4a0dc8814f8f42c3c Mon Sep 17 00:00:00 2001 From: Alexey Kudravtsev Date: Thu, 16 Dec 2010 13:10:30 +0300 Subject: [PATCH 34/54] cleanup --- .../psi/impl/PsiDocumentTransactionListener.java | 4 ++-- .../intellij/testFramework/LoggedErrorProcessor.java | 7 +++---- .../com/intellij/openapi/util/text/StringUtil.java | 2 +- .../util/messages/impl/MessageBusConnectionImpl.java | 11 ++--------- xml/impl/src/com/intellij/xml/XmlExtension.java | 1 - .../src/com/intellij/xml/XmlSchemaProvider.java | 12 +++++------- 6 files changed, 13 insertions(+), 24 deletions(-) diff --git a/platform/lang-impl/src/com/intellij/psi/impl/PsiDocumentTransactionListener.java b/platform/lang-impl/src/com/intellij/psi/impl/PsiDocumentTransactionListener.java index 0334dd6d2dda..02c61db3d138 100644 --- a/platform/lang-impl/src/com/intellij/psi/impl/PsiDocumentTransactionListener.java +++ b/platform/lang-impl/src/com/intellij/psi/impl/PsiDocumentTransactionListener.java @@ -24,8 +24,8 @@ import com.intellij.psi.PsiFile; import com.intellij.util.messages.Topic; public interface PsiDocumentTransactionListener { - Topic TOPIC = new Topic("psi.DocumentTransactionListener", PsiDocumentTransactionListener.class, Topic.BroadcastDirection.TO_PARENT); + Topic TOPIC = new Topic("psi.DocumentTransactionListener", PsiDocumentTransactionListener.class, Topic.BroadcastDirection.TO_PARENT); void transactionStarted(Document doc, PsiFile file); void transactionCompleted(Document doc, PsiFile file); -} \ No newline at end of file +} diff --git a/platform/testFramework/src/com/intellij/testFramework/LoggedErrorProcessor.java b/platform/testFramework/src/com/intellij/testFramework/LoggedErrorProcessor.java index 769916a183b6..18be4a3942cb 100644 --- a/platform/testFramework/src/com/intellij/testFramework/LoggedErrorProcessor.java +++ b/platform/testFramework/src/com/intellij/testFramework/LoggedErrorProcessor.java @@ -19,8 +19,7 @@ import org.apache.log4j.Logger; import org.jetbrains.annotations.NonNls; @NonNls public abstract class LoggedErrorProcessor { - - private final static LoggedErrorProcessor DEFAULT = new LoggedErrorProcessor() { + private static final LoggedErrorProcessor DEFAULT = new LoggedErrorProcessor() { @Override public void processError(String message, Throwable t, String[] details, Logger logger) { logger.info(message, t); @@ -28,8 +27,8 @@ import org.jetbrains.annotations.NonNls; t.printStackTrace(); if (details != null && details.length > 0) { System.out.println("details: "); - for (int i = 0; i < details.length; i++) { - System.out.println(details[i]); + for (String detail : details) { + System.out.println(detail); } } diff --git a/platform/util/src/com/intellij/openapi/util/text/StringUtil.java b/platform/util/src/com/intellij/openapi/util/text/StringUtil.java index 34b301878989..77686521f389 100644 --- a/platform/util/src/com/intellij/openapi/util/text/StringUtil.java +++ b/platform/util/src/com/intellij/openapi/util/text/StringUtil.java @@ -795,7 +795,7 @@ public class StringUtil { @NotNull public static String trimEnd(@NotNull String s, @NonNls @NotNull String suffix) { if (s.endsWith(suffix)) { - return s.substring(0, s.lastIndexOf(suffix)); + return s.substring(0, s.length() - suffix.length()); } return s; } diff --git a/platform/util/src/com/intellij/util/messages/impl/MessageBusConnectionImpl.java b/platform/util/src/com/intellij/util/messages/impl/MessageBusConnectionImpl.java index f0ad663f76b2..be84fd2683d1 100644 --- a/platform/util/src/com/intellij/util/messages/impl/MessageBusConnectionImpl.java +++ b/platform/util/src/com/intellij/util/messages/impl/MessageBusConnectionImpl.java @@ -47,25 +47,18 @@ public class MessageBusConnectionImpl implements MessageBusConnection { } public void subscribe(Topic topic, L handler) { - if (mySubscriptions.containsKey(topic)) { + if (mySubscriptions.put(topic, handler) != null) { throw new IllegalStateException("Subscription to " + topic + " already exists"); } - - mySubscriptions.put(topic, handler); myBus.notifyOnSubscription(this, topic); } public void subscribe(Topic topic) { - if (mySubscriptions.containsKey(topic)) { - throw new IllegalStateException("Subscription to " + topic + " already exists"); - } - if (myDefaultHandler == null) { throw new IllegalStateException("Connection must have default handler installed prior to any anonymous subscriptions."); } - mySubscriptions.put(topic, myDefaultHandler); - myBus.notifyOnSubscription(this, topic); + subscribe(topic, (L)myDefaultHandler); } public void setDefaultHandler(MessageHandler handler) { diff --git a/xml/impl/src/com/intellij/xml/XmlExtension.java b/xml/impl/src/com/intellij/xml/XmlExtension.java index 761c649d37a1..24e98a544684 100644 --- a/xml/impl/src/com/intellij/xml/XmlExtension.java +++ b/xml/impl/src/com/intellij/xml/XmlExtension.java @@ -49,7 +49,6 @@ import java.util.Set; * @author Dmitry Avdeev */ public abstract class XmlExtension { - private static final ExtensionPointName EP_NAME = new ExtensionPointName("com.intellij.xml.xmlExtension"); public static final XmlExtension DEFAULT_EXTENSION = new DefaultXmlExtension(); diff --git a/xml/openapi/src/com/intellij/xml/XmlSchemaProvider.java b/xml/openapi/src/com/intellij/xml/XmlSchemaProvider.java index 7fa5b7b3e19e..0735d0061ee5 100644 --- a/xml/openapi/src/com/intellij/xml/XmlSchemaProvider.java +++ b/xml/openapi/src/com/intellij/xml/XmlSchemaProvider.java @@ -20,7 +20,6 @@ import com.intellij.openapi.extensions.ExtensionPointName; import com.intellij.openapi.extensions.Extensions; import com.intellij.openapi.module.Module; import com.intellij.openapi.module.ModuleUtil; -import com.intellij.openapi.project.DumbAware; import com.intellij.openapi.project.DumbService; import com.intellij.openapi.util.Condition; import com.intellij.psi.PsiDirectory; @@ -39,8 +38,7 @@ import java.util.Set; * @author Dmitry Avdeev */ public abstract class XmlSchemaProvider { - - public final static ExtensionPointName EP_NAME = new ExtensionPointName("com.intellij.xml.schemaProvider"); + public static final ExtensionPointName EP_NAME = new ExtensionPointName("com.intellij.xml.schemaProvider"); @Nullable public static XmlFile findSchema(@NotNull @NonNls String namespace, @Nullable Module module, @NotNull PsiFile file) { @@ -74,7 +72,7 @@ public abstract class XmlSchemaProvider { */ @Deprecated @Nullable - public static XmlSchemaProvider getAvailableProvider(final @NotNull XmlFile file) { + public static XmlSchemaProvider getAvailableProvider(@NotNull final XmlFile file) { for (XmlSchemaProvider provider: Extensions.getExtensions(EP_NAME)) { if (provider.isAvailable(file)) { return provider; @@ -83,7 +81,7 @@ public abstract class XmlSchemaProvider { return null; } - public static List getAvailableProviders(final @NotNull XmlFile file) { + public static List getAvailableProviders(@NotNull final XmlFile file) { return ContainerUtil.findAll(Extensions.getExtensions(EP_NAME), new Condition() { public boolean value(XmlSchemaProvider xmlSchemaProvider) { return xmlSchemaProvider.isAvailable(file); @@ -95,7 +93,7 @@ public abstract class XmlSchemaProvider { public abstract XmlFile getSchema(@NotNull @NonNls String url, @Nullable Module module, @NotNull final PsiFile baseFile); - public boolean isAvailable(final @NotNull XmlFile file) { + public boolean isAvailable(@NotNull final XmlFile file) { return false; } @@ -106,7 +104,7 @@ public abstract class XmlSchemaProvider { * @return available namespace uris, or null if the provider did not recognize the file. */ @NotNull - public Set getAvailableNamespaces(final @NotNull XmlFile file, final @Nullable String tagName) { + public Set getAvailableNamespaces(@NotNull final XmlFile file, @Nullable final String tagName) { return Collections.emptySet(); } From db474a0ffe652e87410445c72cd9644e21978ec5 Mon Sep 17 00:00:00 2001 From: "peter.gromov" Date: Thu, 16 Dec 2010 14:33:07 +0300 Subject: [PATCH 35/54] IDEA-59018 GDSL: after changing and activating a .gdsl script, all methods/properties added by the script becomes unresolved in .groovy script --- .../plugins/groovy/dsl/GroovyDslFileIndex.java | 11 ++++++++--- 1 file changed, 8 insertions(+), 3 deletions(-) diff --git a/plugins/groovy/src/org/jetbrains/plugins/groovy/dsl/GroovyDslFileIndex.java b/plugins/groovy/src/org/jetbrains/plugins/groovy/dsl/GroovyDslFileIndex.java index 67f34354b175..6868eca27dd8 100644 --- a/plugins/groovy/src/org/jetbrains/plugins/groovy/dsl/GroovyDslFileIndex.java +++ b/plugins/groovy/src/org/jetbrains/plugins/groovy/dsl/GroovyDslFileIndex.java @@ -148,6 +148,13 @@ public class GroovyDslFileIndex extends ScalarIndexExtension { catch (IOException e) { LOG.error(e); } + clearScriptCache(); + } + + private static void clearScriptCache() { + for (Project project : ProjectManager.getInstance().getOpenProjects()) { + project.putUserData(SCRIPTS_CACHE, null); + } } static void disableFile(final VirtualFile vfile) { @@ -158,9 +165,7 @@ public class GroovyDslFileIndex extends ScalarIndexExtension { LOG.error(e1); } vfile.putUserData(CACHED_EXECUTOR, null); - for (Project project : ProjectManager.getInstance().getOpenProjects()) { - project.putUserData(SCRIPTS_CACHE, null); - } + clearScriptCache(); } From 8cfd6aa17194ace0f48fb7cb25546c31d25e214e Mon Sep 17 00:00:00 2001 From: Roman Shevchenko Date: Tue, 14 Dec 2010 22:07:25 +0300 Subject: [PATCH 36/54] Cleanup --- .../intellij/psi/impl/source/SourceTreeToPsiMap.java | 11 ++++++----- 1 file changed, 6 insertions(+), 5 deletions(-) diff --git a/platform/lang-impl/src/com/intellij/psi/impl/source/SourceTreeToPsiMap.java b/platform/lang-impl/src/com/intellij/psi/impl/source/SourceTreeToPsiMap.java index 947be673102c..e2c777821e95 100644 --- a/platform/lang-impl/src/com/intellij/psi/impl/source/SourceTreeToPsiMap.java +++ b/platform/lang-impl/src/com/intellij/psi/impl/source/SourceTreeToPsiMap.java @@ -23,20 +23,21 @@ import com.intellij.psi.impl.source.tree.TreeElement; import org.jetbrains.annotations.Nullable; public class SourceTreeToPsiMap { - private SourceTreeToPsiMap() { - } + private SourceTreeToPsiMap() { } - public static PsiElement treeElementToPsi(@Nullable ASTNode element) { + @Nullable + public static PsiElement treeElementToPsi(@Nullable final ASTNode element) { if (element == null) return null; return element.getPsi(); } - public static ASTNode psiElementToTree(@Nullable PsiElement psiElement) { + @Nullable + public static ASTNode psiElementToTree(@Nullable final PsiElement psiElement) { if (psiElement == null) return null; return psiElement.getNode(); } - public static boolean hasTreeElement(@Nullable PsiElement psiElement) { + public static boolean hasTreeElement(@Nullable final PsiElement psiElement) { return psiElement instanceof TreeElement || psiElement instanceof ASTDelegatePsiElement || psiElement instanceof PsiFileImpl; } } From f742e0dc5ddf53dcbe5d104f4e5793a183034766 Mon Sep 17 00:00:00 2001 From: Roman Shevchenko Date: Tue, 14 Dec 2010 22:08:57 +0300 Subject: [PATCH 37/54] Don't pass leading spaces to Java parser facade --- .../VariableAccessFromInnerClassFix.java | 2 +- .../extractclass/ExtractClassProcessor.java | 5 ++-- .../generator/GroovyToJavaGenerator.java | 28 +++++++++++-------- 3 files changed, 19 insertions(+), 16 deletions(-) diff --git a/java/java-impl/src/com/intellij/codeInsight/daemon/impl/quickfix/VariableAccessFromInnerClassFix.java b/java/java-impl/src/com/intellij/codeInsight/daemon/impl/quickfix/VariableAccessFromInnerClassFix.java index 5b5355f5f048..56b34711ed8b 100644 --- a/java/java-impl/src/com/intellij/codeInsight/daemon/impl/quickfix/VariableAccessFromInnerClassFix.java +++ b/java/java-impl/src/com/intellij/codeInsight/daemon/impl/quickfix/VariableAccessFromInnerClassFix.java @@ -176,7 +176,7 @@ public class VariableAccessFromInnerClassFix implements IntentionAction { variableDeclarationStatement = factory.createVariableDeclarationStatement(variable.getName(), newType, init); } else { - PsiExpression init = factory.createExpressionFromText(" { " + initializer.getText() + " }", variable); + PsiExpression init = factory.createExpressionFromText("{ " + initializer.getText() + " }", variable); variableDeclarationStatement = factory.createVariableDeclarationStatement(variable.getName(), newType, init); } PsiVariable newVariable = (PsiVariable)variableDeclarationStatement.getDeclaredElements()[0]; diff --git a/java/java-impl/src/com/intellij/refactoring/extractclass/ExtractClassProcessor.java b/java/java-impl/src/com/intellij/refactoring/extractclass/ExtractClassProcessor.java index f834fb0292b4..19f0c1df49c4 100644 --- a/java/java-impl/src/com/intellij/refactoring/extractclass/ExtractClassProcessor.java +++ b/java/java-impl/src/com/intellij/refactoring/extractclass/ExtractClassProcessor.java @@ -395,7 +395,7 @@ public class ExtractClassProcessor extends FixableUsagesRefactoringProcessor { final CodeStyleManager codeStyleManager = manager.getCodeStyleManager(); @NonNls final StringBuilder fieldBuffer = new StringBuilder(); final String delegateVisibility = calculateDelegateVisibility(); - fieldBuffer.append(delegateVisibility).append(' '); + if (delegateVisibility.length() > 0) fieldBuffer.append(delegateVisibility).append(' '); fieldBuffer.append("final "); final String fullyQualifiedName = StringUtil.getQualifiedName(newPackageName, newClassName); fieldBuffer.append(fullyQualifiedName); @@ -408,8 +408,7 @@ public class ExtractClassProcessor extends FixableUsagesRefactoringProcessor { } fieldBuffer.append(' '); fieldBuffer.append(delegateFieldName); - fieldBuffer.append('='); - fieldBuffer.append("new ").append(fullyQualifiedName); + fieldBuffer.append(" = new ").append(fullyQualifiedName); if (!typeParams.isEmpty()) { fieldBuffer.append('<'); for (PsiTypeParameter typeParameter : typeParams) { diff --git a/plugins/groovy/src/org/jetbrains/plugins/groovy/compiler/generator/GroovyToJavaGenerator.java b/plugins/groovy/src/org/jetbrains/plugins/groovy/compiler/generator/GroovyToJavaGenerator.java index 4e54bcb542c3..27ed3f58f051 100644 --- a/plugins/groovy/src/org/jetbrains/plugins/groovy/compiler/generator/GroovyToJavaGenerator.java +++ b/plugins/groovy/src/org/jetbrains/plugins/groovy/compiler/generator/GroovyToJavaGenerator.java @@ -288,7 +288,7 @@ public class GroovyToJavaGenerator { } if (method instanceof GrConstructor) { - writeConstructor(text, (GrConstructor)method, aClass.isEnum()); + writeConstructor(text, (GrConstructor)method, aClass.isEnum(), true); continue; } @@ -305,7 +305,7 @@ public class GroovyToJavaGenerator { MethodSignature signature = MethodSignatureUtil.createMethodSignature(method.getName(), parameterTypes, method.getTypeParameters(), PsiSubstitutor.EMPTY); if (methodSignatures.add(signature)) { - writeMethod(text, method, parametersCopy); + writeMethod(text, method, parametersCopy, true); } PsiParameter parameter = parameters[i]; @@ -317,7 +317,7 @@ public class GroovyToJavaGenerator { else { MethodSignature signature = method.getSignature(PsiSubstitutor.EMPTY); if (methodSignatures.add(signature)) { - writeMethod(text, method, parameters); + writeMethod(text, method, parameters, true); } } } @@ -407,7 +407,7 @@ public class GroovyToJavaGenerator { if (block != null) { text.append("{\n"); for (PsiMethod method : block.getMethods()) { - writeMethod(text, method, method.getParameterList().getParameters()); + writeMethod(text, method, method.getParameterList().getParameters(), true); } text.append("}"); } @@ -434,9 +434,11 @@ public class GroovyToJavaGenerator { } } - private void writeConstructor(final StringBuffer text, final GrConstructor constructor, boolean isEnum) { - text.append("\n"); - text.append(" "); + private void writeConstructor(final StringBuffer text, final GrConstructor constructor, boolean isEnum, final boolean prefix) { + if (prefix) { + text.append("\n"); + text.append(" "); + } if (!isEnum) { text.append("public "); //writeMethodModifiers(text, constructor.getModifierList(), JAVA_MODIFIERS); @@ -562,15 +564,15 @@ public class GroovyToJavaGenerator { final GroovyToJavaGenerator generator = new GroovyToJavaGenerator(method.getProject(), null, Collections.emptyList()); final StringBuffer buffer = new StringBuffer(); if (method instanceof GrConstructor) { - generator.writeConstructor(buffer, (GrConstructor)method, false); + generator.writeConstructor(buffer, (GrConstructor)method, false, false); } else { - generator.writeMethod(buffer, method, method.getParameterList().getParameters()); + generator.writeMethod(buffer, method, method.getParameterList().getParameters(), false); } return buffer.toString(); } - private void writeMethod(StringBuffer text, PsiMethod method, final PsiParameter[] parameters) { + private void writeMethod(StringBuffer text, PsiMethod method, final PsiParameter[] parameters, final boolean prefix) { if (method == null) return; String name = method.getName(); if (!JavaPsiFacade.getInstance(method.getProject()).getNameHelper().isIdentifier(name)) @@ -580,8 +582,10 @@ public class GroovyToJavaGenerator { PsiModifierList modifierList = method.getModifierList(); - text.append("\n"); - text.append(" "); + if (prefix) { + text.append("\n"); + text.append(" "); + } writeMethodModifiers(text, modifierList, JAVA_MODIFIERS); if (method.hasTypeParameters()) { appendTypeParameters(text, method); From 3373849bbca79d2163ddd132dbd578ed378c3036 Mon Sep 17 00:00:00 2001 From: Roman Shevchenko Date: Tue, 14 Dec 2010 22:09:55 +0300 Subject: [PATCH 38/54] Missing string join method added --- .../intellij/openapi/util/text/StringUtil.java | 16 ++++++++++++++++ 1 file changed, 16 insertions(+) diff --git a/platform/util/src/com/intellij/openapi/util/text/StringUtil.java b/platform/util/src/com/intellij/openapi/util/text/StringUtil.java index 77686521f389..7e8ac5b0ae7d 100644 --- a/platform/util/src/com/intellij/openapi/util/text/StringUtil.java +++ b/platform/util/src/com/intellij/openapi/util/text/StringUtil.java @@ -1087,6 +1087,22 @@ public class StringUtil { return result.toString(); } + @NotNull + public static String join(final String... strings) { + if (strings == null || strings.length == 0) return ""; + + final StringBuilder builder = StringBuilderSpinAllocator.alloc(); + try { + for (final String string : strings) { + builder.append(string); + } + return builder.toString(); + } + finally { + StringBuilderSpinAllocator.dispose(builder); + } + } + @NotNull public static String stripQuotesAroundValue(@NotNull String text) { if (startsWithChar(text, '\"') || startsWithChar(text, '\'')) text = text.substring(1); From 280df748e1ac29b4e34986662008178fe1a6b189 Mon Sep 17 00:00:00 2001 From: Roman Shevchenko Date: Tue, 14 Dec 2010 22:50:15 +0300 Subject: [PATCH 39/54] Primitive type constants type fixed --- .../util/RefactoringHierarchyUtil.java | 3 ++- .../openapi/src/com/intellij/psi/PsiType.java | 21 ++++++++++--------- 2 files changed, 13 insertions(+), 11 deletions(-) diff --git a/java/java-impl/src/com/intellij/refactoring/util/RefactoringHierarchyUtil.java b/java/java-impl/src/com/intellij/refactoring/util/RefactoringHierarchyUtil.java index 573eeffbc369..257f978adc0a 100644 --- a/java/java-impl/src/com/intellij/refactoring/util/RefactoringHierarchyUtil.java +++ b/java/java-impl/src/com/intellij/refactoring/util/RefactoringHierarchyUtil.java @@ -38,7 +38,8 @@ import java.util.*; public class RefactoringHierarchyUtil { private static final Logger LOG = Logger.getInstance("#com.intellij.refactoring.util.RefactoringHierarchyUtil"); - private static final List PRIMITIVE_TYPES = Arrays.asList( + + private static final List PRIMITIVE_TYPES = Arrays.asList( PsiType.BYTE, PsiType.CHAR, PsiType.SHORT, PsiType.INT, PsiType.LONG, PsiType.FLOAT, PsiType.DOUBLE ); diff --git a/java/openapi/src/com/intellij/psi/PsiType.java b/java/openapi/src/com/intellij/psi/PsiType.java index 7d62a6f7ca91..5c70c8a21576 100644 --- a/java/openapi/src/com/intellij/psi/PsiType.java +++ b/java/openapi/src/com/intellij/psi/PsiType.java @@ -27,16 +27,17 @@ import org.jetbrains.annotations.Nullable; * Representation of Java type (primitive type, array or class type). */ public abstract class PsiType implements PsiAnnotationOwner { - public static final PsiType BYTE = new PsiPrimitiveType("byte", "java.lang.Byte"); - public static final PsiType CHAR = new PsiPrimitiveType("char", "java.lang.Character"); - public static final PsiType DOUBLE = new PsiPrimitiveType("double", "java.lang.Double"); - public static final PsiType FLOAT = new PsiPrimitiveType("float", "java.lang.Float"); - public static final PsiType INT = new PsiPrimitiveType("int", "java.lang.Integer"); - public static final PsiType LONG = new PsiPrimitiveType("long", "java.lang.Long"); - public static final PsiType SHORT = new PsiPrimitiveType("short", "java.lang.Short"); - public static final PsiType BOOLEAN = new PsiPrimitiveType("boolean", "java.lang.Boolean"); - public static final PsiType VOID = new PsiPrimitiveType("void", "java.lang.Void"); - public static final PsiType NULL = new PsiPrimitiveType("null", (String)null); + public static final PsiPrimitiveType BYTE = new PsiPrimitiveType("byte", "java.lang.Byte"); + public static final PsiPrimitiveType CHAR = new PsiPrimitiveType("char", "java.lang.Character"); + public static final PsiPrimitiveType DOUBLE = new PsiPrimitiveType("double", "java.lang.Double"); + public static final PsiPrimitiveType FLOAT = new PsiPrimitiveType("float", "java.lang.Float"); + public static final PsiPrimitiveType INT = new PsiPrimitiveType("int", "java.lang.Integer"); + public static final PsiPrimitiveType LONG = new PsiPrimitiveType("long", "java.lang.Long"); + public static final PsiPrimitiveType SHORT = new PsiPrimitiveType("short", "java.lang.Short"); + public static final PsiPrimitiveType BOOLEAN = new PsiPrimitiveType("boolean", "java.lang.Boolean"); + public static final PsiPrimitiveType VOID = new PsiPrimitiveType("void", "java.lang.Void"); + public static final PsiPrimitiveType NULL = new PsiPrimitiveType("null", (String)null); + public static final PsiType[] EMPTY_ARRAY = new PsiType[0]; private final PsiAnnotation[] myAnnotations; From 6cf386c376358f7564e92353ec1943b941ed41f1 Mon Sep 17 00:00:00 2001 From: Roman Shevchenko Date: Wed, 15 Dec 2010 16:12:14 +0300 Subject: [PATCH 40/54] Typo --- .../src/com/intellij/lang/impl/PsiBuilderImpl.java | 8 ++++---- 1 file changed, 4 insertions(+), 4 deletions(-) diff --git a/platform/lang-impl/src/com/intellij/lang/impl/PsiBuilderImpl.java b/platform/lang-impl/src/com/intellij/lang/impl/PsiBuilderImpl.java index 896911a5ce1e..522c70575b82 100644 --- a/platform/lang-impl/src/com/intellij/lang/impl/PsiBuilderImpl.java +++ b/platform/lang-impl/src/com/intellij/lang/impl/PsiBuilderImpl.java @@ -93,7 +93,7 @@ public class PsiBuilderImpl extends UserDataHolderBase implements PsiBuilder { private int myLexemeCount = 0; private boolean myTokenTypeChecked; private ITokenTypeRemapper myRemapper; - private WhitespaceSkippedCallback myWhispaceSkippedCallback; + private WhitespaceSkippedCallback myWhitespaceSkippedCallback; private ASTNode myOriginalTree = null; @@ -626,7 +626,7 @@ public class PsiBuilderImpl extends UserDataHolderBase implements PsiBuilder { @Override public void setWhitespaceSkippedCallback(WhitespaceSkippedCallback callback) { - myWhispaceSkippedCallback = callback; + myWhitespaceSkippedCallback = callback; } public void advanceLexer() { @@ -647,8 +647,8 @@ public class PsiBuilderImpl extends UserDataHolderBase implements PsiBuilder { } private void onSkip(IElementType type, int start, int end) { - if (myWhispaceSkippedCallback != null) { - myWhispaceSkippedCallback.onSkip(type, start, end); + if (myWhitespaceSkippedCallback != null) { + myWhitespaceSkippedCallback.onSkip(type, start, end); } } From 2e8fa6eb9b372a269877fc608060cb5d2468d731 Mon Sep 17 00:00:00 2001 From: Roman Shevchenko Date: Wed, 15 Dec 2010 17:50:14 +0300 Subject: [PATCH 41/54] Dummy Java element with pluggable parser --- .../lang/java/parser/JavaParserUtil.java | 10 ++- .../psi/impl/source/JavaDummyElement.java | 82 +++++++++++++++++++ .../psi/impl/source/tree/JavaElementType.java | 22 +++++ .../intellij/psi/impl/source/DummyHolder.java | 13 ++- 4 files changed, 121 insertions(+), 6 deletions(-) create mode 100644 java/java-impl/src/com/intellij/psi/impl/source/JavaDummyElement.java diff --git a/java/java-impl/src/com/intellij/lang/java/parser/JavaParserUtil.java b/java/java-impl/src/com/intellij/lang/java/parser/JavaParserUtil.java index 99982aed1d3d..9313500b6149 100644 --- a/java/java-impl/src/com/intellij/lang/java/parser/JavaParserUtil.java +++ b/java/java-impl/src/com/intellij/lang/java/parser/JavaParserUtil.java @@ -184,13 +184,18 @@ public class JavaParserUtil { return builder; } + @Nullable public static ASTNode parseFragment(final ASTNode chameleon, final ParserWrapper wrapper) { + return parseFragment(chameleon, wrapper, true, LanguageLevel.HIGHEST); + } + + @Nullable + public static ASTNode parseFragment(final ASTNode chameleon, final ParserWrapper wrapper, final boolean eatAll, final LanguageLevel level) { final PsiElement psi = (chameleon.getTreeParent() != null ? chameleon.getTreeParent().getPsi() : chameleon.getPsi()); assert psi != null : chameleon; final Project project = psi.getProject(); final PsiBuilderFactory factory = PsiBuilderFactory.getInstance(); - final LanguageLevel level = LanguageLevel.HIGHEST; final Lexer lexer = JavaParserDefinition.createLexer(level); final PsiBuilder builder = factory.createBuilder(project, chameleon, lexer, chameleon.getElementType().getLanguage(), chameleon.getChars()); setLanguageLevel(builder, level); @@ -198,6 +203,7 @@ public class JavaParserUtil { final PsiBuilder.Marker root = builder.mark(); wrapper.parse(builder); if (!builder.eof()) { + if (!eatAll) throw new AssertionError("Unexpected tokens"); final PsiBuilder.Marker extras = builder.mark(); while (!builder.eof()) builder.advanceLexer(); extras.error(JavaErrorMessages.message("unexpected.tokens")); @@ -389,4 +395,4 @@ public class JavaParserUtil { myDelegate.putUserDataUnprotected(key, value); } } -} +} \ No newline at end of file diff --git a/java/java-impl/src/com/intellij/psi/impl/source/JavaDummyElement.java b/java/java-impl/src/com/intellij/psi/impl/source/JavaDummyElement.java new file mode 100644 index 000000000000..c54c4e18eba8 --- /dev/null +++ b/java/java-impl/src/com/intellij/psi/impl/source/JavaDummyElement.java @@ -0,0 +1,82 @@ +/* + * Copyright 2000-2010 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.psi.impl.source; + +import com.intellij.lang.java.parser.JavaParserUtil; +import com.intellij.pom.java.LanguageLevel; +import com.intellij.psi.impl.source.tree.FileElement; +import com.intellij.psi.impl.source.tree.JavaElementType; +import com.intellij.psi.impl.source.tree.TreeElement; +import org.jetbrains.annotations.NotNull; +import org.jetbrains.annotations.Nullable; + +/** + * Dummy file element for using together with DummyHolder. + * See {@link com.intellij.psi.impl.PsiJavaParserFacadeImpl} for details. + */ +public class JavaDummyElement extends FileElement { + @NotNull private final JavaParserUtil.ParserWrapper myParser; + private final boolean myConsumeAll; + @NotNull private final LanguageLevel myLanguageLevel; + + public JavaDummyElement(@Nullable final CharSequence text, @NotNull final JavaParserUtil.ParserWrapper parser, final boolean consumeAll) { + this(text, parser, consumeAll, LanguageLevel.HIGHEST); + } + + public JavaDummyElement(@Nullable final CharSequence text, + @NotNull final JavaParserUtil.ParserWrapper parser, + final boolean consumeAll, + @NotNull final LanguageLevel level) { + super(JavaElementType.DUMMY_ELEMENT, text); + myParser = parser; + myConsumeAll = consumeAll; + myLanguageLevel = level; + } + + @NotNull + public JavaParserUtil.ParserWrapper getParser() { + return myParser; + } + + public boolean consumeAll() { + return myConsumeAll; + } + + @NotNull + public LanguageLevel getLanguageLevel() { + return myLanguageLevel; + } + + @Override + public TreeElement getFirstChildNode() { + try { + return super.getFirstChildNode(); + } + catch (AssertionError e) { + return null; // masquerade parser errors + } + } + + @Override + public TreeElement getLastChildNode() { + try { + return super.getLastChildNode(); + } + catch (AssertionError e) { + return null; // masquerade parser errors + } + } +} \ No newline at end of file diff --git a/java/java-impl/src/com/intellij/psi/impl/source/tree/JavaElementType.java b/java/java-impl/src/com/intellij/psi/impl/source/tree/JavaElementType.java index 0af5952b0e1a..6fb19b8624c9 100644 --- a/java/java-impl/src/com/intellij/psi/impl/source/tree/JavaElementType.java +++ b/java/java-impl/src/com/intellij/psi/impl/source/tree/JavaElementType.java @@ -28,6 +28,7 @@ import com.intellij.pom.java.LanguageLevel; import com.intellij.psi.JavaTokenType; import com.intellij.psi.PsiManager; import com.intellij.psi.impl.java.stubs.JavaStubElementTypes; +import com.intellij.psi.impl.source.JavaDummyElement; import com.intellij.psi.impl.source.parsing.JavaParsingContext; import com.intellij.psi.impl.source.parsing.Parsing; import com.intellij.psi.impl.source.tree.java.PsiCodeBlockImpl; @@ -40,6 +41,7 @@ import com.intellij.psi.tree.java.IJavaElementType; import com.intellij.psi.util.PsiUtil; import com.intellij.util.CharTable; import com.intellij.util.diff.FlyweightCapableTreeStructure; +import org.jetbrains.annotations.Nullable; import static com.intellij.lang.PsiBuilderUtil.expect; @@ -158,6 +160,7 @@ public interface JavaElementType { seq, 0, seq.length(), 0).getFirstChildNode(); } + @Override public int getErrorsCount(final CharSequence seq, final Project project) { final Lexer lexer = new JavaLexer(LanguageLevel.HIGHEST); @@ -184,6 +187,7 @@ public interface JavaElementType { class ICodeBlockNewElementType extends ICodeBlockElementType implements ILightLazyParseableElementType { private ICodeBlockNewElementType() { } + @Override public FlyweightCapableTreeStructure parseContents(final LighterLazyParseableNode chameleon) { final PsiBuilder builder = JavaParserUtil.createBuilder(chameleon); StatementParser.parseCodeBlockDeep(builder, true); @@ -194,6 +198,8 @@ public interface JavaElementType { ILazyParseableElementType CODE_BLOCK = JavaParserDefinition.USE_NEW_PARSER ? new ICodeBlockNewElementType() : new ICodeBlockElementType(); IElementType STATEMENTS = new ICodeFragmentElementType("STATEMENTS", StdLanguages.JAVA) { + @Nullable + @Override public ASTNode parseContents(final ASTNode chameleon) { if (JavaParserDefinition.USE_NEW_PARSER) { return JavaParserUtil.parseFragment(chameleon, @@ -213,6 +219,8 @@ public interface JavaElementType { }; IElementType EXPRESSION_TEXT = new ICodeFragmentElementType("EXPRESSION_TEXT", StdLanguages.JAVA) { + @Nullable + @Override public ASTNode parseContents(final ASTNode chameleon) { if (JavaParserDefinition.USE_NEW_PARSER) { return JavaParserUtil.parseFragment(chameleon, @@ -231,6 +239,8 @@ public interface JavaElementType { }; IElementType REFERENCE_TEXT = new ICodeFragmentElementType("REFERENCE_TEXT", StdLanguages.JAVA) { + @Nullable + @Override public ASTNode parseContents(final ASTNode chameleon) { if (JavaParserDefinition.USE_NEW_PARSER) { return JavaParserUtil.parseFragment(chameleon, @@ -248,6 +258,8 @@ public interface JavaElementType { }; IElementType TYPE_TEXT = new ICodeFragmentElementType("TYPE_TEXT", StdLanguages.JAVA) { + @Nullable + @Override public ASTNode parseContents(final ASTNode chameleon) { if (JavaParserDefinition.USE_NEW_PARSER) { return JavaParserUtil.parseFragment(chameleon, @@ -264,4 +276,14 @@ public interface JavaElementType { SharedImplUtil.findCharTableByTree(chameleon)); } }; + + IElementType DUMMY_ELEMENT = new ILazyParseableElementType("DUMMY_ELEMENT", StdLanguages.JAVA) { + @Nullable + @Override + public ASTNode parseContents(final ASTNode chameleon) { + assert chameleon instanceof JavaDummyElement : chameleon; + final JavaDummyElement dummyElement = (JavaDummyElement)chameleon; + return JavaParserUtil.parseFragment(chameleon, dummyElement.getParser(), dummyElement.consumeAll(), dummyElement.getLanguageLevel()); + } + }; } diff --git a/platform/lang-impl/src/com/intellij/psi/impl/source/DummyHolder.java b/platform/lang-impl/src/com/intellij/psi/impl/source/DummyHolder.java index b6009113df3c..f6d4d1e28b54 100644 --- a/platform/lang-impl/src/com/intellij/psi/impl/source/DummyHolder.java +++ b/platform/lang-impl/src/com/intellij/psi/impl/source/DummyHolder.java @@ -56,7 +56,12 @@ public class DummyHolder extends PsiFileImpl { ((DummyHolderViewProvider)getViewProvider()).setDummyHolder(this); myContext = context; myTable = table != null ? table : IdentityCharTable.INSTANCE; - if(contentElement != null) { + if (contentElement instanceof FileElement) { + myFileElement = (FileElement)contentElement; + myFileElement.setPsi(this); + if (myTable != null) myFileElement.setCharTable(myTable); + } + else if (contentElement != null) { getTreeElement().rawAddChildren(contentElement); clearCaches(); } @@ -81,7 +86,7 @@ public class DummyHolder extends PsiFileImpl { } public boolean isValid() { - if(myExplicitlyValid != null) return myExplicitlyValid.booleanValue(); + if (myExplicitlyValid != null) return myExplicitlyValid.booleanValue(); return super.isValid() && !(myContext != null && !myContext.isValid()); } @@ -112,10 +117,10 @@ public class DummyHolder extends PsiFileImpl { } public FileElement getTreeElementNoLock() { - if(myFileElement == null){ + if (myFileElement == null) { myFileElement = new FileElement(TokenType.DUMMY_HOLDER, null); myFileElement.setPsi(this); - if(myTable != null) myFileElement.setCharTable(myTable); + if (myTable != null) myFileElement.setCharTable(myTable); clearCaches(); } return myFileElement; From c40d41aa098b1407107cc947067f9f823dadf4af Mon Sep 17 00:00:00 2001 From: Roman Shevchenko Date: Wed, 15 Dec 2010 18:47:18 +0300 Subject: [PATCH 42/54] PsiElementFactory and PsiJavaParserFacade updated to use new parser --- .../lang/java/parser/DeclarationParser.java | 2 +- .../lang/java/parser/ReferenceParser.java | 2 +- .../lang/java/parser/StatementParser.java | 5 +- .../psi/impl/PsiElementFactoryImpl.java | 576 ++++++++---------- .../psi/impl/PsiJavaParserFacadeImpl.java | 381 +++++++----- .../com/intellij/psi/PsiElementFactory.java | 13 +- .../com/intellij/psi/PsiJavaParserFacade.java | 38 +- 7 files changed, 509 insertions(+), 508 deletions(-) diff --git a/java/java-impl/src/com/intellij/lang/java/parser/DeclarationParser.java b/java/java-impl/src/com/intellij/lang/java/parser/DeclarationParser.java index d1d91be0ee21..2c01a1babfe2 100644 --- a/java/java-impl/src/com/intellij/lang/java/parser/DeclarationParser.java +++ b/java/java-impl/src/com/intellij/lang/java/parser/DeclarationParser.java @@ -146,7 +146,7 @@ public class DeclarationParser { } @Nullable - private static PsiBuilder.Marker parseEnumConstant(final PsiBuilder builder) { + public static PsiBuilder.Marker parseEnumConstant(final PsiBuilder builder) { final PsiBuilder.Marker constant = builder.mark(); parseModifierList(builder); diff --git a/java/java-impl/src/com/intellij/lang/java/parser/ReferenceParser.java b/java/java-impl/src/com/intellij/lang/java/parser/ReferenceParser.java index e6cfac8b80a2..1d25b4b7841f 100644 --- a/java/java-impl/src/com/intellij/lang/java/parser/ReferenceParser.java +++ b/java/java-impl/src/com/intellij/lang/java/parser/ReferenceParser.java @@ -311,7 +311,7 @@ public class ReferenceParser { } @Nullable - private static PsiBuilder.Marker parseTypeParameter(final PsiBuilder builder) { + public static PsiBuilder.Marker parseTypeParameter(final PsiBuilder builder) { final PsiBuilder.Marker param = builder.mark(); DeclarationParser.parseAnnotations(builder); diff --git a/java/java-impl/src/com/intellij/lang/java/parser/StatementParser.java b/java/java-impl/src/com/intellij/lang/java/parser/StatementParser.java index 561e249289cb..42c861dc6cfa 100644 --- a/java/java-impl/src/com/intellij/lang/java/parser/StatementParser.java +++ b/java/java-impl/src/com/intellij/lang/java/parser/StatementParser.java @@ -165,7 +165,7 @@ public class StatementParser { } @Nullable - private static PsiBuilder.Marker parseStatement(final PsiBuilder builder) { + public static PsiBuilder.Marker parseStatement(final PsiBuilder builder) { final IElementType tokenType = builder.getTokenType(); // todo: custom parsers (?) @@ -637,7 +637,8 @@ public class StatementParser { return statement; } - private static boolean parseCatchBlock(final PsiBuilder builder) { + public static boolean parseCatchBlock(final PsiBuilder builder) { + assert builder.getTokenType() == JavaTokenType.CATCH_KEYWORD : builder.getTokenType(); final PsiBuilder.Marker section = builder.mark(); builder.advanceLexer(); diff --git a/java/java-impl/src/com/intellij/psi/impl/PsiElementFactoryImpl.java b/java/java-impl/src/com/intellij/psi/impl/PsiElementFactoryImpl.java index 4a4c8a7620ba..e048f84772b8 100644 --- a/java/java-impl/src/com/intellij/psi/impl/PsiElementFactoryImpl.java +++ b/java/java-impl/src/com/intellij/psi/impl/PsiElementFactoryImpl.java @@ -17,7 +17,6 @@ package com.intellij.psi.impl; import com.intellij.lang.*; import com.intellij.lexer.Lexer; -import com.intellij.openapi.diagnostic.Logger; import com.intellij.openapi.project.Project; import com.intellij.pom.java.LanguageLevel; import com.intellij.psi.*; @@ -27,12 +26,15 @@ import com.intellij.psi.codeStyle.JavaCodeStyleManager; import com.intellij.psi.impl.light.*; import com.intellij.psi.impl.source.*; import com.intellij.psi.impl.source.codeStyle.CodeEditUtil; -import com.intellij.psi.impl.source.tree.*; +import com.intellij.psi.impl.source.tree.FileElement; +import com.intellij.psi.impl.source.tree.JavaElementType; +import com.intellij.psi.impl.source.tree.TreeElement; import com.intellij.psi.javadoc.PsiDocTag; import com.intellij.psi.search.GlobalSearchScope; import com.intellij.psi.tree.IElementType; import com.intellij.psi.util.PsiUtil; import com.intellij.util.IncorrectOperationException; +import com.intellij.util.StringBuilderSpinAllocator; import com.intellij.util.containers.HashMap; import org.jetbrains.annotations.NonNls; import org.jetbrains.annotations.NotNull; @@ -41,30 +43,14 @@ import org.jetbrains.annotations.Nullable; import java.util.Collections; import java.util.Map; +import static com.intellij.openapi.util.text.StringUtil.join; + public class PsiElementFactoryImpl extends PsiJavaParserFacadeImpl implements PsiElementFactory { - private static final Logger LOG = Logger.getInstance("#com.intellij.psi.impl.PsiElementFactoryImpl"); + private PsiClass myArrayClass; + private PsiClass myArrayClass15; + private PsiJavaFile myDummyJavaFile; - private PsiClass ARRAY_CLASS; - private PsiClass ARRAY_CLASS15; - - static { - initPrimitiveTypes(); - } - - private static void initPrimitiveTypes() { - ourPrimitiveTypesMap.put(PsiType.BYTE.getCanonicalText(), (PsiPrimitiveType)PsiType.BYTE); - ourPrimitiveTypesMap.put(PsiType.CHAR.getCanonicalText(), (PsiPrimitiveType)PsiType.CHAR); - ourPrimitiveTypesMap.put(PsiType.DOUBLE.getCanonicalText(), (PsiPrimitiveType)PsiType.DOUBLE); - ourPrimitiveTypesMap.put(PsiType.FLOAT.getCanonicalText(), (PsiPrimitiveType)PsiType.FLOAT); - ourPrimitiveTypesMap.put(PsiType.INT.getCanonicalText(), (PsiPrimitiveType)PsiType.INT); - ourPrimitiveTypesMap.put(PsiType.LONG.getCanonicalText(), (PsiPrimitiveType)PsiType.LONG); - ourPrimitiveTypesMap.put(PsiType.SHORT.getCanonicalText(), (PsiPrimitiveType)PsiType.SHORT); - ourPrimitiveTypesMap.put(PsiType.BOOLEAN.getCanonicalText(), (PsiPrimitiveType)PsiType.BOOLEAN); - ourPrimitiveTypesMap.put(PsiType.VOID.getCanonicalText(), (PsiPrimitiveType)PsiType.VOID); - ourPrimitiveTypesMap.put(PsiType.NULL.getCanonicalText(), (PsiPrimitiveType)PsiType.NULL); - } - - public PsiElementFactoryImpl(PsiManagerEx manager) { + public PsiElementFactoryImpl(final PsiManagerEx manager) { super(manager); } @@ -77,32 +63,29 @@ public class PsiElementFactoryImpl extends PsiJavaParserFacadeImpl implements Ps } @NotNull - public PsiClass getArrayClass(@NotNull LanguageLevel languageLevel) { - try { - if (languageLevel.compareTo(LanguageLevel.JDK_1_5) < 0) { - if (ARRAY_CLASS == null) { - ARRAY_CLASS = createClassFromText("public class __Array__{\n public final int length; \n public Object clone(){}\n}", null).getInnerClasses()[0]; - } - return ARRAY_CLASS; - } - else { - if (ARRAY_CLASS15 == null) { - ARRAY_CLASS15 = createClassFromText("public class __Array__{\n public final int length; \n public T[] clone(){}\n}", null).getInnerClasses()[0]; - } - return ARRAY_CLASS15; + public PsiClass getArrayClass(@NotNull final LanguageLevel languageLevel) { + if (!languageLevel.isAtLeast(LanguageLevel.JDK_1_5)) { + if (myArrayClass == null) { + final String body = "public class __Array__{\n public final int length;\n public Object clone() {}\n}"; + myArrayClass = createClassFromText(body, null).getInnerClasses()[0]; } + return myArrayClass; } - catch (IncorrectOperationException e) { - LOG.error(e); - return null; + else { + if (myArrayClass15 == null) { + final String body = "public class __Array__{\n public final int length;\n public T[] clone() {}\n}"; + myArrayClass15 = createClassFromText(body, null).getInnerClasses()[0]; + } + return myArrayClass15; } } @NotNull - public PsiClassType getArrayClassType(@NotNull PsiType componentType, @NotNull final LanguageLevel languageLevel) { - PsiClass arrayClass = getArrayClass(languageLevel); + public PsiClassType getArrayClassType(@NotNull final PsiType componentType, @NotNull final LanguageLevel languageLevel) { + final PsiClass arrayClass = getArrayClass(languageLevel); + final PsiTypeParameter[] typeParameters = arrayClass.getTypeParameters(); + PsiSubstitutor substitutor = PsiSubstitutor.EMPTY; - PsiTypeParameter[] typeParameters = arrayClass.getTypeParameters(); if (typeParameters.length == 1) { substitutor = substitutor.put(typeParameters[0], componentType); } @@ -111,305 +94,227 @@ public class PsiElementFactoryImpl extends PsiJavaParserFacadeImpl implements Ps } @NotNull - public PsiClassType createType(@NotNull PsiClass resolve, @NotNull PsiSubstitutor substitutor) { + public PsiClassType createType(@NotNull final PsiClass resolve, @NotNull final PsiSubstitutor substitutor) { return new PsiImmediateClassType(resolve, substitutor); } @NotNull - public PsiClassType createType(@NotNull PsiClass resolve, @NotNull PsiSubstitutor substitutor, @NotNull LanguageLevel languageLevel) { + public PsiClassType createType(@NotNull final PsiClass resolve, + @NotNull final PsiSubstitutor substitutor, + @NotNull final LanguageLevel languageLevel) { return new PsiImmediateClassType(resolve, substitutor, languageLevel); } @NotNull - public PsiClassType createType(@NotNull PsiClass resolve, - @NotNull PsiSubstitutor substitutor, - @NotNull LanguageLevel languageLevel, - @NotNull PsiAnnotation[] annotations) { + public PsiClassType createType(@NotNull final PsiClass resolve, + @NotNull final PsiSubstitutor substitutor, + @NotNull final LanguageLevel languageLevel, + @NotNull final PsiAnnotation[] annotations) { return new PsiImmediateClassType(resolve, substitutor, languageLevel, annotations); } @NotNull - public PsiClass createClass(@NotNull String name) throws IncorrectOperationException { - PsiUtil.checkIsIdentifier(myManager, name); - @NonNls String text = "public class " + name + "{ }"; - PsiJavaFile aFile = createDummyJavaFile(text); - PsiClass[] classes = aFile.getClasses(); - if (classes.length != 1) { - throw new IncorrectOperationException(); - } - return classes[0]; + public PsiClass createClass(@NotNull final String name) throws IncorrectOperationException { + return createClassInner("class", name); } @NotNull - public PsiClass createInterface(@NotNull String name) throws IncorrectOperationException { - PsiUtil.checkIsIdentifier(myManager, name); - @NonNls String text = "public interface " + name + "{ }"; - PsiJavaFile aFile = createDummyJavaFile(text); - PsiClass[] classes = aFile.getClasses(); - if (classes.length != 1) { - throw new IncorrectOperationException(); - } - return classes[0]; + public PsiClass createInterface(@NotNull final String name) throws IncorrectOperationException { + return createClassInner("interface", name); } + @NotNull public PsiClass createEnum(@NotNull final String name) throws IncorrectOperationException { + return createClassInner("enum", name); + } + + private PsiClass createClassInner(final String type, final String name) { PsiUtil.checkIsIdentifier(myManager, name); - @NonNls String text = "public enum " + name + "{ }"; - PsiJavaFile aFile = createDummyJavaFile(text); - PsiClass[] classes = aFile.getClasses(); + final PsiJavaFile aFile = createDummyJavaFile(join("public ", type, " ", name, " { }")); + final PsiClass[] classes = aFile.getClasses(); if (classes.length != 1) { - throw new IncorrectOperationException(); + throw new IncorrectOperationException("Incorrect " + type + " name \"" + name + "\"."); } return classes[0]; } @NotNull - public PsiTypeElement createTypeElement(@NotNull PsiType psiType) { + public PsiTypeElement createTypeElement(@NotNull final PsiType psiType) { final LightTypeElement element = new LightTypeElement(myManager, psiType); CodeEditUtil.setNodeGenerated(element.getNode(), true); return element; } @NotNull - public PsiJavaCodeReferenceElement createReferenceElementByType(@NotNull PsiClassType type) { + public PsiJavaCodeReferenceElement createReferenceElementByType(@NotNull final PsiClassType type) { if (type instanceof PsiClassReferenceType) { return ((PsiClassReferenceType)type).getReference(); } final PsiClassType.ClassResolveResult resolveResult = type.resolveGenerics(); - return new LightClassReference(myManager, type.getPresentableText(), resolveResult.getElement(), resolveResult.getSubstitutor()); + final PsiClass refClass = resolveResult.getElement(); + assert refClass != null : type; + return new LightClassReference(myManager, type.getPresentableText(), refClass, resolveResult.getSubstitutor()); } @NotNull - public PsiField createField(@NotNull String name, @NotNull PsiType type) throws IncorrectOperationException { + public PsiField createField(@NotNull final String name, @NotNull final PsiType type) throws IncorrectOperationException { PsiUtil.checkIsIdentifier(myManager, name); if (PsiType.NULL.equals(type)) { - throw new IncorrectOperationException("Cannot create field with type \"\"."); + throw new IncorrectOperationException("Cannot create field with type \"null\"."); } - TreeElement typeCopy = ChangeUtil.copyToElement(createTypeElement(type)); - typeCopy.acceptTree(new GeneratedMarkerVisitor()); - @NonNls String text = "class _Dummy_ {private int " + name + ";}"; - PsiJavaFile aFile = createDummyJavaFile(text); - PsiClass aClass = aFile.getClasses()[0]; - PsiField field = aClass.getFields()[0]; - SourceTreeToPsiMap.psiElementToTree(field).replaceChild(SourceTreeToPsiMap.psiElementToTree(field.getTypeElement()), typeCopy); - ChangeUtil.decodeInformation((TreeElement)SourceTreeToPsiMap.psiElementToTree(field)); + + final PsiJavaFile aFile = createDummyJavaFile(join("class _Dummy_ { private ", type.getCanonicalText(), " ", name, "; }")); + final PsiField field = aFile.getClasses()[0].getFields()[0]; + JavaCodeStyleManager.getInstance(myManager.getProject()).shortenClassReferences(field); return (PsiField)CodeStyleManager.getInstance(myManager.getProject()).reformat(field); } @NotNull - public PsiMethod createMethod(@NotNull String name, PsiType returnType) throws IncorrectOperationException { + public PsiMethod createMethod(@NotNull final String name, final PsiType returnType) throws IncorrectOperationException { PsiUtil.checkIsIdentifier(myManager, name); if (PsiType.NULL.equals(returnType)) { - throw new IncorrectOperationException("Cannot create field with type \"\"."); + throw new IncorrectOperationException("Cannot create method with type \"null\"."); } - @NonNls String text = "class _Dummy_ {\n public " + returnType.getCanonicalText() + " " + name + "(){}\n}"; - PsiJavaFile aFile = createDummyJavaFile(text); - PsiClass aClass = aFile.getClasses()[0]; - PsiMethod method = aClass.getMethods()[0]; + + final PsiJavaFile aFile = createDummyJavaFile(join("class _Dummy_ { public " + returnType.getCanonicalText(), " ", name, "() {} }")); + final PsiMethod method = aFile.getClasses()[0].getMethods()[0]; JavaCodeStyleManager.getInstance(myManager.getProject()).shortenClassReferences(method); return (PsiMethod)CodeStyleManager.getInstance(myManager.getProject()).reformat(method); } @NotNull public PsiMethod createConstructor() { - try { - @NonNls String text = "class _Dummy_ {\n public _Dummy_(){}\n}"; - PsiJavaFile aFile = createDummyJavaFile(text); - PsiClass aClass = aFile.getClasses()[0]; - PsiMethod method = aClass.getMethods()[0]; - return (PsiMethod)CodeStyleManager.getInstance(myManager.getProject()).reformat(method); - } - catch (IncorrectOperationException e) { - LOG.assertTrue(false); - return null; - } + final PsiJavaFile aFile = createDummyJavaFile("class _Dummy_ { public _Dummy_() {} }"); + final PsiMethod method = aFile.getClasses()[0].getMethods()[0]; + return (PsiMethod)CodeStyleManager.getInstance(myManager.getProject()).reformat(method); } @NotNull public PsiClassInitializer createClassInitializer() throws IncorrectOperationException { - @NonNls String text = "class _Dummy_ { {} }"; - final PsiJavaFile aFile = createDummyJavaFile(text); - final PsiClass aClass = aFile.getClasses()[0]; - final PsiClassInitializer psiClassInitializer = aClass.getInitializers()[0]; - return (PsiClassInitializer)CodeStyleManager.getInstance(myManager.getProject()).reformat(psiClassInitializer); + final PsiJavaFile aFile = createDummyJavaFile("class _Dummy_ { {} }"); + final PsiClassInitializer classInitializer = aFile.getClasses()[0].getInitializers()[0]; + return (PsiClassInitializer)CodeStyleManager.getInstance(myManager.getProject()).reformat(classInitializer); } @NotNull - public PsiParameter createParameter(@NotNull String name, @NotNull PsiType type) throws IncorrectOperationException { + public PsiParameter createParameter(@NotNull final String name, @NotNull final PsiType type) throws IncorrectOperationException { PsiUtil.checkIsIdentifier(myManager, name); if (PsiType.NULL.equals(type)) { - throw new IncorrectOperationException("Cannot create field with type \"\"."); + throw new IncorrectOperationException("Cannot create parameter with type \"null\"."); } - final FileElement treeHolder = DummyHolderFactory.createHolder(myManager, null).getTreeElement(); - final String text = type.getCanonicalText() + " " + name; - final CompositeElement treeElement = getJavaParsingContext(treeHolder).getDeclarationParsing().parseParameterText(text); - if (treeElement == null) { - throw new AssertionError("Null element for text = " + text); - } - treeHolder.rawAddChildren(treeElement); - CodeStyleManager codeStyleManager = CodeStyleManager.getInstance(myManager.getProject()); - PsiParameter parameter = (PsiParameter)SourceTreeToPsiMap.treeElementToPsi(treeElement); - PsiUtil.setModifierProperty(parameter, PsiModifier.FINAL, CodeStyleSettingsManager.getSettings(myManager.getProject()).GENERATE_FINAL_PARAMETERS); - treeElement.acceptTree(new GeneratedMarkerVisitor()); + final String text = join(type.getCanonicalText() + " " + name); + final PsiParameter parameter = createParameterFromText(text, null); + final CodeStyleManager codeStyleManager = CodeStyleManager.getInstance(myManager.getProject()); + PsiUtil.setModifierProperty(parameter, PsiModifier.FINAL, + CodeStyleSettingsManager.getSettings(myManager.getProject()).GENERATE_FINAL_PARAMETERS); + markGenerated(parameter); JavaCodeStyleManager.getInstance(myManager.getProject()).shortenClassReferences(parameter); return (PsiParameter)codeStyleManager.reformat(parameter); } @NotNull public PsiCodeBlock createCodeBlock() { - try { - PsiCodeBlock block = createCodeBlockFromText("{}", null); - return (PsiCodeBlock)CodeStyleManager.getInstance(myManager.getProject()).reformat(block); - } - catch (IncorrectOperationException e) { - LOG.error(e); - return null; - } + final PsiCodeBlock block = createCodeBlockFromText("{}", null); + return (PsiCodeBlock)CodeStyleManager.getInstance(myManager.getProject()).reformat(block); } @NotNull - public PsiClassType createType(@NotNull PsiClass aClass) { + public PsiClassType createType(@NotNull final PsiClass aClass) { return new PsiImmediateClassType(aClass, aClass instanceof PsiTypeParameter ? PsiSubstitutor.EMPTY : createRawSubstitutor(aClass)); } @NotNull - public PsiClassType createType(@NotNull PsiJavaCodeReferenceElement classReference) { + public PsiClassType createType(@NotNull final PsiJavaCodeReferenceElement classReference) { return new PsiClassReferenceType(classReference, null); } @NotNull - public PsiClassType createType(@NotNull PsiClass aClass, PsiType parameter) { - PsiTypeParameter[] typeParameters = aClass.getTypeParameters(); - assert typeParameters.length == 1; - - Map map = Collections.singletonMap(typeParameters[0], parameter); + public PsiClassType createType(@NotNull final PsiClass aClass, final PsiType parameter) { + final PsiTypeParameter[] typeParameters = aClass.getTypeParameters(); + assert typeParameters.length == 1 : aClass; + final Map map = Collections.singletonMap(typeParameters[0], parameter); return createType(aClass, createSubstitutor(map)); } @NotNull - public PsiClassType createType(@NotNull PsiClass aClass, PsiType... parameters) { - PsiTypeParameter[] typeParameters = aClass.getTypeParameters(); + public PsiClassType createType(@NotNull final PsiClass aClass, final PsiType... parameters) { + final PsiTypeParameter[] typeParameters = aClass.getTypeParameters(); assert parameters.length == typeParameters.length; - Map map = new java.util.HashMap(); + final Map map = new java.util.HashMap(); for (int i = 0; i < parameters.length; i++) { map.put(typeParameters[i], parameters[i]); } - return createType(aClass, createSubstitutor(map)); } - private static class TypeDetacher extends PsiTypeVisitor { - public static final TypeDetacher INSTANCE = new TypeDetacher(); - - public PsiType visitType(PsiType type) { - return type; - } - - public PsiType visitWildcardType(PsiWildcardType wildcardType) { - final PsiType bound = wildcardType.getBound(); - if (bound == null) { - return wildcardType; - } - else { - return PsiWildcardType.changeBound(wildcardType, bound.accept(this)); - } - } - - public PsiType visitArrayType(PsiArrayType arrayType) { - final PsiType componentType = arrayType.getComponentType(); - final PsiType detachedComponentType = componentType.accept(this); - if (detachedComponentType == componentType) return arrayType; // optimization - return detachedComponentType.createArrayType(); - } - - public PsiType visitClassType(PsiClassType classType) { - final PsiClassType.ClassResolveResult resolveResult = classType.resolveGenerics(); - final PsiClass aClass = resolveResult.getElement(); - if (aClass == null) return classType; - final HashMap map = new HashMap(); - for (PsiTypeParameter parameter : PsiUtil.typeParametersIterable(aClass)) { - PsiType type = resolveResult.getSubstitutor().substitute(parameter); - if (type != null) { - type = type.accept(this); - } - map.put(parameter, type); - } - return new PsiImmediateClassType(aClass, PsiSubstitutorImpl.createSubstitutor(map)); - } - } - - @NotNull - public PsiType detachType(@NotNull PsiType type) { - return type.accept(TypeDetacher.INSTANCE); + public PsiType detachType(@NotNull final PsiType type) { + return type; } @NotNull - public PsiSubstitutor createRawSubstitutor(@NotNull PsiTypeParameterListOwner owner) { - Map substMap = null; + public PsiSubstitutor createRawSubstitutor(@NotNull final PsiTypeParameterListOwner owner) { + Map substitutorMap = null; for (PsiTypeParameter parameter : PsiUtil.typeParametersIterable(owner)) { - if (substMap == null) substMap = new HashMap(); - substMap.put(parameter, null); + if (substitutorMap == null) substitutorMap = new HashMap(); + substitutorMap.put(parameter, null); } - return PsiSubstitutorImpl.createSubstitutor(substMap); - } - @NotNull - public PsiSubstitutor createRawSubstitutor(@NotNull PsiSubstitutor baseSubstitutor, @NotNull PsiTypeParameter[] typeParameters) { - Map substMap = null; - for (PsiTypeParameter parameter : typeParameters) { - if (substMap == null) substMap = new HashMap(); - substMap.put(parameter, null); - } - return baseSubstitutor.putAll(PsiSubstitutorImpl.createSubstitutor(substMap)); + return PsiSubstitutorImpl.createSubstitutor(substitutorMap); } @NotNull - public PsiElement createDummyHolder(@NotNull String text, @NotNull IElementType type, @Nullable PsiElement context) { + public PsiSubstitutor createRawSubstitutor(@NotNull final PsiSubstitutor baseSubstitutor, @NotNull final PsiTypeParameter[] typeParameters) { + Map substitutorMap = null; + for (PsiTypeParameter parameter : typeParameters) { + if (substitutorMap == null) substitutorMap = new HashMap(); + substitutorMap.put(parameter, null); + } + return baseSubstitutor.putAll(PsiSubstitutorImpl.createSubstitutor(substitutorMap)); + } + + @NotNull + public PsiElement createDummyHolder(@NotNull final String text, @NotNull final IElementType type, @Nullable final PsiElement context) { final DummyHolder result = DummyHolderFactory.createHolder(myManager, context); final FileElement holder = result.getTreeElement(); final Language language = type.getLanguage(); final ParserDefinition parserDefinition = LanguageParserDefinitions.INSTANCE.forLanguage(language); - if (parserDefinition == null) { - throw new AssertionError("No parser definition for language " + language); - } + assert parserDefinition != null : "No parser definition for language " + language; final Project project = myManager.getProject(); final Lexer lexer = parserDefinition.createLexer(project); final PsiBuilder builder = PsiBuilderFactory.getInstance().createBuilder(project, holder, lexer, language, text); final ASTNode node = parserDefinition.createParser(project).parse(type, builder); holder.rawAddChildren((TreeElement)node); - return node.getPsi(); + final PsiElement psi = node.getPsi(); + assert psi != null : text; + return psi; } @NotNull - public PsiSubstitutor createSubstitutor(@NotNull Map map) { + public PsiSubstitutor createSubstitutor(@NotNull final Map map) { return PsiSubstitutorImpl.createSubstitutor(map); } @Nullable - public PsiPrimitiveType createPrimitiveType(@NotNull String text) { - return getPrimitiveType(text); - } - - public static PsiPrimitiveType getPrimitiveType(final String text) { - return ourPrimitiveTypesMap.get(text); + public PsiPrimitiveType createPrimitiveType(@NotNull final String text) { + return PsiJavaParserFacadeImpl.getPrimitiveType(text); } @NotNull - public PsiClassType createTypeByFQClassName(@NotNull String qName) { + public PsiClassType createTypeByFQClassName(@NotNull final String qName) { return createTypeByFQClassName(qName, GlobalSearchScope.allScope(myManager.getProject())); } @NotNull - public PsiClassType createTypeByFQClassName(@NotNull String qName, @NotNull GlobalSearchScope resolveScope) { + public PsiClassType createTypeByFQClassName(@NotNull final String qName, @NotNull final GlobalSearchScope resolveScope) { return new PsiClassReferenceType(createReferenceElementByFQClassName(qName, resolveScope), null); } @NotNull - public PsiJavaCodeReferenceElement createClassReferenceElement(@NotNull PsiClass aClass) { + public PsiJavaCodeReferenceElement createClassReferenceElement(@NotNull final PsiClass aClass) { final String text; if (aClass instanceof PsiAnonymousClass) { text = ((PsiAnonymousClass)aClass).getBaseClassType().getPresentableText(); @@ -421,19 +326,20 @@ public class PsiElementFactoryImpl extends PsiJavaParserFacadeImpl implements Ps } @NotNull - public PsiJavaCodeReferenceElement createReferenceElementByFQClassName(@NotNull String qName, @NotNull GlobalSearchScope resolveScope) { - String shortName = PsiNameHelper.getShortClassName(qName); + public PsiJavaCodeReferenceElement createReferenceElementByFQClassName(@NotNull final String qName, + @NotNull final GlobalSearchScope resolveScope) { + final String shortName = PsiNameHelper.getShortClassName(qName); return new LightClassReference(myManager, shortName, qName, resolveScope); } @NotNull - public PsiJavaCodeReferenceElement createFQClassNameReferenceElement(@NotNull String qName, @NotNull GlobalSearchScope resolveScope) { + public PsiJavaCodeReferenceElement createFQClassNameReferenceElement(@NotNull final String qName, + @NotNull final GlobalSearchScope resolveScope) { return new LightClassReference(myManager, qName, qName, resolveScope); } @NotNull - public PsiJavaCodeReferenceElement createPackageReferenceElement(@NotNull PsiPackage aPackage) - throws IncorrectOperationException { + public PsiJavaCodeReferenceElement createPackageReferenceElement(@NotNull final PsiPackage aPackage) throws IncorrectOperationException { if (aPackage.getQualifiedName().length() == 0) { throw new IncorrectOperationException("Cannot create reference to default package."); } @@ -441,18 +347,20 @@ public class PsiElementFactoryImpl extends PsiJavaParserFacadeImpl implements Ps } @NotNull - public PsiPackageStatement createPackageStatement(@NotNull String name) throws IncorrectOperationException { - final PsiJavaFile javaFile = (PsiJavaFile)PsiFileFactory.getInstance(myManager.getProject()).createFileFromText("dummy.java", "package " + name + ";"); - final PsiPackageStatement stmt = javaFile.getPackageStatement(); - if (stmt == null) throw new IncorrectOperationException("Incorrect package name: " + name); + public PsiPackageStatement createPackageStatement(@NotNull final String name) throws IncorrectOperationException { + final PsiJavaFile aFile = createDummyJavaFile(join("package ", name, ";")); + final PsiPackageStatement stmt = aFile.getPackageStatement(); + if (stmt == null) { + throw new IncorrectOperationException("Incorrect package name: " + name); + } return stmt; } @NotNull - public PsiJavaCodeReferenceCodeFragment createReferenceCodeFragment(@NotNull String text, - PsiElement context, - boolean isPhysical, - boolean isClassesAccepted) { + public PsiJavaCodeReferenceCodeFragment createReferenceCodeFragment(@NotNull final String text, + final PsiElement context, + final boolean isPhysical, + final boolean isClassesAccepted) { final PsiJavaCodeReferenceCodeFragmentImpl result = new PsiJavaCodeReferenceCodeFragmentImpl(myManager.getProject(), isPhysical, "fragment.java", text, isClassesAccepted); result.setContext(context); @@ -460,51 +368,54 @@ public class PsiElementFactoryImpl extends PsiJavaParserFacadeImpl implements Ps } @NotNull - public PsiImportStaticStatement createImportStaticStatement(@NotNull PsiClass aClass, @NotNull String memberName) throws IncorrectOperationException { + public PsiImportStaticStatement createImportStaticStatement(@NotNull final PsiClass aClass, + @NotNull final String memberName) throws IncorrectOperationException { if (aClass instanceof PsiAnonymousClass) { throw new IncorrectOperationException("Cannot create import statement for anonymous class."); } else if (aClass.getParent() instanceof PsiDeclarationStatement) { throw new IncorrectOperationException("Cannot create import statement for local class."); } - @NonNls String text = "import static " + aClass.getQualifiedName() + "." + memberName + ";"; - PsiJavaFile aFile = createDummyJavaFile(text); - PsiImportStaticStatement statement = aFile.getImportList().getImportStaticStatements()[0]; + + final PsiJavaFile aFile = createDummyJavaFile(join("import static ", aClass.getQualifiedName(), ".", memberName, ";")); + final PsiImportStatementBase statement = extractImport(aFile, true); return (PsiImportStaticStatement)CodeStyleManager.getInstance(myManager.getProject()).reformat(statement); } @NotNull - public PsiParameterList createParameterList(@NotNull String[] names, @NotNull PsiType[] types) throws IncorrectOperationException { - @NonNls String text = "void method("; - String sep = ""; - for (int i = 0; i < names.length; i++) { - final String name = names[i]; - PsiType type = types[i]; - text += sep + type.getCanonicalText() + " " + name; - sep = ","; + public PsiParameterList createParameterList(@NotNull final String[] names, @NotNull final PsiType[] types) throws IncorrectOperationException { + final StringBuilder builder = StringBuilderSpinAllocator.alloc(); + try { + builder.append("void method("); + for (int i = 0; i < names.length; i++) { + if (i > 0) builder.append(", "); + builder.append(types[i].getCanonicalText()).append(' ').append(names[i]); + } + return createMethodFromText(builder.toString(), null).getParameterList(); + } + finally { + StringBuilderSpinAllocator.dispose(builder); } - text += "){}"; - PsiMethod method = createMethodFromText(text, null); - return method.getParameterList(); } @NotNull - public PsiReferenceList createReferenceList(@NotNull PsiJavaCodeReferenceElement[] references) throws IncorrectOperationException { - @NonNls String text = "void method() "; - if (references.length > 0) text += "throws "; - String sep = ""; - for (final PsiJavaCodeReferenceElement reference : references) { - text += sep + reference.getCanonicalText(); - sep = ","; + public PsiReferenceList createReferenceList(@NotNull final PsiJavaCodeReferenceElement[] references) throws IncorrectOperationException { + final StringBuilder builder = StringBuilderSpinAllocator.alloc(); + try { + builder.append("void method() throws "); + for (int i = 0; i < references.length; i++) { + if (i > 0) builder.append(", "); + builder.append(references[i].getCanonicalText()); + } + return createMethodFromText(builder.toString(), null).getThrowsList(); + } + finally { + StringBuilderSpinAllocator.dispose(builder); } - text += "{}"; - PsiMethod method = createMethodFromText(text, null); - return method.getThrowsList(); } @NotNull - public PsiJavaCodeReferenceElement createPackageReferenceElement(@NotNull String packageName) - throws IncorrectOperationException { + public PsiJavaCodeReferenceElement createPackageReferenceElement(@NotNull final String packageName) throws IncorrectOperationException { if (packageName.length() == 0) { throw new IncorrectOperationException("Cannot create reference to default package."); } @@ -512,8 +423,8 @@ public class PsiElementFactoryImpl extends PsiJavaParserFacadeImpl implements Ps } @NotNull - public PsiReferenceExpression createReferenceExpression(@NotNull PsiClass aClass) throws IncorrectOperationException { - String text; + public PsiReferenceExpression createReferenceExpression(@NotNull final PsiClass aClass) throws IncorrectOperationException { + final String text; if (aClass instanceof PsiAnonymousClass) { text = ((PsiAnonymousClass)aClass).getBaseClassType().getPresentableText(); } @@ -524,7 +435,7 @@ public class PsiElementFactoryImpl extends PsiJavaParserFacadeImpl implements Ps } @NotNull - public PsiReferenceExpression createReferenceExpression(@NotNull PsiPackage aPackage) throws IncorrectOperationException { + public PsiReferenceExpression createReferenceExpression(@NotNull final PsiPackage aPackage) throws IncorrectOperationException { if (aPackage.getQualifiedName().length() == 0) { throw new IncorrectOperationException("Cannot create reference to default package."); } @@ -532,13 +443,13 @@ public class PsiElementFactoryImpl extends PsiJavaParserFacadeImpl implements Ps } @NotNull - public PsiIdentifier createIdentifier(@NotNull String text) throws IncorrectOperationException { + public PsiIdentifier createIdentifier(@NotNull final String text) throws IncorrectOperationException { PsiUtil.checkIsIdentifier(myManager, text); return new LightIdentifier(myManager, text); } @NotNull - public PsiKeyword createKeyword(@NotNull String text) throws IncorrectOperationException { + public PsiKeyword createKeyword(@NotNull final String text) throws IncorrectOperationException { if (!JavaPsiFacade.getInstance(myManager.getProject()).getNameHelper().isKeyword(text)) { throw new IncorrectOperationException("\"" + text + "\" is not a keyword."); } @@ -546,21 +457,21 @@ public class PsiElementFactoryImpl extends PsiJavaParserFacadeImpl implements Ps } @NotNull - public PsiImportStatement createImportStatement(@NotNull PsiClass aClass) throws IncorrectOperationException { + public PsiImportStatement createImportStatement(@NotNull final PsiClass aClass) throws IncorrectOperationException { if (aClass instanceof PsiAnonymousClass) { throw new IncorrectOperationException("Cannot create import statement for anonymous class."); } else if (aClass.getParent() instanceof PsiDeclarationStatement) { throw new IncorrectOperationException("Cannot create import statement for local class."); } - @NonNls String text = "import " + aClass.getQualifiedName() + ";"; - PsiJavaFile aFile = createDummyJavaFile(text); - PsiImportStatement statement = aFile.getImportList().getImportStatements()[0]; + + final PsiJavaFile aFile = createDummyJavaFile(join("import ", aClass.getQualifiedName(), ";")); + final PsiImportStatementBase statement = extractImport(aFile, false); return (PsiImportStatement)CodeStyleManager.getInstance(myManager.getProject()).reformat(statement); } @NotNull - public PsiImportStatement createImportStatementOnDemand(@NotNull String packageName) throws IncorrectOperationException { + public PsiImportStatement createImportStatementOnDemand(@NotNull final String packageName) throws IncorrectOperationException { if (packageName.length() == 0) { throw new IncorrectOperationException("Cannot create import statement for default package."); } @@ -568,102 +479,103 @@ public class PsiElementFactoryImpl extends PsiJavaParserFacadeImpl implements Ps throw new IncorrectOperationException("Incorrect package name: \"" + packageName + "\"."); } - @NonNls String text = "import " + packageName + ".*;"; - PsiJavaFile aFile = createDummyJavaFile(text); - PsiImportStatement statement = aFile.getImportList().getImportStatements()[0]; + final PsiJavaFile aFile = createDummyJavaFile(join("import ", packageName, ".*;")); + final PsiImportStatementBase statement = extractImport(aFile, false); return (PsiImportStatement)CodeStyleManager.getInstance(myManager.getProject()).reformat(statement); } @NotNull - public PsiDeclarationStatement createVariableDeclarationStatement(@NotNull String name, @NotNull PsiType type, PsiExpression initializer) - throws IncorrectOperationException { + public PsiDeclarationStatement createVariableDeclarationStatement(@NotNull final String name, + @NotNull final PsiType type, + final PsiExpression initializer) throws IncorrectOperationException { if (!JavaPsiFacade.getInstance(myManager.getProject()).getNameHelper().isIdentifier(name)) { throw new IncorrectOperationException("\"" + name + "\" is not an identifier."); } if (PsiType.NULL.equals(type)) { - throw new IncorrectOperationException("Cannot create field with type \"\"."); + throw new IncorrectOperationException("Cannot create variable with type \"null\"."); } - @NonNls StringBuilder buffer = new StringBuilder(); - buffer.append("X "); - buffer.append(name); + + final StringBuilder builder = StringBuilderSpinAllocator.alloc(); + builder.append("X ").append(name); if (initializer != null) { - buffer.append("=x"); + builder.append(" = x"); } - buffer.append(";"); - PsiDeclarationStatement statement = (PsiDeclarationStatement)createStatementFromText(buffer.toString(), null); - PsiVariable variable = (PsiVariable)statement.getDeclaredElements()[0]; - variable.getTypeElement().replace(createTypeElement(type)); - PsiUtil.setModifierProperty(variable, PsiModifier.FINAL, CodeStyleSettingsManager.getSettings(myManager.getProject()).GENERATE_FINAL_LOCALS); + builder.append(';'); + final String text = builder.toString(); + StringBuilderSpinAllocator.dispose(builder); + + final PsiDeclarationStatement statement = (PsiDeclarationStatement)createStatementFromText(text, null); + final PsiVariable variable = (PsiVariable)statement.getDeclaredElements()[0]; + replace(variable.getTypeElement(), createTypeElement(type), text); + PsiUtil.setModifierProperty(variable, PsiModifier.FINAL, + CodeStyleSettingsManager.getSettings(myManager.getProject()).GENERATE_FINAL_LOCALS); if (initializer != null) { - variable.getInitializer().replace(initializer); + replace(variable.getInitializer(), initializer, text); } markGenerated(statement); return statement; - } @NotNull - public PsiDocTag createParamTag(@NotNull String parameterName, @NonNls String description) throws IncorrectOperationException { - @NonNls StringBuilder buffer = new StringBuilder(); - buffer.append(" * @param "); - buffer.append(parameterName); - buffer.append(" "); - final String[] strings = description.split("\\n"); - for (int i = 0; i < strings.length; i++) { - String string = strings[i]; - if (i > 0) buffer.append("\n * "); - buffer.append(string); + public PsiDocTag createParamTag(@NotNull final String parameterName, @NonNls final String description) throws IncorrectOperationException { + final StringBuilder builder = StringBuilderSpinAllocator.alloc(); + try { + builder.append(" * @param "); + builder.append(parameterName); + builder.append(" "); + final String[] strings = description.split("\\n"); + for (int i = 0; i < strings.length; i++) { + if (i > 0) builder.append("\n * "); + builder.append(strings[i]); + } + return createDocTagFromText(builder.toString()); + } + finally { + StringBuilderSpinAllocator.dispose(builder); } - return createDocTagFromText(buffer.toString(), null); } @NotNull - public PsiExpressionCodeFragment createExpressionCodeFragment(@NotNull String text, - PsiElement context, + public PsiExpressionCodeFragment createExpressionCodeFragment(@NotNull final String text, + final PsiElement context, final PsiType expectedType, - boolean isPhysical) { - final PsiExpressionCodeFragmentImpl result = new PsiExpressionCodeFragmentImpl( - myManager.getProject(), isPhysical, "fragment.java", text, expectedType); + final boolean isPhysical) { + final PsiExpressionCodeFragmentImpl result = + new PsiExpressionCodeFragmentImpl(myManager.getProject(), isPhysical, "fragment.java", text, expectedType); result.setContext(context); return result; } @NotNull - public JavaCodeFragment createCodeBlockCodeFragment(@NotNull String text, PsiElement context, boolean isPhysical) { - final PsiCodeFragmentImpl result = new PsiCodeFragmentImpl(myManager.getProject(), JavaElementType.STATEMENTS, - isPhysical, - "fragment.java", - text); + public JavaCodeFragment createCodeBlockCodeFragment(@NotNull final String text, final PsiElement context, final boolean isPhysical) { + final PsiCodeFragmentImpl result = + new PsiCodeFragmentImpl(myManager.getProject(), JavaElementType.STATEMENTS, isPhysical, "fragment.java", text); result.setContext(context); return result; } @NotNull - public PsiTypeCodeFragment createTypeCodeFragment(@NotNull String text, PsiElement context, boolean isPhysical) { - + public PsiTypeCodeFragment createTypeCodeFragment(@NotNull final String text, final PsiElement context, final boolean isPhysical) { return createTypeCodeFragment(text, context, false, isPhysical, false); } @NotNull - public PsiTypeCodeFragment createTypeCodeFragment(@NotNull String text, - PsiElement context, - boolean isVoidValid, - boolean isPhysical) { + public PsiTypeCodeFragment createTypeCodeFragment(@NotNull final String text, + final PsiElement context, + final boolean isVoidValid, + final boolean isPhysical) { return createTypeCodeFragment(text, context, true, isPhysical, false); } @NotNull - public PsiTypeCodeFragment createTypeCodeFragment(@NotNull String text, - PsiElement context, - boolean isVoidValid, - boolean isPhysical, - boolean allowEllipsis) { - final PsiTypeCodeFragmentImpl result = new PsiTypeCodeFragmentImpl(myManager.getProject(), - isPhysical, - allowEllipsis, - "fragment.java", - text); + public PsiTypeCodeFragment createTypeCodeFragment(@NotNull final String text, + final PsiElement context, + final boolean isVoidValid, + final boolean isPhysical, + final boolean allowEllipsis) { + final PsiTypeCodeFragmentImpl result + = new PsiTypeCodeFragmentImpl(myManager.getProject(), isPhysical, allowEllipsis, "fragment.java", text); result.setContext(context); if (isVoidValid) { result.putUserData(PsiUtil.VALID_VOID_TYPE_IN_CODE_FRAGMENT, Boolean.TRUE); @@ -671,7 +583,6 @@ public class PsiElementFactoryImpl extends PsiJavaParserFacadeImpl implements Ps return result; } - @NotNull public PsiAnnotation createAnnotationFromText(@NotNull final String annotationText, final PsiElement context) throws IncorrectOperationException { final PsiAnnotation psiAnnotation = super.createAnnotationFromText(annotationText, context); @@ -727,8 +638,8 @@ public class PsiElementFactoryImpl extends PsiJavaParserFacadeImpl implements Ps } @NotNull - public PsiTypeParameter createTypeParameterFromText(@NotNull final String text, final PsiElement context) throws - IncorrectOperationException { + public PsiTypeParameter createTypeParameterFromText(@NotNull final String text, + final PsiElement context) throws IncorrectOperationException { final PsiTypeParameter typeParameter = super.createTypeParameterFromText(text, context); markGenerated(typeParameter); return typeParameter; @@ -742,18 +653,18 @@ public class PsiElementFactoryImpl extends PsiJavaParserFacadeImpl implements Ps } @NotNull - public PsiMethod createMethodFromText(@NotNull final String text, final PsiElement context, final LanguageLevel level) throws - IncorrectOperationException { + public PsiMethod createMethodFromText(@NotNull final String text, + final PsiElement context, + final LanguageLevel level) throws IncorrectOperationException { final PsiMethod method = super.createMethodFromText(text, context, level); markGenerated(method); return method; } - @NotNull public PsiCatchSection createCatchSection(@NotNull final PsiClassType exceptionType, - @NotNull final String exceptionName, final PsiElement context) throws - IncorrectOperationException { + @NotNull final String exceptionName, + final PsiElement context) throws IncorrectOperationException { final PsiCatchSection psiCatchSection = super.createCatchSection(exceptionType, exceptionName, context); markGenerated(psiCatchSection); return psiCatchSection; @@ -762,4 +673,25 @@ public class PsiElementFactoryImpl extends PsiJavaParserFacadeImpl implements Ps private static void markGenerated(final PsiElement element) { ((TreeElement)element.getNode()).acceptTree(new GeneratedMarkerVisitor()); } + + private static PsiImportStatementBase extractImport(final PsiJavaFile aFile, final boolean isStatic) { + final PsiImportList importList = aFile.getImportList(); + assert importList != null : aFile; + final PsiImportStatementBase[] statements = isStatic ? importList.getImportStaticStatements() : importList.getImportStatements(); + assert statements.length == 1 : aFile.getText(); + return statements[0]; + } + + private static void replace(final PsiElement original, final PsiElement replacement, final String message) { + assert original != null : message; + original.replace(replacement); + } + + /** + * @deprecated use {@link PsiJavaParserFacadeImpl#getPrimitiveType(String)} (remove in IDEA 11). + */ + @SuppressWarnings({"MethodOverridesStaticMethodOfSuperclass", "UnusedDeclaration"}) + public static PsiPrimitiveType getPrimitiveType(final String text) { + return PsiJavaParserFacadeImpl.getPrimitiveType(text); + } } diff --git a/java/java-impl/src/com/intellij/psi/impl/PsiJavaParserFacadeImpl.java b/java/java-impl/src/com/intellij/psi/impl/PsiJavaParserFacadeImpl.java index 79bf4d8f2303..acc40b73b1a5 100644 --- a/java/java-impl/src/com/intellij/psi/impl/PsiJavaParserFacadeImpl.java +++ b/java/java-impl/src/com/intellij/psi/impl/PsiJavaParserFacadeImpl.java @@ -14,14 +14,13 @@ * limitations under the License. */ -/* - * @author max - */ package com.intellij.psi.impl; import com.intellij.ide.fileTemplates.FileTemplate; import com.intellij.ide.fileTemplates.FileTemplateManager; import com.intellij.ide.fileTemplates.JavaTemplateUtil; +import com.intellij.lang.PsiBuilder; +import com.intellij.lang.java.parser.*; import com.intellij.openapi.diagnostic.Logger; import com.intellij.openapi.fileTypes.FileType; import com.intellij.openapi.fileTypes.StdFileTypes; @@ -29,79 +28,154 @@ import com.intellij.openapi.progress.ProcessCanceledException; import com.intellij.openapi.roots.LanguageLevelProjectExtension; import com.intellij.pom.java.LanguageLevel; import com.intellij.psi.*; +import com.intellij.psi.impl.source.DummyHolder; import com.intellij.psi.impl.source.DummyHolderFactory; +import com.intellij.psi.impl.source.JavaDummyElement; import com.intellij.psi.impl.source.SourceTreeToPsiMap; -import com.intellij.psi.impl.source.parsing.DeclarationParsing; -import com.intellij.psi.impl.source.parsing.ExpressionParsing; -import com.intellij.psi.impl.source.parsing.JavaParsingContext; -import com.intellij.psi.impl.source.parsing.Parsing; -import com.intellij.psi.impl.source.tree.CompositeElement; -import com.intellij.psi.impl.source.tree.FileElement; -import com.intellij.psi.impl.source.tree.JavaElementType; import com.intellij.psi.impl.source.tree.TreeElement; import com.intellij.psi.javadoc.PsiDocComment; import com.intellij.psi.javadoc.PsiDocTag; -import com.intellij.psi.util.PsiUtil; import com.intellij.util.IncorrectOperationException; import com.intellij.util.containers.HashMap; -import org.jetbrains.annotations.NonNls; import org.jetbrains.annotations.NotNull; import java.util.Map; import java.util.Properties; +import static com.intellij.openapi.util.text.StringUtil.join; + +/* + * @author max + */ public class PsiJavaParserFacadeImpl extends PsiParserFacadeImpl implements PsiJavaParserFacade { private static final Logger LOG = Logger.getInstance("#com.intellij.psi.impl.PsiJavaParserFacadeImpl"); - protected static final Map ourPrimitiveTypesMap = new HashMap(); - protected PsiJavaFile myDummyJavaFile; + private static final JavaParserUtil.ParserWrapper ANNOTATION = new JavaParserUtil.ParserWrapper() { + @Override + public void parse(final PsiBuilder builder) { + DeclarationParser.parseAnnotation(builder); + } + }; - public PsiJavaParserFacadeImpl(PsiManagerEx manager) { + private static final JavaParserUtil.ParserWrapper PARAMETER = new JavaParserUtil.ParserWrapper() { + @Override + public void parse(final PsiBuilder builder) { + DeclarationParser.parseParameter(builder, true); + } + }; + + private static final JavaParserUtil.ParserWrapper TYPE = new JavaParserUtil.ParserWrapper() { + @Override + public void parse(final PsiBuilder builder) { + ReferenceParser.parseType(builder, ReferenceParser.EAT_LAST_DOT | ReferenceParser.ELLIPSIS | ReferenceParser.WILDCARD); + } + }; + + private static final JavaParserUtil.ParserWrapper TYPE_PARAMETER = new JavaParserUtil.ParserWrapper() { + @Override + public void parse(final PsiBuilder builder) { + ReferenceParser.parseTypeParameter(builder); + } + }; + + private static final JavaParserUtil.ParserWrapper DECLARATION = new JavaParserUtil.ParserWrapper() { + @Override + public void parse(final PsiBuilder builder) { + DeclarationParser.parse(builder, DeclarationParser.Context.CLASS); + } + }; + + private static final JavaParserUtil.ParserWrapper CODE_BLOCK = new JavaParserUtil.ParserWrapper() { + @Override + public void parse(final PsiBuilder builder) { + StatementParser.parseCodeBlockDeep(builder, true); + } + }; + + private static final JavaParserUtil.ParserWrapper STATEMENT = new JavaParserUtil.ParserWrapper() { + @Override + public void parse(final PsiBuilder builder) { + StatementParser.parseStatement(builder); + } + }; + + private static final JavaParserUtil.ParserWrapper EXPRESSION = new JavaParserUtil.ParserWrapper() { + @Override + public void parse(final PsiBuilder builder) { + ExpressionParser.parse(builder); + } + }; + + private static final JavaParserUtil.ParserWrapper ENUM_CONSTANT = new JavaParserUtil.ParserWrapper() { + @Override + public void parse(final PsiBuilder builder) { + DeclarationParser.parseEnumConstant(builder); + } + }; + + private static final JavaParserUtil.ParserWrapper CATCH_SECTION = new JavaParserUtil.ParserWrapper() { + @Override + public void parse(final PsiBuilder builder) { + StatementParser.parseCatchBlock(builder); + } + }; + + private static final Map PRIMITIVE_TYPES; + static { + PRIMITIVE_TYPES = new HashMap(); + PRIMITIVE_TYPES.put(PsiType.BYTE.getCanonicalText(), PsiType.BYTE); + PRIMITIVE_TYPES.put(PsiType.CHAR.getCanonicalText(), PsiType.CHAR); + PRIMITIVE_TYPES.put(PsiType.DOUBLE.getCanonicalText(), PsiType.DOUBLE); + PRIMITIVE_TYPES.put(PsiType.FLOAT.getCanonicalText(), PsiType.FLOAT); + PRIMITIVE_TYPES.put(PsiType.INT.getCanonicalText(), PsiType.INT); + PRIMITIVE_TYPES.put(PsiType.LONG.getCanonicalText(), PsiType.LONG); + PRIMITIVE_TYPES.put(PsiType.SHORT.getCanonicalText(), PsiType.SHORT); + PRIMITIVE_TYPES.put(PsiType.BOOLEAN.getCanonicalText(), PsiType.BOOLEAN); + PRIMITIVE_TYPES.put(PsiType.VOID.getCanonicalText(), PsiType.VOID); + PRIMITIVE_TYPES.put(PsiType.NULL.getCanonicalText(), PsiType.NULL); + } + + public PsiJavaParserFacadeImpl(final PsiManagerEx manager) { super(manager); } @NotNull - public PsiAnnotation createAnnotationFromText(@NotNull String annotationText, PsiElement context) throws IncorrectOperationException { - final FileElement holderElement = DummyHolderFactory.createHolder(myManager, context).getTreeElement(); - CompositeElement annotationElement = getJavaParsingContext(holderElement).getDeclarationParsing().parseAnnotationFromText(myManager, annotationText, getLanguageLevel(context)); - if (annotationElement == null || annotationElement.getElementType() != JavaElementType.ANNOTATION) { - throw new IncorrectOperationException("Incorrect annotation \"" + annotationText + "\"."); + public PsiAnnotation createAnnotationFromText(@NotNull final String text, final PsiElement context) throws IncorrectOperationException { + final DummyHolder holder = DummyHolderFactory.createHolder(myManager, new JavaDummyElement(text, ANNOTATION, false), context); + final PsiElement element = SourceTreeToPsiMap.treeElementToPsi(holder.getTreeElement().getFirstChildNode()); + if (!(element instanceof PsiAnnotation)) { + throw new IncorrectOperationException("Incorrect annotation \"" + text + "\"."); } - holderElement.rawAddChildren(annotationElement); - return (PsiAnnotation)SourceTreeToPsiMap.treeElementToPsi(annotationElement); - } - - private LanguageLevel getLanguageLevel(final PsiElement context) { - if (context == null) { - return LanguageLevelProjectExtension.getInstance(myManager.getProject()).getLanguageLevel(); - } - return PsiUtil.getLanguageLevel(context); + return (PsiAnnotation)element; } @NotNull - public PsiDocTag createDocTagFromText(@NotNull String docTagText, PsiElement context) throws IncorrectOperationException { - StringBuilder buffer = new StringBuilder(); - buffer.append("/**\n"); - buffer.append(docTagText); - buffer.append("\n */"); - PsiDocComment comment = createDocCommentFromText(buffer.toString(), context); - return comment.getTags()[0]; + public PsiDocTag createDocTagFromText(@NotNull final String text) throws IncorrectOperationException { + return createDocCommentFromText(join("/**\n", text, "\n */")).getTags()[0]; } @NotNull - public PsiDocComment createDocCommentFromText(@NotNull String docCommentText, PsiElement context) throws IncorrectOperationException { - @NonNls StringBuilder buffer = new StringBuilder(); - buffer.append(docCommentText); - buffer.append("void m();"); - final PsiMethod method = createMethodFromText(buffer.toString(), null); - return method.getDocComment(); + public PsiDocTag createDocTagFromText(@NotNull final String text, final PsiElement context) throws IncorrectOperationException { + return createDocTagFromText(text); } @NotNull - public PsiClass createClassFromText(@NotNull String body, PsiElement context) throws IncorrectOperationException { - @NonNls String fileText = "class _Dummy_ { " + body + " }"; - PsiJavaFile aFile = createDummyJavaFile(fileText); - PsiClass[] classes = aFile.getClasses(); + public PsiDocComment createDocCommentFromText(@NotNull final String text) throws IncorrectOperationException { + final PsiMethod method = createMethodFromText(join(text, "void m();"), null); + final PsiDocComment comment = method.getDocComment(); + assert comment != null : text; + return comment; + } + + @NotNull + public PsiDocComment createDocCommentFromText(@NotNull final String text, final PsiElement context) throws IncorrectOperationException { + return createDocCommentFromText(text); + } + + @NotNull + public PsiClass createClassFromText(@NotNull final String body, final PsiElement context) throws IncorrectOperationException { + final PsiJavaFile aFile = createDummyJavaFile(join("class _Dummy_ { ", body, " }")); + final PsiClass[] classes = aFile.getClasses(); if (classes.length != 1) { throw new IncorrectOperationException("Incorrect class \"" + body + "\"."); } @@ -109,211 +183,186 @@ public class PsiJavaParserFacadeImpl extends PsiParserFacadeImpl implements PsiJ } @NotNull - public PsiField createFieldFromText(@NotNull String text, PsiElement context) throws IncorrectOperationException { - final FileElement holderElement = DummyHolderFactory.createHolder(myManager, context).getTreeElement(); - TreeElement decl = getJavaParsingContext(holderElement).getDeclarationParsing().parseDeclarationText(myManager, LanguageLevelProjectExtension - .getInstance(myManager.getProject()).getLanguageLevel(), text, DeclarationParsing.Context.CLASS_CONTEXT); - if (decl == null || decl.getElementType() != JavaElementType.FIELD) { + public PsiField createFieldFromText(@NotNull final String text, final PsiElement context) throws IncorrectOperationException { + final DummyHolder holder = DummyHolderFactory.createHolder(myManager, new JavaDummyElement(text, DECLARATION, false), context); + final PsiElement element = SourceTreeToPsiMap.treeElementToPsi(holder.getTreeElement().getFirstChildNode()); + if (!(element instanceof PsiField)) { throw new IncorrectOperationException("Incorrect field \"" + text + "\"."); } - holderElement.rawAddChildren(decl); - return (PsiField)SourceTreeToPsiMap.treeElementToPsi(decl); - } - - protected JavaParsingContext getJavaParsingContext (FileElement holderElement) { - return new JavaParsingContext(holderElement.getCharTable(), LanguageLevelProjectExtension.getInstance(myManager.getProject()).getLanguageLevel()); - } - - private static JavaParsingContext getJavaParsingContext (FileElement holderElement, LanguageLevel languageLevel) { - return new JavaParsingContext(holderElement.getCharTable(), languageLevel); + return (PsiField)element; } @NotNull - public PsiMethod createMethodFromText(@NotNull String text, PsiElement context, LanguageLevel level) throws IncorrectOperationException { - final FileElement holderElement = DummyHolderFactory.createHolder(myManager, context).getTreeElement(); - TreeElement decl = getJavaParsingContext(holderElement, level).getDeclarationParsing().parseDeclarationText(myManager, level, text, - DeclarationParsing.Context.CLASS_CONTEXT); - if (decl == null || decl.getElementType() != JavaElementType.METHOD) { - throw new IncorrectOperationException("Incorrect method '" + text + "'. Context:"+context+"; Level:"+level+"; parsed: "+(decl == null ? null : DebugUtil.treeToString(decl, false))); + public PsiMethod createMethodFromText(@NotNull final String text, final PsiElement context, final LanguageLevel level) + throws IncorrectOperationException { + final DummyHolder holder = DummyHolderFactory.createHolder(myManager, new JavaDummyElement(text, DECLARATION, false, level), context); + final PsiElement element = SourceTreeToPsiMap.treeElementToPsi(holder.getTreeElement().getFirstChildNode()); + if (!(element instanceof PsiMethod)) { + throw new IncorrectOperationException("Incorrect method \"" + text + "\"."); } - holderElement.rawAddChildren(decl); - return (PsiMethod)SourceTreeToPsiMap.treeElementToPsi(decl); + return (PsiMethod)element; } @NotNull - public final PsiMethod createMethodFromText(@NotNull String text, PsiElement context) throws IncorrectOperationException { - return createMethodFromText(text, context, LanguageLevelProjectExtension.getInstance(myManager.getProject()).getLanguageLevel()); + public final PsiMethod createMethodFromText(@NotNull final String text, final PsiElement context) throws IncorrectOperationException { + final LanguageLevel level = LanguageLevelProjectExtension.getInstance(myManager.getProject()).getLanguageLevel(); + return createMethodFromText(text, context, level); } @NotNull - public PsiParameter createParameterFromText(@NotNull String text, PsiElement context) throws IncorrectOperationException { - final FileElement holderElement = DummyHolderFactory.createHolder(myManager, context).getTreeElement(); - CompositeElement param = getJavaParsingContext(holderElement).getDeclarationParsing().parseParameterText(text); - if (param == null) { + public PsiParameter createParameterFromText(@NotNull final String text, final PsiElement context) throws IncorrectOperationException { + final DummyHolder holder = DummyHolderFactory.createHolder(myManager, new JavaDummyElement(text, PARAMETER, false), context); + final PsiElement element = SourceTreeToPsiMap.treeElementToPsi(holder.getTreeElement().getFirstChildNode()); + if (!(element instanceof PsiParameter)) { throw new IncorrectOperationException("Incorrect parameter \"" + text + "\"."); } - holderElement.rawAddChildren(param); - return (PsiParameter)SourceTreeToPsiMap.treeElementToPsi(param); + return (PsiParameter)element; } @NotNull - public PsiType createTypeFromText(@NotNull String text, PsiElement context) throws IncorrectOperationException { + public PsiType createTypeFromText(@NotNull final String text, final PsiElement context) throws IncorrectOperationException { return createTypeInner(text, context, false); } - protected PsiType createTypeInner(final String text, final PsiElement context, boolean markAsCopy) throws IncorrectOperationException { - PsiPrimitiveType primitiveType = ourPrimitiveTypesMap.get(text); + protected PsiType createTypeInner(final String text, final PsiElement context, final boolean markAsCopy) throws IncorrectOperationException { + final PsiPrimitiveType primitiveType = PRIMITIVE_TYPES.get(text); if (primitiveType != null) return primitiveType; - final FileElement holderElement = DummyHolderFactory.createHolder(myManager, context).getTreeElement(); - CompositeElement typeElement = Parsing.parseTypeText(myManager, text, 0, text.length(), holderElement.getCharTable()); - if (typeElement == null) { - throw new IncorrectOperationException("Incorrect type \"" + text + "\""); + + final DummyHolder holder = DummyHolderFactory.createHolder(myManager, new JavaDummyElement(text, TYPE, false), context); + final PsiElement element = SourceTreeToPsiMap.treeElementToPsi(holder.getTreeElement().getFirstChildNode()); + if (!(element instanceof PsiTypeElement)) { + throw new IncorrectOperationException("Incorrect type \"" + text + "\"."); } - holderElement.rawAddChildren(typeElement); + if (markAsCopy) { - holderElement.acceptTree(new GeneratedMarkerVisitor()); + holder.getTreeElement().acceptTree(new GeneratedMarkerVisitor()); } - PsiTypeElement psiTypeElement = (PsiTypeElement)SourceTreeToPsiMap.treeElementToPsi(typeElement); - if (psiTypeElement == null) { - throw new IncorrectOperationException("PSI is null for element "+typeElement); - } - return psiTypeElement.getType(); + + return ((PsiTypeElement)element).getType(); } @NotNull - public PsiCodeBlock createCodeBlockFromText(@NotNull String text, PsiElement context) throws IncorrectOperationException { - final FileElement holderElement = DummyHolderFactory.createHolder(myManager, context).getTreeElement(); - CompositeElement treeElement = getJavaParsingContext(holderElement).getStatementParsing().parseCodeBlockText(myManager, text); - if (treeElement == null) { + public PsiCodeBlock createCodeBlockFromText(@NotNull final String text, final PsiElement context) throws IncorrectOperationException { + final DummyHolder holder = DummyHolderFactory.createHolder(myManager, new JavaDummyElement(text, CODE_BLOCK, true), context); + final PsiElement element = SourceTreeToPsiMap.treeElementToPsi(holder.getTreeElement().getFirstChildNode()); + if (!(element instanceof PsiCodeBlock)) { throw new IncorrectOperationException("Incorrect code block \"" + text + "\"."); } - holderElement.rawAddChildren(treeElement); - return (PsiCodeBlock)SourceTreeToPsiMap.treeElementToPsi(treeElement); + return (PsiCodeBlock)element; } @NotNull - public PsiStatement createStatementFromText(@NotNull String text, PsiElement context) throws IncorrectOperationException { - final FileElement treeHolder = DummyHolderFactory.createHolder(myManager, context).getTreeElement(); - TreeElement treeElement = getJavaParsingContext(treeHolder).getStatementParsing().parseStatementText(text); - if (treeElement == null) { + public PsiStatement createStatementFromText(@NotNull final String text, final PsiElement context) throws IncorrectOperationException { + final DummyHolder holder = DummyHolderFactory.createHolder(myManager, new JavaDummyElement(text, STATEMENT, false), context); + final PsiElement element = SourceTreeToPsiMap.treeElementToPsi(holder.getTreeElement().getFirstChildNode()); + if (!(element instanceof PsiStatement)) { throw new IncorrectOperationException("Incorrect statement \"" + text + "\"."); } - treeHolder.rawAddChildren(treeElement); - return (PsiStatement)SourceTreeToPsiMap.treeElementToPsi(treeElement); + return (PsiStatement)element; } @NotNull - public PsiExpression createExpressionFromText(@NotNull String text, PsiElement context) throws IncorrectOperationException { - final FileElement treeHolder = DummyHolderFactory.createHolder(myManager, context).getTreeElement(); - final CompositeElement treeElement = ExpressionParsing.parseExpressionText(myManager, text, 0, - text.length(), treeHolder.getCharTable()); - if (treeElement == null) { + public PsiExpression createExpressionFromText(@NotNull final String text, final PsiElement context) throws IncorrectOperationException { + final DummyHolder holder = DummyHolderFactory.createHolder(myManager, new JavaDummyElement(text, EXPRESSION, false), context); + final PsiElement element = SourceTreeToPsiMap.treeElementToPsi(holder.getTreeElement().getFirstChildNode()); + if (!(element instanceof PsiExpression)) { throw new IncorrectOperationException("Incorrect expression \"" + text + "\"."); } - treeHolder.rawAddChildren(treeElement); - return (PsiExpression)SourceTreeToPsiMap.treeElementToPsi(treeElement); + return (PsiExpression)element; } - protected PsiJavaFile createDummyJavaFile(String text) { - String ext = StdFileTypes.JAVA.getDefaultExtension(); - @NonNls String fileName = "_Dummy_." + ext; - FileType type = StdFileTypes.JAVA; - + protected PsiJavaFile createDummyJavaFile(final String text) { + final String fileName = "_Dummy_." + StdFileTypes.JAVA.getDefaultExtension(); + final FileType type = StdFileTypes.JAVA; return (PsiJavaFile)PsiFileFactory.getInstance(myManager.getProject()).createFileFromText(type, fileName, text, 0, text.length()); } @NotNull - public PsiTypeParameter createTypeParameterFromText(@NotNull String text, PsiElement context) - throws IncorrectOperationException { - final FileElement holderElement = DummyHolderFactory.createHolder(myManager, context).getTreeElement(); - TreeElement treeElement = getJavaParsingContext(holderElement).getDeclarationParsing().parseTypeParameterText(text); - if (treeElement == null) { - throw new IncorrectOperationException("Incorrect type parameter \"" + text + "\""); + public PsiTypeParameter createTypeParameterFromText(@NotNull final String text, final PsiElement context) throws IncorrectOperationException { + final DummyHolder holder = DummyHolderFactory.createHolder(myManager, new JavaDummyElement(text, TYPE_PARAMETER, false), context); + final PsiElement element = SourceTreeToPsiMap.treeElementToPsi(holder.getTreeElement().getFirstChildNode()); + if (!(element instanceof PsiTypeParameter)) { + throw new IncorrectOperationException("Incorrect type parameter \"" + text + "\"."); } - holderElement.rawAddChildren(treeElement); - return (PsiTypeParameter)SourceTreeToPsiMap.treeElementToPsi(treeElement); + return (PsiTypeParameter)element; } @NotNull - public PsiComment createCommentFromText(@NotNull String text, PsiElement context) throws IncorrectOperationException { - PsiJavaFile aFile = createDummyJavaFile(text); - PsiElement[] children = aFile.getChildren(); - for (PsiElement aChildren : children) { + public PsiComment createCommentFromText(@NotNull final String text, final PsiElement context) throws IncorrectOperationException { + final PsiJavaFile aFile = createDummyJavaFile(text); + for (PsiElement aChildren : aFile.getChildren()) { if (aChildren instanceof PsiComment) { if (!aChildren.getText().equals(text)) { - throw new IncorrectOperationException("Incorrect comment \"" + text + "\"."); + break; } - PsiComment comment = (PsiComment)aChildren; + final PsiComment comment = (PsiComment)aChildren; DummyHolderFactory.createHolder(myManager, (TreeElement)SourceTreeToPsiMap.psiElementToTree(comment), context); return comment; } } + throw new IncorrectOperationException("Incorrect comment \"" + text + "\"."); } @NotNull - public PsiEnumConstant createEnumConstantFromText(@NotNull String text, PsiElement context) throws IncorrectOperationException { - final FileElement holderElement = DummyHolderFactory.createHolder(myManager, context).getTreeElement(); - TreeElement decl = getJavaParsingContext(holderElement).getDeclarationParsing().parseEnumConstantText(text); - if (decl == null || decl.getElementType() != JavaElementType.ENUM_CONSTANT) { - throw new IncorrectOperationException("Incorrect enum constant text \"" + text + "\"."); + public PsiEnumConstant createEnumConstantFromText(@NotNull final String text, final PsiElement context) throws IncorrectOperationException { + final DummyHolder holder = DummyHolderFactory.createHolder(myManager, new JavaDummyElement(text, ENUM_CONSTANT, false), context); + final PsiElement element = SourceTreeToPsiMap.treeElementToPsi(holder.getTreeElement().getFirstChildNode()); + if (!(element instanceof PsiEnumConstant)) { + throw new IncorrectOperationException("Incorrect enum constant \"" + text + "\"."); } - holderElement.rawAddChildren(decl); - return (PsiEnumConstant)SourceTreeToPsiMap.treeElementToPsi(decl); + return (PsiEnumConstant)element; } @NotNull - public PsiCatchSection createCatchSection(@NotNull PsiClassType exceptionType, - @NotNull String exceptionName, - PsiElement context) throws IncorrectOperationException { - @NonNls StringBuilder buffer = new StringBuilder(); - buffer.append("catch ("); - buffer.append(exceptionType.getCanonicalText()); - buffer.append(" ").append(exceptionName).append("){}"); - String catchSectionText = buffer.toString(); - final FileElement holderElement = DummyHolderFactory.createHolder(myManager, context).getTreeElement(); - TreeElement catchSection = getJavaParsingContext(holderElement).getStatementParsing().parseCatchSectionText(catchSectionText); - if (catchSection == null || catchSection.getElementType() != JavaElementType.CATCH_SECTION) { - LOG.error(catchSectionText + "\nPSI:" + (catchSection == null ? null : DebugUtil.treeToString(catchSection, false))); + public PsiCatchSection createCatchSection(@NotNull final PsiClassType exceptionType, @NotNull final String exceptionName, + final PsiElement context) throws IncorrectOperationException { + final String text = join("catch (", exceptionType.getCanonicalText(), " ", exceptionName, ") {}"); + final DummyHolder holder = DummyHolderFactory.createHolder(myManager, new JavaDummyElement(text, CATCH_SECTION, false), context); + final PsiElement element = SourceTreeToPsiMap.treeElementToPsi(holder.getTreeElement().getFirstChildNode()); + if (!(element instanceof PsiCatchSection)) { + throw new IncorrectOperationException("Incorrect catch section \"" + text + "\"."); } - holderElement.rawAddChildren(catchSection); - PsiCatchSection psiCatchSection = (PsiCatchSection)SourceTreeToPsiMap.treeElementToPsi(catchSection); - - setupCatchBlock(exceptionName, context, psiCatchSection); - return (PsiCatchSection)myManager.getCodeStyleManager().reformat(psiCatchSection); + setupCatchBlock(exceptionName, context, (PsiCatchSection)element); + return (PsiCatchSection)myManager.getCodeStyleManager().reformat(element); } - private void setupCatchBlock(String exceptionName, PsiElement context, PsiCatchSection psiCatchSection) - throws IncorrectOperationException { - FileTemplate catchBodyTemplate = FileTemplateManager.getInstance().getCodeTemplate(JavaTemplateUtil.TEMPLATE_CATCH_BODY); + private void setupCatchBlock(final String exceptionName, final PsiElement context, final PsiCatchSection psiCatchSection) + throws IncorrectOperationException { + final FileTemplate catchBodyTemplate = FileTemplateManager.getInstance().getCodeTemplate(JavaTemplateUtil.TEMPLATE_CATCH_BODY); LOG.assertTrue(catchBodyTemplate != null); - Properties props = new Properties(); + final Properties props = new Properties(); props.setProperty(FileTemplate.ATTRIBUTE_EXCEPTION, exceptionName); if (context != null && context.isPhysical()) { - PsiDirectory directory = context.getContainingFile().getContainingDirectory(); + final PsiDirectory directory = context.getContainingFile().getContainingDirectory(); if (directory != null) { JavaTemplateUtil.setPackageNameAttribute(props, directory); } } - PsiCodeBlock codeBlockFromText; + + final PsiCodeBlock codeBlockFromText; try { - String catchBody = catchBodyTemplate.getText(props); - codeBlockFromText = createCodeBlockFromText("{\n" + catchBody + "\n}", null); + codeBlockFromText = createCodeBlockFromText("{\n" + catchBodyTemplate.getText(props) + "\n}", null); } catch (ProcessCanceledException ce) { throw ce; } catch (Exception e) { - throw new IncorrectOperationException("Incorrect file template",e); + throw new IncorrectOperationException("Incorrect file template", e); } psiCatchSection.getCatchBlock().replace(codeBlockFromText); } - public PsiType createPrimitiveType(@NotNull String text, @NotNull PsiAnnotation[] annotations) { - if (annotations.length == 0) { - return PsiElementFactoryImpl.getPrimitiveType(text);//todo + public PsiType createPrimitiveType(@NotNull final String text, @NotNull final PsiAnnotation[] annotations) throws IncorrectOperationException { + final PsiPrimitiveType primitiveType = getPrimitiveType(text); + if (primitiveType == null) { + throw new IncorrectOperationException("Incorrect primitive type \"" + text + "\"."); } - return new PsiPrimitiveType(text, annotations); + return annotations.length == 0 ? primitiveType : new PsiPrimitiveType(text, annotations); + } + + public static PsiPrimitiveType getPrimitiveType(final String text) { + return PRIMITIVE_TYPES.get(text); } } diff --git a/java/openapi/src/com/intellij/psi/PsiElementFactory.java b/java/openapi/src/com/intellij/psi/PsiElementFactory.java index 0ac50882572e..d74a242b882b 100644 --- a/java/openapi/src/com/intellij/psi/PsiElementFactory.java +++ b/java/openapi/src/com/intellij/psi/PsiElementFactory.java @@ -58,8 +58,7 @@ public interface PsiElementFactory extends PsiJavaParserFacade { * @return the created enum instance. * @throws IncorrectOperationException if name is not a valid Java identifier. */ - - PsiClass createEnum(@NotNull @NonNls String name) throws IncorrectOperationException; + @NotNull PsiClass createEnum(@NotNull @NonNls String name) throws IncorrectOperationException; /** * Creates a field with the specified name and type. @@ -158,7 +157,7 @@ public interface PsiElementFactory extends PsiJavaParserFacade { * * @param type the type to detach. * @return the detached type. - * @deprecated Optimization method, do not use if you do not understand what it does. + * @deprecated does nothing (remove in IDEA 11) */ @NotNull PsiType detachType(@NotNull PsiType type); @@ -189,9 +188,10 @@ public interface PsiElementFactory extends PsiJavaParserFacade { @Nullable PsiPrimitiveType createPrimitiveType(@NotNull String text); /** - * The same as {@link #createTypeByFQClassName(String, GlobalSearchScope)} with {@link GlobalSearchScope#allScope()} + * The same as {@link #createTypeByFQClassName(String, GlobalSearchScope)} + * with {@link GlobalSearchScope#allScope(com.intellij.openapi.project.Project)}. * - * @param qName the full-qualified name of the class to create the reference to. + * @param qName the full-qualified name of the class to create the reference to. * @return the class type instance. */ @NotNull PsiClassType createTypeByFQClassName(@NotNull @NonNls String qName); @@ -419,6 +419,7 @@ public interface PsiElementFactory extends PsiJavaParserFacade { /** * Returns a synthetic Java class containing methods which are defined on Java arrays. * + * @param languageLevel language level used to construct array class. * @return the array synthetic class. */ @NotNull PsiClass getArrayClass(@NotNull LanguageLevel languageLevel); @@ -428,7 +429,7 @@ public interface PsiElementFactory extends PsiJavaParserFacade { * are defined on Java arrays with the specified element type. * * @param componentType the component type of the array for which the class type is returned. - * @param languageLevel + * @param languageLevel language level used to construct array class. * @return the class type the array synthetic class. */ @NotNull PsiClassType getArrayClassType(@NotNull PsiType componentType, @NotNull final LanguageLevel languageLevel); diff --git a/java/openapi/src/com/intellij/psi/PsiJavaParserFacade.java b/java/openapi/src/com/intellij/psi/PsiJavaParserFacade.java index a52c7e26dc0f..676de126bfba 100644 --- a/java/openapi/src/com/intellij/psi/PsiJavaParserFacade.java +++ b/java/openapi/src/com/intellij/psi/PsiJavaParserFacade.java @@ -14,9 +14,6 @@ * limitations under the License. */ -/* - * @author max - */ package com.intellij.psi; import com.intellij.pom.java.LanguageLevel; @@ -26,28 +23,41 @@ import com.intellij.util.IncorrectOperationException; import org.jetbrains.annotations.NonNls; import org.jetbrains.annotations.NotNull; +/* + * @author max + */ public interface PsiJavaParserFacade extends PsiParserFacade { /** * Creates a JavaDoc tag from the specified text. * * @param docTagText the text of the JavaDoc tag. - * @param context ignored; no longer used * @return the created tag. * @throws com.intellij.util.IncorrectOperationException if the text of the tag is not valid. */ @NotNull - PsiDocTag createDocTagFromText(@NotNull String docTagText, @Deprecated PsiElement context) throws IncorrectOperationException; + PsiDocTag createDocTagFromText(@NotNull String docTagText) throws IncorrectOperationException; + + /** + * @deprecated use {@link #createDocTagFromText(String)} (to remove in IDEA 11) + */ + @NotNull + PsiDocTag createDocTagFromText(@NotNull String docTagText, PsiElement context) throws IncorrectOperationException; /** * Creates a JavaDoc comment from the specified text. * * @param docCommentText the text of the JavaDoc comment. - * @param context ignored; no longer used * @return the created comment. * @throws com.intellij.util.IncorrectOperationException if the text of the comment is not valid. */ @NotNull - PsiDocComment createDocCommentFromText(@NotNull String docCommentText, @Deprecated PsiElement context) throws IncorrectOperationException; + PsiDocComment createDocCommentFromText(@NotNull String docCommentText) throws IncorrectOperationException; + + /** + * @deprecated use {@link #createDocCommentFromText(String)} (to remove in IDEA 11) + */ + @NotNull + PsiDocComment createDocCommentFromText(@NotNull String docCommentText, PsiElement context) throws IncorrectOperationException; /** * Creates a Java class from the specified text. @@ -110,7 +120,7 @@ public interface PsiJavaParserFacade extends PsiParserFacade { * Creates a Java type from the specified text. * * @param text the text of the type to create (for example, a primitive type keyword, an array - * declaration or the name of a class) + * declaration or the name of a class). * @param context the PSI element used as context for resolving the reference. * @return the created type instance. * @throws com.intellij.util.IncorrectOperationException if the text does not specify a valid type. @@ -193,7 +203,7 @@ public interface PsiJavaParserFacade extends PsiParserFacade { * type and name. * * @param exceptionType the type of the exception to catch. - * @param exceptionName the name of the variable in which the caught exception is stored (may be an empty string) + * @param exceptionName the name of the variable in which the caught exception is stored (may be an empty string). * @param context the context for resolving references. * @return the created catch section instance. * @throws IncorrectOperationException if some of the parameters are not valid. @@ -201,5 +211,13 @@ public interface PsiJavaParserFacade extends PsiParserFacade { @NotNull PsiCatchSection createCatchSection(@NotNull PsiClassType exceptionType, @NotNull String exceptionName, PsiElement context) throws IncorrectOperationException; - PsiType createPrimitiveType(@NotNull String text, @NotNull PsiAnnotation[] annotations); + /** + * Creates a Java type from the specified text. + * + * @param text the text of the type to create (a primitive type keyword). + * @param annotations array (possible empty) of annotations to annotate the created type. + * @return the created type instance. + * @throws IncorrectOperationException if some of the parameters are not valid. + */ + PsiType createPrimitiveType(@NotNull String text, @NotNull PsiAnnotation[] annotations) throws IncorrectOperationException; } From 9996c399f38e802b12273b057c666f3158fc59e1 Mon Sep 17 00:00:00 2001 From: Roman Shevchenko Date: Wed, 15 Dec 2010 18:51:52 +0300 Subject: [PATCH 43/54] Use non-deprecated methods of PsiElementFactory and PsiJavaParserFacade --- .../daemon/impl/RemoveSuppressWarningAction.java | 2 +- .../daemon/impl/actions/SuppressAllForClassFix.java | 2 +- .../codeInsight/daemon/impl/actions/SuppressFix.java | 6 +++--- .../intention/impl/ConvertToBasicLatinAction.java | 2 +- .../intellij/codeInsight/javadoc/JavaDocInfoGenerator.java | 5 ++--- .../codeInspection/javaDoc/JavaDocLocalInspection.java | 2 +- .../impl/manipulators/PsiDocTagValueManipulator.java | 2 +- .../IntroduceParameterObjectProcessor.java | 3 +-- .../testng/inspection/ConvertAnnotationInspection.java | 4 ++-- 9 files changed, 13 insertions(+), 15 deletions(-) diff --git a/java/java-impl/src/com/intellij/codeInsight/daemon/impl/RemoveSuppressWarningAction.java b/java/java-impl/src/com/intellij/codeInsight/daemon/impl/RemoveSuppressWarningAction.java index 972cc03e1441..dec89978d01f 100644 --- a/java/java-impl/src/com/intellij/codeInsight/daemon/impl/RemoveSuppressWarningAction.java +++ b/java/java-impl/src/com/intellij/codeInsight/daemon/impl/RemoveSuppressWarningAction.java @@ -138,7 +138,7 @@ public class RemoveSuppressWarningAction implements LocalQuickFix { } else if (newText != null) { newText = "@" + SuppressionUtil.SUPPRESS_INSPECTIONS_TAG_NAME + " " + newText; - PsiDocTag newTag = JavaPsiFacade.getInstance(tag.getProject()).getElementFactory().createDocTagFromText(newText, tag); + PsiDocTag newTag = JavaPsiFacade.getInstance(tag.getProject()).getElementFactory().createDocTagFromText(newText); tag.replace(newTag); } } diff --git a/java/java-impl/src/com/intellij/codeInsight/daemon/impl/actions/SuppressAllForClassFix.java b/java/java-impl/src/com/intellij/codeInsight/daemon/impl/actions/SuppressAllForClassFix.java index 421a8161fd30..e39e54fbf800 100644 --- a/java/java-impl/src/com/intellij/codeInsight/daemon/impl/actions/SuppressAllForClassFix.java +++ b/java/java-impl/src/com/intellij/codeInsight/daemon/impl/actions/SuppressAllForClassFix.java @@ -84,7 +84,7 @@ public class SuppressAllForClassFix extends SuppressFix { PsiDocTag noInspectionTag = docComment.findTagByName(SuppressionUtil.SUPPRESS_INSPECTIONS_TAG_NAME); if (noInspectionTag != null) { String tagText = "@" + SuppressionUtil.SUPPRESS_INSPECTIONS_TAG_NAME + " " + SuppressionUtil.ALL; - noInspectionTag.replace(JavaPsiFacade.getInstance(project).getElementFactory().createDocTagFromText(tagText, null)); + noInspectionTag.replace(JavaPsiFacade.getInstance(project).getElementFactory().createDocTagFromText(tagText)); DaemonCodeAnalyzer.getInstance(project).restart(); return; } diff --git a/java/java-impl/src/com/intellij/codeInsight/daemon/impl/actions/SuppressFix.java b/java/java-impl/src/com/intellij/codeInsight/daemon/impl/actions/SuppressFix.java index 99db61ace268..b3fd3fbe2676 100644 --- a/java/java-impl/src/com/intellij/codeInsight/daemon/impl/actions/SuppressFix.java +++ b/java/java-impl/src/com/intellij/codeInsight/daemon/impl/actions/SuppressFix.java @@ -109,7 +109,7 @@ public class SuppressFix extends SuppressIntentionAction { PsiManager manager = PsiManager.getInstance(project); if (docComment == null) { String commentText = "/** @" + SuppressionUtil.SUPPRESS_INSPECTIONS_TAG_NAME + " " + getID(container) + "*/"; - docComment = JavaPsiFacade.getInstance(manager.getProject()).getElementFactory().createDocCommentFromText(commentText, null); + docComment = JavaPsiFacade.getInstance(manager.getProject()).getElementFactory().createDocCommentFromText(commentText); PsiElement firstChild = container.getFirstChild(); container.addBefore(docComment, firstChild); } @@ -122,11 +122,11 @@ public class SuppressFix extends SuppressIntentionAction { " " + (valueElement != null ? valueElement.getText() + "," : "") + getID(container); - noInspectionTag.replace(JavaPsiFacade.getInstance(manager.getProject()).getElementFactory().createDocTagFromText(tagText, null)); + noInspectionTag.replace(JavaPsiFacade.getInstance(manager.getProject()).getElementFactory().createDocTagFromText(tagText)); } else { String tagText = "@" + SuppressionUtil.SUPPRESS_INSPECTIONS_TAG_NAME + " " + getID(container); - docComment.add(JavaPsiFacade.getInstance(manager.getProject()).getElementFactory().createDocTagFromText(tagText, null)); + docComment.add(JavaPsiFacade.getInstance(manager.getProject()).getElementFactory().createDocTagFromText(tagText)); } } } diff --git a/java/java-impl/src/com/intellij/codeInsight/intention/impl/ConvertToBasicLatinAction.java b/java/java-impl/src/com/intellij/codeInsight/intention/impl/ConvertToBasicLatinAction.java index 98a5bcf697aa..e4b0467119e9 100644 --- a/java/java-impl/src/com/intellij/codeInsight/intention/impl/ConvertToBasicLatinAction.java +++ b/java/java-impl/src/com/intellij/codeInsight/intention/impl/ConvertToBasicLatinAction.java @@ -177,7 +177,7 @@ public class ConvertToBasicLatinAction extends PsiElementBaseIntentionAction { } public PsiElement createReplacement(final PsiElement element, final String newText) { - return JavaPsiFacade.getElementFactory(element.getProject()).createDocCommentFromText(newText, element.getParent()); + return JavaPsiFacade.getElementFactory(element.getProject()).createDocCommentFromText(newText); } private static void loadEntities(final Project project) { diff --git a/java/java-impl/src/com/intellij/codeInsight/javadoc/JavaDocInfoGenerator.java b/java/java-impl/src/com/intellij/codeInsight/javadoc/JavaDocInfoGenerator.java index 6f56bc39b7f0..5d3ff59a8e97 100644 --- a/java/java-impl/src/com/intellij/codeInsight/javadoc/JavaDocInfoGenerator.java +++ b/java/java-impl/src/com/intellij/codeInsight/javadoc/JavaDocInfoGenerator.java @@ -1343,9 +1343,8 @@ public class JavaDocInfoGenerator { } else { try { - final PsiDocTag tag = JavaPsiFacade.getInstance(method.getProject()).getElementFactory().createDocCommentFromText("/** @exception " + paramName + " */", - method.getContainingFile()).getTags()[0]; - + final PsiElementFactory elementFactory = JavaPsiFacade.getInstance(method.getProject()).getElementFactory(); + final PsiDocTag tag = elementFactory.createDocTagFromText("@exception " + paramName); collectedTags.addLast(new Pair>(tag, ourEmptyProvider)); } catch (IncorrectOperationException e) { diff --git a/java/java-impl/src/com/intellij/codeInspection/javaDoc/JavaDocLocalInspection.java b/java/java-impl/src/com/intellij/codeInspection/javaDoc/JavaDocLocalInspection.java index 73c1821c0a38..4eedb6c34abe 100644 --- a/java/java-impl/src/com/intellij/codeInspection/javaDoc/JavaDocLocalInspection.java +++ b/java/java-impl/src/com/intellij/codeInspection/javaDoc/JavaDocLocalInspection.java @@ -323,7 +323,7 @@ public class JavaDocLocalInspection extends BaseLocalInspectionTool { if (owner != null) { if (!CodeInsightUtil.preparePsiElementsForWrite(owner)) return; final PsiDocComment docComment = owner.getDocComment(); - final PsiDocTag tag = factory.createDocTagFromText("@" + myTag+" "+myValue, docComment); + final PsiDocTag tag = factory.createDocTagFromText("@" + myTag + " " + myValue); if (docComment != null) { PsiElement addedTag; final PsiElement anchor = getAnchor(); diff --git a/java/java-impl/src/com/intellij/psi/impl/source/resolve/reference/impl/manipulators/PsiDocTagValueManipulator.java b/java/java-impl/src/com/intellij/psi/impl/source/resolve/reference/impl/manipulators/PsiDocTagValueManipulator.java index 66fd5a77ae72..4388efd53c9c 100644 --- a/java/java-impl/src/com/intellij/psi/impl/source/resolve/reference/impl/manipulators/PsiDocTagValueManipulator.java +++ b/java/java-impl/src/com/intellij/psi/impl/source/resolve/reference/impl/manipulators/PsiDocTagValueManipulator.java @@ -36,7 +36,7 @@ public class PsiDocTagValueManipulator extends AbstractElementManipulator Date: Tue, 14 Dec 2010 22:37:57 +0300 Subject: [PATCH 44/54] Old Java parser deprecation --- .../intellij/psi/impl/source/parsing/ClassBodyParsing.java | 2 +- .../psi/impl/source/parsing/DeclarationParsing.java | 2 +- .../psi/impl/source/parsing/ExpressionParsing.java | 3 +++ .../intellij/psi/impl/source/parsing/FileTextParsing.java | 2 +- .../psi/impl/source/parsing/ImportsTextParsing.java | 2 +- .../intellij/psi/impl/source/parsing/JavadocParsing.java | 3 +++ .../src/com/intellij/psi/impl/source/parsing/Parsing.java | 7 +++++-- .../intellij/psi/impl/source/parsing/StatementParsing.java | 3 +++ 8 files changed, 18 insertions(+), 6 deletions(-) diff --git a/java/java-impl/src/com/intellij/psi/impl/source/parsing/ClassBodyParsing.java b/java/java-impl/src/com/intellij/psi/impl/source/parsing/ClassBodyParsing.java index af3dcdf38783..5261951b12a6 100644 --- a/java/java-impl/src/com/intellij/psi/impl/source/parsing/ClassBodyParsing.java +++ b/java/java-impl/src/com/intellij/psi/impl/source/parsing/ClassBodyParsing.java @@ -25,7 +25,7 @@ import com.intellij.psi.impl.source.tree.TreeElement; import com.intellij.psi.tree.IElementType; /** - * + * @deprecated old Java parser is deprecated in favor of PSI builder-based one (see com.intellij.lang.java.parser.*) (to remove in IDEA 11). */ public class ClassBodyParsing extends Parsing { private static final Logger LOG = Logger.getInstance("#com.intellij.psi.impl.source.parsing.ClassBodyParsing"); diff --git a/java/java-impl/src/com/intellij/psi/impl/source/parsing/DeclarationParsing.java b/java/java-impl/src/com/intellij/psi/impl/source/parsing/DeclarationParsing.java index a220b14d694a..10899f2551ef 100644 --- a/java/java-impl/src/com/intellij/psi/impl/source/parsing/DeclarationParsing.java +++ b/java/java-impl/src/com/intellij/psi/impl/source/parsing/DeclarationParsing.java @@ -32,7 +32,7 @@ import org.jetbrains.annotations.NotNull; import org.jetbrains.annotations.Nullable; /** - * + * @deprecated old Java parser is deprecated in favor of PSI builder-based one (see com.intellij.lang.java.parser.*) (to remove in IDEA 11). */ public class DeclarationParsing extends Parsing { private static final Logger LOG = Logger.getInstance("#com.intellij.psi.impl.source.parsing.DeclarationParsing"); diff --git a/java/java-impl/src/com/intellij/psi/impl/source/parsing/ExpressionParsing.java b/java/java-impl/src/com/intellij/psi/impl/source/parsing/ExpressionParsing.java index fc27fc95ca14..fb96293d27e0 100644 --- a/java/java-impl/src/com/intellij/psi/impl/source/parsing/ExpressionParsing.java +++ b/java/java-impl/src/com/intellij/psi/impl/source/parsing/ExpressionParsing.java @@ -34,6 +34,9 @@ import com.intellij.psi.tree.TokenSet; import com.intellij.util.CharTable; import org.jetbrains.annotations.NotNull; +/** + * @deprecated old Java parser is deprecated in favor of PSI builder-based one (see com.intellij.lang.java.parser.*) (to remove in IDEA 11). + */ public class ExpressionParsing extends Parsing { private static final Logger LOG = Logger.getInstance("#com.intellij.psi.impl.source.parsing.ExpressionParsing"); diff --git a/java/java-impl/src/com/intellij/psi/impl/source/parsing/FileTextParsing.java b/java/java-impl/src/com/intellij/psi/impl/source/parsing/FileTextParsing.java index 50bdf945ddd0..93035892410e 100644 --- a/java/java-impl/src/com/intellij/psi/impl/source/parsing/FileTextParsing.java +++ b/java/java-impl/src/com/intellij/psi/impl/source/parsing/FileTextParsing.java @@ -31,7 +31,7 @@ import org.jetbrains.annotations.NotNull; import org.jetbrains.annotations.Nullable; /** - * + * @deprecated old Java parser is deprecated in favor of PSI builder-based one (see com.intellij.lang.java.parser.*) (to remove in IDEA 11). */ public class FileTextParsing extends Parsing { public FileTextParsing(JavaParsingContext context) { diff --git a/java/java-impl/src/com/intellij/psi/impl/source/parsing/ImportsTextParsing.java b/java/java-impl/src/com/intellij/psi/impl/source/parsing/ImportsTextParsing.java index 2a24d49bd43a..bae311297dba 100644 --- a/java/java-impl/src/com/intellij/psi/impl/source/parsing/ImportsTextParsing.java +++ b/java/java-impl/src/com/intellij/psi/impl/source/parsing/ImportsTextParsing.java @@ -28,7 +28,7 @@ import com.intellij.psi.TokenType; import org.jetbrains.annotations.Nullable; /** - * + * @deprecated old Java parser is deprecated in favor of PSI builder-based one (see com.intellij.lang.java.parser.*) (to remove in IDEA 11). */ public class ImportsTextParsing extends Parsing { private static final Logger LOG = Logger.getInstance("#com.intellij.psi.impl.source.parsing.ImportsTextParsing"); diff --git a/java/java-impl/src/com/intellij/psi/impl/source/parsing/JavadocParsing.java b/java/java-impl/src/com/intellij/psi/impl/source/parsing/JavadocParsing.java index 0617588c385b..b43a2b70755d 100644 --- a/java/java-impl/src/com/intellij/psi/impl/source/parsing/JavadocParsing.java +++ b/java/java-impl/src/com/intellij/psi/impl/source/parsing/JavadocParsing.java @@ -33,6 +33,9 @@ import com.intellij.psi.tree.IElementType; import com.intellij.psi.tree.TokenSet; import org.jetbrains.annotations.NonNls; +/** + * todo[r.sh] rewrite and deprecate + */ public class JavadocParsing extends Parsing { private static final Logger LOG = Logger.getInstance("#com.intellij.psi.impl.source.parsing.JavadocParsing"); diff --git a/java/java-impl/src/com/intellij/psi/impl/source/parsing/Parsing.java b/java/java-impl/src/com/intellij/psi/impl/source/parsing/Parsing.java index b9a38cba114a..a93645b172a5 100644 --- a/java/java-impl/src/com/intellij/psi/impl/source/parsing/Parsing.java +++ b/java/java-impl/src/com/intellij/psi/impl/source/parsing/Parsing.java @@ -33,6 +33,9 @@ import com.intellij.util.CharTable; import org.jetbrains.annotations.NotNull; import org.jetbrains.annotations.Nullable; +/** + * @deprecated old Java parser is deprecated in favor of PSI builder-based one (see com.intellij.lang.java.parser.*) (to remove in IDEA 11). + */ public class Parsing { private static final Logger LOG = Logger.getInstance("#com.intellij.psi.impl.source.parsing.Parsing"); protected static final boolean DEEP_PARSE_BLOCKS_IN_STATEMENTS = false; @@ -198,8 +201,8 @@ public class Parsing { return type; } - public CompositeElement parseTypeWithEllipsis(Lexer lexer, boolean eatLastDot, boolean allowWilcard) { - CompositeElement type = parseType(lexer, eatLastDot, allowWilcard, false); + public CompositeElement parseTypeWithEllipsis(Lexer lexer, boolean eatLastDot, boolean allowWildcard) { + CompositeElement type = parseType(lexer, eatLastDot, allowWildcard, false); if (type == null) return null; if (lexer.getTokenType() == JavaTokenType.ELLIPSIS) { CompositeElement type1 = ASTFactory.composite(JavaElementType.TYPE); diff --git a/java/java-impl/src/com/intellij/psi/impl/source/parsing/StatementParsing.java b/java/java-impl/src/com/intellij/psi/impl/source/parsing/StatementParsing.java index 6e4f8feade39..c45036a40403 100644 --- a/java/java-impl/src/com/intellij/psi/impl/source/parsing/StatementParsing.java +++ b/java/java-impl/src/com/intellij/psi/impl/source/parsing/StatementParsing.java @@ -33,6 +33,9 @@ import org.jetbrains.annotations.Nullable; import java.util.ArrayList; import java.util.List; +/** + * @deprecated old Java parser is deprecated in favor of PSI builder-based one (see com.intellij.lang.java.parser.*) (to remove in IDEA 11). + */ public class StatementParsing extends Parsing { private static final Logger LOG = Logger.getInstance("#com.intellij.psi.impl.source.parsing.StatementParsing"); From 104add6261efd030fe0f4debc3851e05d889241b Mon Sep 17 00:00:00 2001 From: Roman Shevchenko Date: Thu, 16 Dec 2010 14:50:46 +0300 Subject: [PATCH 45/54] CE main module dependencies fixed --- community-main.iml | 9 +++++++++ 1 file changed, 9 insertions(+) diff --git a/community-main.iml b/community-main.iml index e984246e74c7..e3109b8263bf 100644 --- a/community-main.iml +++ b/community-main.iml @@ -77,6 +77,15 @@ + + + + + + + + + From d3c5837dbf23800fe3c886a7090b1fcb346e5cd4 Mon Sep 17 00:00:00 2001 From: Dmitry Avdeev Date: Wed, 15 Dec 2010 14:06:25 +0300 Subject: [PATCH 46/54] another task completion test --- .../intellij/tasks/TaskCompletionTest.java | 29 +++++++++++++++---- 1 file changed, 24 insertions(+), 5 deletions(-) diff --git a/plugins/tasks/tasks-tests/test/com/intellij/tasks/TaskCompletionTest.java b/plugins/tasks/tasks-tests/test/com/intellij/tasks/TaskCompletionTest.java index 0336cf4f4860..999611999a25 100644 --- a/plugins/tasks/tasks-tests/test/com/intellij/tasks/TaskCompletionTest.java +++ b/plugins/tasks/tasks-tests/test/com/intellij/tasks/TaskCompletionTest.java @@ -1,6 +1,9 @@ package com.intellij.tasks; +import com.intellij.codeInsight.completion.CompletionType; +import com.intellij.codeInsight.lookup.LookupElement; import com.intellij.psi.PsiFile; +import com.intellij.tasks.impl.LocalTaskImpl; import com.intellij.tasks.impl.TaskCompletionContributor; import com.intellij.tasks.impl.TaskManagerImpl; import com.intellij.testFramework.fixtures.LightCodeInsightFixtureTestCase; @@ -24,17 +27,33 @@ public class TaskCompletionTest extends LightCodeInsightFixtureTestCase { doTest("my TEST-", "my TEST-001: Test task"); } + public void testNumberCompletion() throws Exception { + configureFile("TEST-0"); + configureRepository(new LocalTaskImpl("TEST-001", "Test task"), new LocalTaskImpl("TEST-002", "Test task 2")); + LookupElement[] elements = myFixture.complete(CompletionType.BASIC); + assertNotNull(elements); + assertEquals(2, elements.length); + } + public void testSIOOBE() throws Exception { doTest(" my ", " TEST-001: Test task my"); } private void doTest(String text, String after) { - PsiFile psiFile = myFixture.configureByText("test.txt", text); - TaskCompletionContributor.installCompletion(myFixture.getDocument(psiFile), getProject(), null, false); - TaskManagerImpl manager = (TaskManagerImpl)TaskManager.getManager(getProject()); - manager.setRepositories(Arrays.asList(new TestRepository())); - manager.getState().updateEnabled = false; + configureFile(text); + configureRepository(new LocalTaskImpl("TEST-001", "Test task")); myFixture.completeBasic(); myFixture.checkResult(after); } + + private void configureFile(String text) { + PsiFile psiFile = myFixture.configureByText("test.txt", text); + TaskCompletionContributor.installCompletion(myFixture.getDocument(psiFile), getProject(), null, false); + } + + private void configureRepository(LocalTaskImpl... tasks) { + TaskManagerImpl manager = (TaskManagerImpl)TaskManager.getManager(getProject()); + manager.setRepositories(Arrays.asList(new TestRepository(tasks))); + manager.getState().updateEnabled = false; + } } From 26de6b81854b5808efe2cf60cbba29853a215f44 Mon Sep 17 00:00:00 2001 From: Dmitry Avdeev Date: Wed, 15 Dec 2010 14:07:07 +0300 Subject: [PATCH 47/54] always use cached issues --- .../intellij/tasks/actions/TaskSearchSupport.java | 12 ++++-------- .../test/com/intellij/tasks/TestRepository.java | 9 +++++++-- 2 files changed, 11 insertions(+), 10 deletions(-) diff --git a/plugins/tasks/tasks-core/src/com/intellij/tasks/actions/TaskSearchSupport.java b/plugins/tasks/tasks-core/src/com/intellij/tasks/actions/TaskSearchSupport.java index 7ef4b52150bc..6004e8725dd4 100644 --- a/plugins/tasks/tasks-core/src/com/intellij/tasks/actions/TaskSearchSupport.java +++ b/plugins/tasks/tasks-core/src/com/intellij/tasks/actions/TaskSearchSupport.java @@ -90,18 +90,14 @@ public class TaskSearchSupport { } private List getTasks(String pattern, boolean cached) { - List issues; - if (cached) { - issues = myManager.getCachedIssues(); + Set taskSet = new HashSet(myManager.getCachedIssues()); + if (!cached) { + taskSet.addAll(myManager.getIssues(pattern)); } - else { - issues = myManager.getIssues(pattern); - } - Set taskSet = new HashSet(issues); if (myRemoveLocal) { taskSet.removeAll(Arrays.asList(myManager.getLocalTasks())); } - issues = new ArrayList(taskSet); + List issues = new ArrayList(taskSet); Collections.sort(issues, myTaskComparator); return issues; } diff --git a/plugins/tasks/tasks-tests/test/com/intellij/tasks/TestRepository.java b/plugins/tasks/tasks-tests/test/com/intellij/tasks/TestRepository.java index 807dca75e884..a4fd7d0913ea 100644 --- a/plugins/tasks/tasks-tests/test/com/intellij/tasks/TestRepository.java +++ b/plugins/tasks/tasks-tests/test/com/intellij/tasks/TestRepository.java @@ -1,13 +1,18 @@ package com.intellij.tasks; import com.intellij.tasks.impl.BaseRepository; -import com.intellij.tasks.impl.LocalTaskImpl; import org.jetbrains.annotations.Nullable; /** * @author Dmitry Avdeev */ class TestRepository extends BaseRepository { + private final Task[] myTasks; + + public TestRepository(Task... tasks) { + myTasks = tasks; + } + @Override public BaseRepository clone() { return this; @@ -19,7 +24,7 @@ class TestRepository extends BaseRepository { @Override public Task[] getIssues(@Nullable String query, int max, long since) throws Exception { - return new Task[] { new LocalTaskImpl("TEST-001", "Test task")}; + return myTasks; } @Override From 4f3fe523079f3a7aa0081873126d64b9a788ddcb Mon Sep 17 00:00:00 2001 From: Dmitry Avdeev Date: Wed, 15 Dec 2010 16:06:30 +0300 Subject: [PATCH 48/54] IDEA-56497: IDEA is trying to access JIRA with bad password every 5 minutes --- .../intellij/tasks/jira/JiraRepository.java | 46 +++++++++---------- .../intellij/tasks/impl/TaskManagerImpl.java | 27 ++++++++++- 2 files changed, 47 insertions(+), 26 deletions(-) diff --git a/plugins/tasks/jira-connector/src/main/java/com/intellij/tasks/jira/JiraRepository.java b/plugins/tasks/jira-connector/src/main/java/com/intellij/tasks/jira/JiraRepository.java index c7a8540c6a4b..1ed71cd9f9bf 100644 --- a/plugins/tasks/jira-connector/src/main/java/com/intellij/tasks/jira/JiraRepository.java +++ b/plugins/tasks/jira-connector/src/main/java/com/intellij/tasks/jira/JiraRepository.java @@ -56,31 +56,25 @@ public class JiraRepository extends BaseRepositoryImpl implements XmlRpcTranspor super(type); } - public Task[] getIssues(String request, int max, long since) { - try { - StringBuilder url = new StringBuilder(getUrl()); - String version = getServerVersion(); - if (version == null || StringUtil.compareVersionNumbers(myServerVersion, "3.7") < 0) { - url.append("/secure/IssueNavigator.jspa?view=rss&decorator=none&"); - } - else { - url.append("/sr/jira.issueviews:searchrequest-xml/temp/SearchRequest.xml?"); - } - url.append("tempMax=").append(max); - url.append("&assignee=").append(encodeUrl(getUsername())); + public Task[] getIssues(String request, int max, long since) throws Exception { + StringBuilder url = new StringBuilder(getUrl()); + String version = getServerVersion(); + if (version == null || StringUtil.compareVersionNumbers(myServerVersion, "3.7") < 0) { + url.append("/secure/IssueNavigator.jspa?view=rss&decorator=none&"); + } + else { + url.append("/sr/jira.issueviews:searchrequest-xml/temp/SearchRequest.xml?"); + } + url.append("tempMax=").append(max); + url.append("&assignee=").append(encodeUrl(getUsername())); // url.append("&resolution=-1"); - url.append("&reset=true"); - url.append("&sorter/field=").append("updated"); - url.append("&sorter/order=").append("DESC"); - url.append("&pager/start=").append(0); - appendAuthentication(url, false); + url.append("&reset=true"); + url.append("&sorter/field=").append("updated"); + url.append("&sorter/order=").append("DESC"); + url.append("&pager/start=").append(0); + appendAuthentication(url, false); - return processRSS(url.toString()); - } - catch (Exception e) { - LOG.info(e); - return new Task[0]; - } + return processRSS(url.toString()); } @Override @@ -160,15 +154,19 @@ public class JiraRepository extends BaseRepositoryImpl implements XmlRpcTranspor } } - private String getServerVersion() { + private String getServerVersion() throws Exception { if (myServerVersion == null) { try { Map map = (Map)doXmlRpcRequest("getServerInfo"); myServerVersion = (String)map.get("version"); } catch (Exception e) { + myServerVersion = "3.8"; LOG.warn(e); + if (e.getMessage().contains("Authentication")) { + throw e; + } } } return myServerVersion; diff --git a/plugins/tasks/tasks-core/src/com/intellij/tasks/impl/TaskManagerImpl.java b/plugins/tasks/tasks-core/src/com/intellij/tasks/impl/TaskManagerImpl.java index 3cb677729135..8e830373deca 100644 --- a/plugins/tasks/tasks-core/src/com/intellij/tasks/impl/TaskManagerImpl.java +++ b/plugins/tasks/tasks-core/src/com/intellij/tasks/impl/TaskManagerImpl.java @@ -1,8 +1,10 @@ package com.intellij.tasks.impl; +import com.intellij.notification.*; import com.intellij.openapi.application.ApplicationManager; import com.intellij.openapi.components.*; import com.intellij.openapi.diagnostic.Logger; +import com.intellij.openapi.options.ShowSettingsUtil; import com.intellij.openapi.progress.ProgressIndicator; import com.intellij.openapi.progress.ProgressManager; import com.intellij.openapi.project.Project; @@ -14,8 +16,10 @@ import com.intellij.openapi.util.text.StringUtil; import com.intellij.openapi.vcs.ProjectLevelVcsManager; import com.intellij.openapi.vcs.changes.*; import com.intellij.tasks.*; +import com.intellij.tasks.config.TaskRepositoriesConfigurable; import com.intellij.tasks.context.WorkingContextManager; import com.intellij.ui.ColoredTreeCellRenderer; +import com.intellij.util.ArrayUtil; import com.intellij.util.EventDispatcher; import com.intellij.util.Function; import com.intellij.util.containers.ContainerUtil; @@ -30,6 +34,7 @@ import org.jetbrains.annotations.NotNull; import org.jetbrains.annotations.Nullable; import javax.swing.Timer; +import javax.swing.event.HyperlinkEvent; import java.awt.event.ActionEvent; import java.awt.event.ActionListener; import java.text.DecimalFormat; @@ -93,6 +98,7 @@ public class TaskManagerImpl extends TaskManager implements ProjectComponent, Pe private final List myRepositories = new ArrayList(); private final EventDispatcher myDispatcher = EventDispatcher.create(TaskListener.class); + private Set myBadRepositories = new HashSet(); public TaskManagerImpl(Project project, WorkingContextManager contextManager, @@ -158,6 +164,10 @@ public class TaskManagerImpl extends TaskManager implements ProjectComponent, Pe public void setRepositories(List repositories) { + Set set = new HashSet(myRepositories); + set.removeAll(repositories); + myBadRepositories.removeAll(set); // remove all changed reps + myRepositories.clear(); myRepositories.addAll(repositories); @@ -617,8 +627,8 @@ public class TaskManagerImpl extends TaskManager implements ProjectComponent, Pe private List getIssuesFromRepositories(String request, int max, long since) { List issues = new ArrayList(); - for (TaskRepository repository : getAllRepositories()) { - if (!repository.isConfigured()) { + for (final TaskRepository repository : getAllRepositories()) { + if (!repository.isConfigured() || myBadRepositories.contains(repository)) { continue; } try { @@ -626,7 +636,20 @@ public class TaskManagerImpl extends TaskManager implements ProjectComponent, Pe ContainerUtil.addAll(issues, tasks); } catch (Exception e) { + myBadRepositories.add(repository); LOG.warn(e); + ApplicationManager.getApplication().getMessageBus().syncPublisher(Notifications.TOPIC).notify( + new Notification("Tasks", "Cannot connect to " + repository.getUrl(), + "

Configure server...

", NotificationType.WARNING, + new NotificationListener() { + public void hyperlinkUpdate(@NotNull Notification notification, @NotNull HyperlinkEvent event) { + TaskRepositoriesConfigurable configurable = new TaskRepositoriesConfigurable(myProject); + ShowSettingsUtil.getInstance().editConfigurable(myProject, configurable); + if (!ArrayUtil.contains(repository, getAllRepositories())) { + notification.expire(); + } + } + }), NotificationDisplayType.STICKY_BALLOON); } } return issues; From 570a506bc6b06b1f49eaee65a00ea14da7805a37 Mon Sep 17 00:00:00 2001 From: Dmitry Avdeev Date: Wed, 15 Dec 2010 16:38:04 +0300 Subject: [PATCH 49/54] better caching for tasks --- .../src/com/intellij/tasks/TaskManager.java | 13 +++++++- .../intellij/tasks/impl/TaskManagerImpl.java | 30 ++++++++++++------- 2 files changed, 31 insertions(+), 12 deletions(-) diff --git a/plugins/tasks/tasks-api/src/com/intellij/tasks/TaskManager.java b/plugins/tasks/tasks-api/src/com/intellij/tasks/TaskManager.java index b6f71294efe1..9139b7b85bcb 100644 --- a/plugins/tasks/tasks-api/src/com/intellij/tasks/TaskManager.java +++ b/plugins/tasks/tasks-api/src/com/intellij/tasks/TaskManager.java @@ -32,8 +32,19 @@ public abstract class TaskManager { return project.getComponent(TaskManager.class); } + /** + * Queries all configured task repositories. + * Operation may be blocked for a while. + * @param query text search + * @return up-to-date issues retrieved from repositories + * @see #getCachedIssues() + */ public abstract List getIssues(String query); + /** + * Returns already cached issues. + * @return cached issues. + */ public abstract List getCachedIssues(); @Nullable @@ -53,7 +64,7 @@ public abstract class TaskManager { /** * Update issue cache asynchronously - * @param onComplete + * @param onComplete callback to be invoked after updating */ public abstract void updateIssues(@Nullable Runnable onComplete); diff --git a/plugins/tasks/tasks-core/src/com/intellij/tasks/impl/TaskManagerImpl.java b/plugins/tasks/tasks-core/src/com/intellij/tasks/impl/TaskManagerImpl.java index 8e830373deca..94e5e49e6b5a 100644 --- a/plugins/tasks/tasks-core/src/com/intellij/tasks/impl/TaskManagerImpl.java +++ b/plugins/tasks/tasks-core/src/com/intellij/tasks/impl/TaskManagerImpl.java @@ -22,7 +22,7 @@ import com.intellij.ui.ColoredTreeCellRenderer; import com.intellij.util.ArrayUtil; import com.intellij.util.EventDispatcher; import com.intellij.util.Function; -import com.intellij.util.containers.ContainerUtil; +import com.intellij.util.containers.*; import com.intellij.util.xmlb.XmlSerializationException; import com.intellij.util.xmlb.XmlSerializer; import com.intellij.util.xmlb.XmlSerializerUtil; @@ -39,6 +39,8 @@ import java.awt.event.ActionEvent; import java.awt.event.ActionListener; import java.text.DecimalFormat; import java.util.*; +import java.util.HashMap; +import java.util.HashSet; /** @@ -62,12 +64,19 @@ public class TaskManagerImpl extends TaskManager implements ProjectComponent, Pe return i == 0 ? Comparing.compare(o2.getCreated(), o1.getCreated()) : i; } }; + private static final Convertor KEY_CONVERTOR = new Convertor() { + @Override + public String convert(Task o) { + return o.getId(); + } + }; private final Project myProject; private final WorkingContextManager myContextManager; private final Map myIssueCache = Collections.synchronizedMap(new HashMap()); + private final Map myTemporaryCache = Collections.synchronizedMap(new HashMap()); private final Map myTasks = Collections.synchronizedMap(new LinkedHashMap() { @Override @@ -212,19 +221,20 @@ public class TaskManagerImpl extends TaskManager implements ProjectComponent, Pe @Override public List getIssues(String query) { - if (myConfig.updateEnabled) { - synchronized (myIssueCache) { - return new ArrayList(myIssueCache.values()); - } - } else { - return getIssuesFromRepositories(query, 50, 0); + List tasks = getIssuesFromRepositories(query, 50, 0); + synchronized (myIssueCache) { + myTemporaryCache.clear(); + myTemporaryCache.putAll(ContainerUtil.assignKeys(tasks.iterator(), KEY_CONVERTOR)); } + return tasks; } @Override public List getCachedIssues() { synchronized (myIssueCache) { - return new ArrayList(myIssueCache.values()); + ArrayList tasks = new ArrayList(myIssueCache.values()); + tasks.addAll(myTemporaryCache.values()); + return tasks; } } @@ -596,9 +606,7 @@ public class TaskManagerImpl extends TaskManager implements ProjectComponent, Pe synchronized (myIssueCache) { myIssueCache.clear(); - for (Task issue : issues) { - myIssueCache.put(issue.getId(), issue); - } + myIssueCache.putAll(ContainerUtil.assignKeys(issues.iterator(), KEY_CONVERTOR)); } // update local tasks synchronized (myTasks) { From 24ed10a8929f631b42cb521d13de81227ca28506 Mon Sep 17 00:00:00 2001 From: Dmitry Avdeev Date: Thu, 16 Dec 2010 14:31:40 +0300 Subject: [PATCH 50/54] test fixed --- .../tasks-core/src/com/intellij/tasks/impl/TaskManagerImpl.java | 2 ++ .../tasks-tests/test/com/intellij/tasks/TaskCompletionTest.java | 2 +- 2 files changed, 3 insertions(+), 1 deletion(-) diff --git a/plugins/tasks/tasks-core/src/com/intellij/tasks/impl/TaskManagerImpl.java b/plugins/tasks/tasks-core/src/com/intellij/tasks/impl/TaskManagerImpl.java index 94e5e49e6b5a..770f88d9c034 100644 --- a/plugins/tasks/tasks-core/src/com/intellij/tasks/impl/TaskManagerImpl.java +++ b/plugins/tasks/tasks-core/src/com/intellij/tasks/impl/TaskManagerImpl.java @@ -176,6 +176,8 @@ public class TaskManagerImpl extends TaskManager implements ProjectComponent, Pe Set set = new HashSet(myRepositories); set.removeAll(repositories); myBadRepositories.removeAll(set); // remove all changed reps + myIssueCache.clear(); + myTemporaryCache.clear(); myRepositories.clear(); myRepositories.addAll(repositories); diff --git a/plugins/tasks/tasks-tests/test/com/intellij/tasks/TaskCompletionTest.java b/plugins/tasks/tasks-tests/test/com/intellij/tasks/TaskCompletionTest.java index 999611999a25..5a891420757f 100644 --- a/plugins/tasks/tasks-tests/test/com/intellij/tasks/TaskCompletionTest.java +++ b/plugins/tasks/tasks-tests/test/com/intellij/tasks/TaskCompletionTest.java @@ -36,7 +36,7 @@ public class TaskCompletionTest extends LightCodeInsightFixtureTestCase { } public void testSIOOBE() throws Exception { - doTest(" my ", " TEST-001: Test task my"); + doTest(" my", " TEST-001: Test task my"); } private void doTest(String text, String after) { From 8d8e603e0616e7f3936abbf99dd74ab9d7e7e942 Mon Sep 17 00:00:00 2001 From: Maxim Shafirov Date: Thu, 16 Dec 2010 14:42:05 +0300 Subject: [PATCH 51/54] Delete/Backspace remove unexpanable folding all together. --- .../openapi/editor/actions/BackspaceAction.java | 12 ++++++++++-- .../openapi/editor/actions/DeleteAction.java | 15 +++++++++++---- 2 files changed, 21 insertions(+), 6 deletions(-) diff --git a/platform/platform-impl/src/com/intellij/openapi/editor/actions/BackspaceAction.java b/platform/platform-impl/src/com/intellij/openapi/editor/actions/BackspaceAction.java index 86b8b771ee11..ac2e83ba850e 100644 --- a/platform/platform-impl/src/com/intellij/openapi/editor/actions/BackspaceAction.java +++ b/platform/platform-impl/src/com/intellij/openapi/editor/actions/BackspaceAction.java @@ -83,8 +83,16 @@ public class BackspaceAction extends EditorAction { int offset = editor.getCaretModel().getOffset(); editor.getScrollingModel().scrollToCaret(ScrollType.RELATIVE); editor.getSelectionModel().removeSelection(); - document.deleteString(offset-1, offset); - editor.getCaretModel().moveToOffset(offset - 1, true); + + FoldRegion region = editor.getFoldingModel().getCollapsedRegionAtOffset(offset - 1); + if (region != null && region.shouldNeverExpand()) { + document.deleteString(region.getStartOffset(), region.getEndOffset()); + editor.getCaretModel().moveToOffset(region.getStartOffset()); + } + else { + document.deleteString(offset - 1, offset); + editor.getCaretModel().moveToOffset(offset - 1, true); + } } } else if(lineNumber > 0) { diff --git a/platform/platform-impl/src/com/intellij/openapi/editor/actions/DeleteAction.java b/platform/platform-impl/src/com/intellij/openapi/editor/actions/DeleteAction.java index 6bfb0a282bed..b5d9ad63f2b1 100644 --- a/platform/platform-impl/src/com/intellij/openapi/editor/actions/DeleteAction.java +++ b/platform/platform-impl/src/com/intellij/openapi/editor/actions/DeleteAction.java @@ -96,12 +96,19 @@ public class DeleteAction extends EditorAction { Document document = editor.getDocument(); if(afterLineEnd < 0) { int offset = editor.getCaretModel().getOffset(); - document.deleteString(offset, offset + 1); - editor.getCaretModel().moveToOffset(offset); + FoldRegion region = editor.getFoldingModel().getCollapsedRegionAtOffset(offset); + if (region != null && region.shouldNeverExpand()) { + document.deleteString(region.getStartOffset(), region.getEndOffset()); + editor.getCaretModel().moveToOffset(region.getStartOffset()); + } + else { + document.deleteString(offset, offset + 1); + editor.getCaretModel().moveToOffset(offset); + } return; } - if(lineNumber + 1 >= document.getLineCount()) - return; + + if(lineNumber + 1 >= document.getLineCount()) return; // Do not group delete newline and other deletions. CommandProcessor commandProcessor = CommandProcessor.getInstance(); From d6cbb62dcfd8a01f6aa16f04a5dbb0c06c22038c Mon Sep 17 00:00:00 2001 From: Eugene Zhuravlev Date: Thu, 16 Dec 2010 15:30:39 +0300 Subject: [PATCH 52/54] [r=nik] fixed broken functionality: if there were compile errors, find dependencies of actually compiled and mark them for compilation for the next time --- .../src/com/intellij/compiler/impl/CompileDriver.java | 8 ++++---- 1 file changed, 4 insertions(+), 4 deletions(-) diff --git a/java/compiler/impl/src/com/intellij/compiler/impl/CompileDriver.java b/java/compiler/impl/src/com/intellij/compiler/impl/CompileDriver.java index dd503c74277e..5cbc5fea985e 100644 --- a/java/compiler/impl/src/com/intellij/compiler/impl/CompileDriver.java +++ b/java/compiler/impl/src/com/intellij/compiler/impl/CompileDriver.java @@ -1038,12 +1038,12 @@ public class CompileDriver { generatedTypes.addAll(compilerManager.getRegisteredOutputTypes(compiler)); } - if (_context.getMessageCount(CompilerMessageCategory.ERROR) > 0) { - throw new ExitException(ExitStatus.ERRORS); - } - didSomething |= compiledSomething; compiledSomethingForThisChunk |= didSomething; + + if (_context.getMessageCount(CompilerMessageCategory.ERROR) > 0) { + break; // break the loop over compilers + } } final boolean hasUnprocessedTraverseRoots = context.getDependencyCache().hasUnprocessedTraverseRoots(); From 6652fe5b15c7014ccced2a36e24ff5f6bcaab40e Mon Sep 17 00:00:00 2001 From: Eugene Zhuravlev Date: Thu, 16 Dec 2010 15:32:20 +0300 Subject: [PATCH 53/54] big read action removed --- .../ui/breakpoints/LineBreakpoint.java | 90 +++++++++---------- 1 file changed, 43 insertions(+), 47 deletions(-) diff --git a/java/debugger/impl/src/com/intellij/debugger/ui/breakpoints/LineBreakpoint.java b/java/debugger/impl/src/com/intellij/debugger/ui/breakpoints/LineBreakpoint.java index 472402354c00..9ea0bfe2ba0c 100644 --- a/java/debugger/impl/src/com/intellij/debugger/ui/breakpoints/LineBreakpoint.java +++ b/java/debugger/impl/src/com/intellij/debugger/ui/breakpoints/LineBreakpoint.java @@ -127,59 +127,55 @@ public class LineBreakpoint extends BreakpointWithHighlighter { if (!isInScopeOf(debugProcess, classType.name())) { return; } - ApplicationManager.getApplication().runReadAction(new Runnable() { - public void run() { - try { - List locs = debugProcess.getPositionManager().locationsOfLine(classType, getSourcePosition()); - if (locs.size() > 0) { - for (final Location location : locs) { - if (LOG.isDebugEnabled()) { - LOG.debug("Found location for reference type " + classType.name() + " at line " + getLineIndex() + "; isObsolete: " + (debugProcess.getVirtualMachineProxy().versionHigher("1.4") && location.method().isObsolete())); - } - BreakpointRequest request = debugProcess.getRequestsManager().createBreakpointRequest(LineBreakpoint.this, location); - debugProcess.getRequestsManager().enableRequest(request); - if (LOG.isDebugEnabled()) { - LOG.debug("Created breakpoint request for reference type " + classType.name() + " at line " + getLineIndex()); - } - } - } - else { - // there's no executable code in this class - debugProcess.getRequestsManager().setInvalid(LineBreakpoint.this, DebuggerBundle.message( - "error.invalid.breakpoint.no.executable.code", (getLineIndex() + 1), classType.name()) - ); - if (LOG.isDebugEnabled()) { - LOG.debug("No locations of type " + classType.name() + " found at line " + getLineIndex()); - } - } - } - catch (ClassNotPreparedException ex) { + try { + List locs = debugProcess.getPositionManager().locationsOfLine(classType, getSourcePosition()); + if (locs.size() > 0) { + for (final Location location : locs) { if (LOG.isDebugEnabled()) { - LOG.debug("ClassNotPreparedException: " + ex.getMessage()); + LOG.debug("Found location for reference type " + classType.name() + " at line " + getLineIndex() + "; isObsolete: " + (debugProcess.getVirtualMachineProxy().versionHigher("1.4") && location.method().isObsolete())); } - // there's a chance to add a breakpoint when the class is prepared - } - catch (ObjectCollectedException ex) { + BreakpointRequest request = debugProcess.getRequestsManager().createBreakpointRequest(LineBreakpoint.this, location); + debugProcess.getRequestsManager().enableRequest(request); if (LOG.isDebugEnabled()) { - LOG.debug("ObjectCollectedException: " + ex.getMessage()); + LOG.debug("Created breakpoint request for reference type " + classType.name() + " at line " + getLineIndex()); } - // there's a chance to add a breakpoint when the class is prepared } - catch (InvalidLineNumberException ex) { - if (LOG.isDebugEnabled()) { - LOG.debug("InvalidLineNumberException: " + ex.getMessage()); - } - debugProcess.getRequestsManager().setInvalid(LineBreakpoint.this, DebuggerBundle.message("error.invalid.breakpoint.bad.line.number")); - } - catch (InternalException ex) { - LOG.info(ex); - } - catch(Exception ex) { - LOG.info(ex); - } - updateUI(); } - }); + else { + // there's no executable code in this class + debugProcess.getRequestsManager().setInvalid(LineBreakpoint.this, DebuggerBundle.message( + "error.invalid.breakpoint.no.executable.code", (getLineIndex() + 1), classType.name()) + ); + if (LOG.isDebugEnabled()) { + LOG.debug("No locations of type " + classType.name() + " found at line " + getLineIndex()); + } + } + } + catch (ClassNotPreparedException ex) { + if (LOG.isDebugEnabled()) { + LOG.debug("ClassNotPreparedException: " + ex.getMessage()); + } + // there's a chance to add a breakpoint when the class is prepared + } + catch (ObjectCollectedException ex) { + if (LOG.isDebugEnabled()) { + LOG.debug("ObjectCollectedException: " + ex.getMessage()); + } + // there's a chance to add a breakpoint when the class is prepared + } + catch (InvalidLineNumberException ex) { + if (LOG.isDebugEnabled()) { + LOG.debug("InvalidLineNumberException: " + ex.getMessage()); + } + debugProcess.getRequestsManager().setInvalid(LineBreakpoint.this, DebuggerBundle.message("error.invalid.breakpoint.bad.line.number")); + } + catch (InternalException ex) { + LOG.info(ex); + } + catch(Exception ex) { + LOG.info(ex); + } + updateUI(); } private boolean isInScopeOf(DebugProcessImpl debugProcess, String className) { From 2957c2d05e8d8574e457e4be59f26775993bb9c8 Mon Sep 17 00:00:00 2001 From: Maxim Shafirov Date: Thu, 16 Dec 2010 15:37:14 +0300 Subject: [PATCH 54/54] Lookahead is now aware of whitespace and comment tokens that should not be count --- .../src/com/intellij/lang/impl/PsiBuilderImpl.java | 13 +++++++++++-- 1 file changed, 11 insertions(+), 2 deletions(-) diff --git a/platform/lang-impl/src/com/intellij/lang/impl/PsiBuilderImpl.java b/platform/lang-impl/src/com/intellij/lang/impl/PsiBuilderImpl.java index 522c70575b82..5d9f5e95ea24 100644 --- a/platform/lang-impl/src/com/intellij/lang/impl/PsiBuilderImpl.java +++ b/platform/lang-impl/src/com/intellij/lang/impl/PsiBuilderImpl.java @@ -620,8 +620,17 @@ public class PsiBuilderImpl extends UserDataHolderBase implements PsiBuilder { @Nullable @Override public IElementType lookAhead(int steps) { - if (steps + myCurrentLexeme >= myLexemeCount) return null; - return myLexTypes[myCurrentLexeme + steps]; + int cur = myCurrentLexeme; + + while (steps > 0) { + while (cur < myLexemeCount && whitespaceOrComment(myLexTypes[cur])) { + cur++; + } + + steps--; + } + + return cur < myLexemeCount ? myLexTypes[cur] : null; } @Override