From 2a261417c7eefacaeb3b456d1bc273afd523105f Mon Sep 17 00:00:00 2001 From: Anton Makeev Date: Tue, 5 Apr 2011 17:00:17 +0200 Subject: [PATCH 01/65] CIDR: threads switched "fixed" --- .../src/com/intellij/xdebugger/ui/DebuggerIcons.java | 1 + 1 file changed, 1 insertion(+) diff --git a/platform/xdebugger-api/src/com/intellij/xdebugger/ui/DebuggerIcons.java b/platform/xdebugger-api/src/com/intellij/xdebugger/ui/DebuggerIcons.java index c936776967a1..323228d1f6ba 100644 --- a/platform/xdebugger-api/src/com/intellij/xdebugger/ui/DebuggerIcons.java +++ b/platform/xdebugger-api/src/com/intellij/xdebugger/ui/DebuggerIcons.java @@ -42,5 +42,6 @@ public interface DebuggerIcons { Icon WATCHED_VALUE_ICON = IconLoader.getIcon("/debugger/watch.png"); Icon STACK_FRAME_ICON = IconLoader.getIcon("/debugger/stackFrame.png"); + Icon CURRENT_THREAD_ICON = IconLoader.getIcon("/debugger/threadCurrent.png"); Icon SUSPENDED_THREAD_ICON = IconLoader.getIcon("/debugger/threadSuspended.png"); } From 04baa6e85d5da1210b24f3a3b0742dbfe7ba9a34 Mon Sep 17 00:00:00 2001 From: Sergey Evdokimov Date: Tue, 5 Apr 2011 19:00:09 +0400 Subject: [PATCH 02/65] Remove dead code. --- plugins/groovy/src/META-INF/plugin.xml | 1 - ...vyEventListenersNamedArgumentProvider.java | 71 ------------------- 2 files changed, 72 deletions(-) delete mode 100644 plugins/groovy/src/org/jetbrains/plugins/groovy/lang/GroovyEventListenersNamedArgumentProvider.java diff --git a/plugins/groovy/src/META-INF/plugin.xml b/plugins/groovy/src/META-INF/plugin.xml index 8e67cf558959..6d7eb36e55f2 100644 --- a/plugins/groovy/src/META-INF/plugin.xml +++ b/plugins/groovy/src/META-INF/plugin.xml @@ -72,7 +72,6 @@ - diff --git a/plugins/groovy/src/org/jetbrains/plugins/groovy/lang/GroovyEventListenersNamedArgumentProvider.java b/plugins/groovy/src/org/jetbrains/plugins/groovy/lang/GroovyEventListenersNamedArgumentProvider.java deleted file mode 100644 index ff725f647476..000000000000 --- a/plugins/groovy/src/org/jetbrains/plugins/groovy/lang/GroovyEventListenersNamedArgumentProvider.java +++ /dev/null @@ -1,71 +0,0 @@ -/* - * Copyright 2000-2011 JetBrains s.r.o. - * - * Licensed under the Apache License, Version 2.0 (the "License"); - * you may not use this file except in compliance with the License. - * You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - */ -package org.jetbrains.plugins.groovy.lang; - -import com.intellij.codeInsight.lookup.LookupElementBuilder; -import com.intellij.psi.*; -import com.intellij.psi.util.InheritanceUtil; -import org.jetbrains.annotations.NotNull; -import org.jetbrains.annotations.Nullable; -import org.jetbrains.plugins.groovy.GroovyIcons; -import org.jetbrains.plugins.groovy.extensions.GroovyNamedArgumentProvider; -import org.jetbrains.plugins.groovy.lang.completion.handlers.NamedArgumentInsertHandler; -import org.jetbrains.plugins.groovy.lang.psi.api.statements.expressions.GrCall; -import org.jetbrains.plugins.groovy.lang.psi.api.statements.typedef.members.GrConstructor; - -import java.util.Map; - -/** - * @author Sergey Evdokimov - */ -public class GroovyEventListenersNamedArgumentProvider extends GroovyNamedArgumentProvider { - @Override - public void getNamedArguments(@NotNull GrCall call, - @Nullable PsiMethod method, - @Nullable String argumentName, - boolean forCompletion, - Map result) { - // TODO IDEA-67465 - - //if (!forCompletion || method == null || method instanceof GrConstructor) return; - // - //PsiClass aClass = method.getContainingClass(); - //if (aClass == null) return; - // - //for (PsiMethod m : aClass.getAllMethods()) { - // if (m.getName().startsWith("add") && method.getParameterList().getParametersCount() == 1) { - // final PsiParameter parameter = method.getParameterList().getParameters()[0]; - // final PsiType type = parameter.getType(); - // if (type instanceof PsiClassType) { - // final PsiClassType classType = (PsiClassType)type; - // final PsiClass listenerClass = classType.resolve(); - // if (listenerClass != null) { - // if (InheritanceUtil.isInheritor(listenerClass, "java.util.EventListener")) { - // PsiMethod[] listenerMethods = listenerClass.getMethods(); - // for (PsiMethod listenerMethod : listenerMethods) { - // final String name = listenerMethod.getName(); - // - // ArgumentDescriptor oldValue = result.put(name, TYPE_ANY); - // if (oldValue != null) result.put(name, oldValue); - // } - // } - // } - // } - // } - // - //} - } -} From 20d9ca03535cd371ca2543410ee79cc53994e019 Mon Sep 17 00:00:00 2001 From: "Maxim.Mossienko" Date: Tue, 5 Apr 2011 14:30:56 +0400 Subject: [PATCH 03/65] less size of document for skipping reparse during whole file replacement --- .../src/com/intellij/psi/impl/PsiDocumentManagerImpl.java | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) 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 78a7ed91b58e..f5c0475e4f46 100644 --- a/platform/lang-impl/src/com/intellij/psi/impl/PsiDocumentManagerImpl.java +++ b/platform/lang-impl/src/com/intellij/psi/impl/PsiDocumentManagerImpl.java @@ -623,7 +623,7 @@ public class PsiDocumentManagerImpl extends PsiDocumentManager implements Projec // Consider that it's worth to perform complete re-parse instead of merge if the whole document text is replaced and // current document lines number is roughly above 5000. This makes sense in situations when external change is performed // for the huge file (that causes the whole document to be reloaded and 'merge' way takes a while to complete). - if (event.isWholeTextReplaced() && document.getTextLength() > 500000) { + if (event.isWholeTextReplaced() && document.getTextLength() > 100000) { document.putUserData(BlockSupport.DO_NOT_REPARSE_INCREMENTALLY, Boolean.TRUE); } From f3284a336c4ea453dead71ed93eb984e0af9e0a4 Mon Sep 17 00:00:00 2001 From: Maxim Shafirov Date: Tue, 5 Apr 2011 19:49:54 +0400 Subject: [PATCH 04/65] Create OC files while renaming OC files. --- .../psi/impl/source/PostprocessReformattingAspect.java | 3 +++ 1 file changed, 3 insertions(+) diff --git a/platform/lang-impl/src/com/intellij/psi/impl/source/PostprocessReformattingAspect.java b/platform/lang-impl/src/com/intellij/psi/impl/source/PostprocessReformattingAspect.java index abaf335880ff..49e2c6ba8c26 100644 --- a/platform/lang-impl/src/com/intellij/psi/impl/source/PostprocessReformattingAspect.java +++ b/platform/lang-impl/src/com/intellij/psi/impl/source/PostprocessReformattingAspect.java @@ -217,6 +217,9 @@ public class PostprocessReformattingAspect implements PomModelAspect, Disposable doPostponedFormatting(viewProvider); } } + catch (Exception e) { + LOG.error(e); + } finally { LOG.assertTrue(myReformatElements.isEmpty()); } From 37d1a1e7231ad91c499868aa8e01aa3bd8c0786c Mon Sep 17 00:00:00 2001 From: Dmitry Trofimov Date: Fri, 1 Apr 2011 13:08:19 +0400 Subject: [PATCH 05/65] Fixed bug with history stop working after executing empty last history item (PY-3232). --- .../execution/runners/ConsoleExecuteActionHandler.java | 5 ++--- 1 file changed, 2 insertions(+), 3 deletions(-) diff --git a/platform/lang-impl/src/com/intellij/execution/runners/ConsoleExecuteActionHandler.java b/platform/lang-impl/src/com/intellij/execution/runners/ConsoleExecuteActionHandler.java index 8b0db9e4694d..3e3c1f8e5ccd 100644 --- a/platform/lang-impl/src/com/intellij/execution/runners/ConsoleExecuteActionHandler.java +++ b/platform/lang-impl/src/com/intellij/execution/runners/ConsoleExecuteActionHandler.java @@ -60,9 +60,8 @@ public class ConsoleExecuteActionHandler { languageConsole.addCurrentToHistory(range, false, myPreserveMarkup); } languageConsole.setInputText(""); - if (!StringUtil.isEmptyOrSpaces(text)) { - myConsoleHistoryModel.addToHistory(text); - } + + myConsoleHistoryModel.addToHistory(text); // Send to interpreter / server processLine(text); From fb1dc921bb5f23adbac96a8f71159aeae489e869 Mon Sep 17 00:00:00 2001 From: Dmitry Trofimov Date: Fri, 1 Apr 2011 16:31:58 +0400 Subject: [PATCH 06/65] NPE fixed. --- .../src/com/intellij/openapi/module/ModuleServiceManager.java | 4 +++- 1 file changed, 3 insertions(+), 1 deletion(-) diff --git a/platform/lang-api/src/com/intellij/openapi/module/ModuleServiceManager.java b/platform/lang-api/src/com/intellij/openapi/module/ModuleServiceManager.java index 3ad759137240..da0c3855fa0f 100644 --- a/platform/lang-api/src/com/intellij/openapi/module/ModuleServiceManager.java +++ b/platform/lang-api/src/com/intellij/openapi/module/ModuleServiceManager.java @@ -16,6 +16,8 @@ package com.intellij.openapi.module; +import org.jetbrains.annotations.NotNull; + /** * @author yole */ @@ -23,7 +25,7 @@ public class ModuleServiceManager { private ModuleServiceManager() { } - public static T getService(Module module, Class serviceClass) { + public static T getService(@NotNull Module module, @NotNull Class serviceClass) { return (T)module.getPicoContainer().getComponentInstance(serviceClass.getName()); } } \ No newline at end of file From 983f99eb0d4898d3c4aa06880b965be1973ba68e Mon Sep 17 00:00:00 2001 From: Dmitry Trofimov Date: Tue, 5 Apr 2011 10:53:07 +0400 Subject: [PATCH 07/65] Fixed bug with empty string adding (PY-3232). --- .../execution/process/ConsoleHistoryModel.java | 14 +++++++++----- 1 file changed, 9 insertions(+), 5 deletions(-) diff --git a/platform/platform-impl/src/com/intellij/execution/process/ConsoleHistoryModel.java b/platform/platform-impl/src/com/intellij/execution/process/ConsoleHistoryModel.java index 0e562906b9d4..385b0bb2d862 100644 --- a/platform/platform-impl/src/com/intellij/execution/process/ConsoleHistoryModel.java +++ b/platform/platform-impl/src/com/intellij/execution/process/ConsoleHistoryModel.java @@ -2,6 +2,7 @@ package com.intellij.execution.process; import com.intellij.ide.ui.UISettings; import com.intellij.openapi.util.ModificationTracker; +import com.intellij.openapi.util.text.StringUtil; import org.jetbrains.annotations.Nullable; import java.util.ArrayList; @@ -21,11 +22,14 @@ public class ConsoleHistoryModel implements ModificationTracker { public void addToHistory(final String statement) { final int maxHistorySize = getMaxHistorySize(); synchronized (myHistory) { - removeFromHistory(statement); - if (myHistory.size() >= maxHistorySize) { - myHistory.removeLast(); + myHistoryCursor = -1; + if (!StringUtil.isEmptyOrSpaces(statement)) { + removeFromHistory(statement); + if (myHistory.size() >= maxHistorySize) { + myHistory.removeLast(); + } + myHistory.addFirst(statement); } - myHistory.addFirst(statement); } } @@ -36,7 +40,7 @@ public class ConsoleHistoryModel implements ModificationTracker { public void removeFromHistory(final String statement) { synchronized (myHistory) { myModificationTracker++; - myHistoryCursor = -1; + myHistory.remove(statement); } } From b71b80db234d25caa3e1cfa23505f2f5ee1d4035 Mon Sep 17 00:00:00 2001 From: Konstantin Bulenkov Date: Tue, 5 Apr 2011 20:03:03 +0400 Subject: [PATCH 08/65] remove only added highlighter --- .../internal/psiView/PsiViewerDialog.java | 16 ++++++++-------- 1 file changed, 8 insertions(+), 8 deletions(-) diff --git a/platform/lang-impl/src/com/intellij/internal/psiView/PsiViewerDialog.java b/platform/lang-impl/src/com/intellij/internal/psiView/PsiViewerDialog.java index 1dd56eedd869..09974f4929db 100644 --- a/platform/lang-impl/src/com/intellij/internal/psiView/PsiViewerDialog.java +++ b/platform/lang-impl/src/com/intellij/internal/psiView/PsiViewerDialog.java @@ -646,6 +646,7 @@ public class PsiViewerDialog extends DialogWrapper implements DataProvider { private class MyTreeSelectionListener implements TreeSelectionListener { private final TextAttributes myAttributes; + private RangeHighlighter myHighlighter; public MyTreeSelectionListener() { myAttributes = new TextAttributes(); @@ -656,11 +657,8 @@ public class PsiViewerDialog extends DialogWrapper implements DataProvider { public void valueChanged(TreeSelectionEvent e) { if (!myEditor.getDocument().getText().equals(myLastParsedText)) return; TreePath path = myTree.getSelectionPath(); - if (path == null) { - clearSelection(); - } - else { - clearSelection(); + clearSelection(); + if (path != null) { DefaultMutableTreeNode node = (DefaultMutableTreeNode)path.getLastPathComponent(); if (!(node.getUserObject() instanceof ViewerNodeDescriptor)) return; ViewerNodeDescriptor descriptor = (ViewerNodeDescriptor)node.getUserObject(); @@ -684,8 +682,7 @@ public class PsiViewerDialog extends DialogWrapper implements DataProvider { final int textLength = myEditor.getDocument().getTextLength(); if (end <= textLength) { - myEditor.getMarkupModel() - .addRangeHighlighter(start, end, HighlighterLayer.LAST, myAttributes, HighlighterTargetArea.EXACT_RANGE); + myHighlighter = myEditor.getMarkupModel().addRangeHighlighter(start, end, HighlighterLayer.LAST, myAttributes, HighlighterTargetArea.EXACT_RANGE); if (myTree.hasFocus()) { myEditor.getCaretModel().moveToOffset(start); myEditor.getScrollingModel().scrollToCaret(ScrollType.MAKE_VISIBLE); @@ -716,7 +713,10 @@ public class PsiViewerDialog extends DialogWrapper implements DataProvider { } private void clearSelection() { - myEditor.getMarkupModel().removeAllHighlighters(); + if (myHighlighter != null) { + myEditor.getMarkupModel().removeHighlighter(myHighlighter); + myHighlighter.dispose(); + } } } From de9457b479b6a24a711f6583c84bdd6b6dac3093 Mon Sep 17 00:00:00 2001 From: Alexey Pegov Date: Tue, 5 Apr 2011 20:11:05 +0400 Subject: [PATCH 09/65] minor --- platform/platform-api/src/com/intellij/openapi/ui/Messages.java | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/platform/platform-api/src/com/intellij/openapi/ui/Messages.java b/platform/platform-api/src/com/intellij/openapi/ui/Messages.java index 18465d3167ca..b748b825aa73 100644 --- a/platform/platform-api/src/com/intellij/openapi/ui/Messages.java +++ b/platform/platform-api/src/com/intellij/openapi/ui/Messages.java @@ -251,7 +251,7 @@ public class Messages { new PairFunction() { @Override public Integer fun(final Integer exitCode, final JCheckBox cb) { - return exitCode == CANCEL ? CANCEL : exitCode + (cb.isSelected() ? 1 : 0); + return exitCode == -1 ? CANCEL : exitCode + (cb.isSelected() ? 1 : 0); } }); } From dde2360a0cd77635ea29cf6546eada3368bdb0c4 Mon Sep 17 00:00:00 2001 From: anna Date: Tue, 5 Apr 2011 16:34:30 +0200 Subject: [PATCH 10/65] keep spaces (IDEA-67541 ) --- .../quickfix/CreateLocalFromUsageFix.java | 26 +++++++++++++++---- .../afterTypeArgsFormatted.java | 12 +++++++++ .../beforeTypeArgsFormatted.java | 11 ++++++++ 3 files changed, 44 insertions(+), 5 deletions(-) create mode 100644 java/java-tests/testData/codeInsight/daemonCodeAnalyzer/quickFix/createLocalFromUsage/afterTypeArgsFormatted.java create mode 100644 java/java-tests/testData/codeInsight/daemonCodeAnalyzer/quickFix/createLocalFromUsage/beforeTypeArgsFormatted.java diff --git a/java/java-impl/src/com/intellij/codeInsight/daemon/impl/quickfix/CreateLocalFromUsageFix.java b/java/java-impl/src/com/intellij/codeInsight/daemon/impl/quickfix/CreateLocalFromUsageFix.java index f309dfeaf3e7..e5908b776055 100644 --- a/java/java-impl/src/com/intellij/codeInsight/daemon/impl/quickfix/CreateLocalFromUsageFix.java +++ b/java/java-impl/src/com/intellij/codeInsight/daemon/impl/quickfix/CreateLocalFromUsageFix.java @@ -20,12 +20,15 @@ import com.intellij.codeInsight.daemon.QuickFixBundle; import com.intellij.codeInsight.intention.impl.TypeExpression; import com.intellij.codeInsight.template.Template; import com.intellij.codeInsight.template.TemplateBuilderImpl; +import com.intellij.codeInsight.template.TemplateEditingAdapter; import com.intellij.codeInsight.template.TemplateManager; +import com.intellij.openapi.application.ApplicationManager; import com.intellij.openapi.diagnostic.Logger; import com.intellij.openapi.editor.Editor; import com.intellij.openapi.project.Project; import com.intellij.openapi.util.TextRange; import com.intellij.psi.*; +import com.intellij.psi.codeStyle.CodeStyleManager; import com.intellij.psi.codeStyle.CodeStyleSettingsManager; import com.intellij.psi.util.PsiTreeUtil; import com.intellij.psi.util.PsiUtil; @@ -59,10 +62,10 @@ public class CreateLocalFromUsageFix extends CreateVarFromUsageFix { return; } - Project project = myReferenceExpression.getProject(); + final Project project = myReferenceExpression.getProject(); PsiElementFactory factory = JavaPsiFacade.getInstance(project).getElementFactory(); - PsiFile targetFile = targetClass.getContainingFile(); + final PsiFile targetFile = targetClass.getContainingFile(); PsiType[] expectedTypes = CreateFromUsageUtils.guessType(myReferenceExpression, false); PsiType type = expectedTypes[0]; @@ -104,12 +107,25 @@ public class CreateLocalFromUsageFix extends CreateVarFromUsageFix { builder.setEndVariableAfter(var.getNameIdentifier()); Template template = builder.buildTemplate(); - Editor newEditor = positionCursor(project, targetFile, var); + final Editor newEditor = positionCursor(project, targetFile, var); TextRange range = var.getTextRange(); newEditor.getDocument().deleteString(range.getStartOffset(), range.getEndOffset()); - TemplateManager manager = TemplateManager.getInstance(project); - manager.startTemplate(newEditor, template); + startTemplate(newEditor, template, project, new TemplateEditingAdapter() { + @Override + public void templateFinished(Template template, boolean brokenOff) { + PsiDocumentManager.getInstance(project).commitDocument(newEditor.getDocument()); + final int offset = newEditor.getCaretModel().getOffset(); + final PsiLocalVariable localVariable = PsiTreeUtil.findElementOfClassAtOffset(targetFile, offset, PsiLocalVariable.class, false); + if (localVariable != null) { + ApplicationManager.getApplication().runWriteAction(new Runnable() { + public void run() { + CodeStyleManager.getInstance(project).reformat(localVariable); + } + }); + } + } + }); } protected boolean isAllowOuterTargetClass() { diff --git a/java/java-tests/testData/codeInsight/daemonCodeAnalyzer/quickFix/createLocalFromUsage/afterTypeArgsFormatted.java b/java/java-tests/testData/codeInsight/daemonCodeAnalyzer/quickFix/createLocalFromUsage/afterTypeArgsFormatted.java new file mode 100644 index 000000000000..c9ebd859d267 --- /dev/null +++ b/java/java-tests/testData/codeInsight/daemonCodeAnalyzer/quickFix/createLocalFromUsage/afterTypeArgsFormatted.java @@ -0,0 +1,12 @@ +// "Create Local Variable 'field'" "true" +import java.util.*; +class A { + void foo(Map s){} + + void bar() { + Map field; + foo(field); + } + +} + diff --git a/java/java-tests/testData/codeInsight/daemonCodeAnalyzer/quickFix/createLocalFromUsage/beforeTypeArgsFormatted.java b/java/java-tests/testData/codeInsight/daemonCodeAnalyzer/quickFix/createLocalFromUsage/beforeTypeArgsFormatted.java new file mode 100644 index 000000000000..a0355cd11bcb --- /dev/null +++ b/java/java-tests/testData/codeInsight/daemonCodeAnalyzer/quickFix/createLocalFromUsage/beforeTypeArgsFormatted.java @@ -0,0 +1,11 @@ +// "Create Local Variable 'field'" "true" +import java.util.*; +class A { + void foo(Map s){} + + void bar() { + foo(field); + } + +} + From b3ecfc601fc2f54fee6da3a31fa8690a7e888590 Mon Sep 17 00:00:00 2001 From: anna Date: Tue, 5 Apr 2011 17:35:28 +0200 Subject: [PATCH 11/65] perform automatic rename over valid element (IDEA-67481) --- .../inplace/VariableInplaceRenamer.java | 21 ++++++++++++++----- 1 file changed, 16 insertions(+), 5 deletions(-) diff --git a/platform/lang-impl/src/com/intellij/refactoring/rename/inplace/VariableInplaceRenamer.java b/platform/lang-impl/src/com/intellij/refactoring/rename/inplace/VariableInplaceRenamer.java index 5b0e601e695c..787876bee14e 100644 --- a/platform/lang-impl/src/com/intellij/refactoring/rename/inplace/VariableInplaceRenamer.java +++ b/platform/lang-impl/src/com/intellij/refactoring/rename/inplace/VariableInplaceRenamer.java @@ -32,6 +32,7 @@ import com.intellij.openapi.application.ApplicationManager; import com.intellij.openapi.command.CommandProcessor; import com.intellij.openapi.diagnostic.Logger; import com.intellij.openapi.editor.Editor; +import com.intellij.openapi.editor.RangeMarker; import com.intellij.openapi.editor.SelectionModel; import com.intellij.openapi.editor.colors.EditorColors; import com.intellij.openapi.editor.colors.EditorColorsManager; @@ -95,6 +96,7 @@ public class VariableInplaceRenamer { private ArrayList myHighlighters; private final Editor myEditor; private final Project myProject; + private RangeMarker myRenameOffset; public void setAdvertisementText(String advertisementText) { myAdvertisementText = advertisementText; @@ -108,6 +110,7 @@ public class VariableInplaceRenamer { myElementToRename = elementToRename; myEditor = /*(editor instanceof EditorWindow)? ((EditorWindow)editor).getDelegate() : */editor; myProject = myElementToRename.getProject(); + myRenameOffset = myEditor.getDocument().createRangeMarker(myElementToRename.getTextRange()); } public boolean performInplaceRename() { @@ -230,7 +233,6 @@ public class VariableInplaceRenamer { addAdditionalVariables(builder); final PsiElement scope1 = scope; - final int renameOffset = myElementToRename.getTextOffset(); CommandProcessor.getInstance().executeCommand(myProject, new Runnable() { public void run() { ApplicationManager.getApplication().runWriteAction(new Runnable() { @@ -268,11 +270,10 @@ public class VariableInplaceRenamer { @Override public void templateFinished(Template template, boolean brokenOff) { super.templateFinished(template, brokenOff); - if (myNewName != null) { - performAutomaticRename(myNewName, PsiTreeUtil.getParentOfType(containingFile.findElementAt(renameOffset), - PsiNameIdentifierOwner.class)); - } moveOffsetAfter(!brokenOff); + if (myNewName != null) { + performAutomaticRename(myNewName, getVariable()); + } } public void templateCancelled(Template template) { @@ -318,6 +319,16 @@ public class VariableInplaceRenamer { return null; } + @Nullable + protected PsiNamedElement getVariable() { + if (myElementToRename != null && myElementToRename.isValid()) return myElementToRename; + final PsiFile psiFile = PsiDocumentManager.getInstance(myProject).getPsiFile(myEditor.getDocument()); + if (psiFile != null) { + return PsiTreeUtil.getParentOfType(psiFile.findElementAt(myRenameOffset.getStartOffset()), PsiNameIdentifierOwner.class); + } + return myElementToRename; + } + protected void moveOffsetAfter(boolean success) { } From 5e85b1d33870aebbc3e166e25487ffa96af28e67 Mon Sep 17 00:00:00 2001 From: anna Date: Tue, 5 Apr 2011 18:09:58 +0200 Subject: [PATCH 12/65] add warning on rename to ignored directory/file (IDEA-67484) --- platform/platform-resources/src/META-INF/LangExtensions.xml | 1 + 1 file changed, 1 insertion(+) diff --git a/platform/platform-resources/src/META-INF/LangExtensions.xml b/platform/platform-resources/src/META-INF/LangExtensions.xml index e8335e12e767..a5fa52cf904c 100644 --- a/platform/platform-resources/src/META-INF/LangExtensions.xml +++ b/platform/platform-resources/src/META-INF/LangExtensions.xml @@ -618,6 +618,7 @@ + From a813882d9f82dcd443646592e7932372badfaacb Mon Sep 17 00:00:00 2001 From: anna Date: Tue, 5 Apr 2011 18:22:03 +0200 Subject: [PATCH 13/65] add warning on rename to ignored directory (IDEA-67484 ) --- ...eToIgnoredDirectoryFileInputValidator.java | 51 +++++++++++++++++++ 1 file changed, 51 insertions(+) create mode 100644 platform/lang-impl/src/com/intellij/refactoring/rename/RenameToIgnoredDirectoryFileInputValidator.java diff --git a/platform/lang-impl/src/com/intellij/refactoring/rename/RenameToIgnoredDirectoryFileInputValidator.java b/platform/lang-impl/src/com/intellij/refactoring/rename/RenameToIgnoredDirectoryFileInputValidator.java new file mode 100644 index 000000000000..88bc7d1fbcf5 --- /dev/null +++ b/platform/lang-impl/src/com/intellij/refactoring/rename/RenameToIgnoredDirectoryFileInputValidator.java @@ -0,0 +1,51 @@ +/* + * Copyright 2000-2011 JetBrains s.r.o. + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ +package com.intellij.refactoring.rename; + +import com.intellij.openapi.fileTypes.FileTypeManager; +import com.intellij.openapi.project.Project; +import com.intellij.patterns.ElementPattern; +import com.intellij.patterns.PlatformPatterns; +import com.intellij.psi.PsiDirectory; +import com.intellij.psi.PsiElement; +import com.intellij.psi.PsiFile; +import com.intellij.util.ProcessingContext; +import org.jetbrains.annotations.Nullable; + +/** + * User: anna + * Date: 4/5/11 + */ +public class RenameToIgnoredDirectoryFileInputValidator implements RenameInputValidatorEx { + @Nullable + @Override + public String getErrorMessage(String newName, Project project) { + if (FileTypeManager.getInstance().isFileIgnored(newName)) { + return "Trying to create a directory with ignored name, result will not be visible"; + } + return null; + } + + @Override + public ElementPattern getPattern() { + return PlatformPatterns.or(PlatformPatterns.psiElement(PsiDirectory.class), PlatformPatterns.psiElement(PsiFile.class)); + } + + @Override + public boolean isInputValid(String newName, PsiElement element, ProcessingContext context) { + return newName != null && newName.length() > 0; + } +} From 52616a168ed685a57fab16a8ede90edecd66c155 Mon Sep 17 00:00:00 2001 From: Gregory Shrago Date: Tue, 5 Apr 2011 21:14:58 +0400 Subject: [PATCH 14/65] IDEA-67506 Infinite loop when opening file ThreefishCipher.java --- .../intelliLang/inject/java/ConcatenationInjector.java | 9 +++++++++ 1 file changed, 9 insertions(+) diff --git a/plugins/IntelliLang/java-support/org/intellij/plugins/intelliLang/inject/java/ConcatenationInjector.java b/plugins/IntelliLang/java-support/org/intellij/plugins/intelliLang/inject/java/ConcatenationInjector.java index 46dcc559d2e1..b9612b3d51c6 100644 --- a/plugins/IntelliLang/java-support/org/intellij/plugins/intelliLang/inject/java/ConcatenationInjector.java +++ b/plugins/IntelliLang/java-support/org/intellij/plugins/intelliLang/inject/java/ConcatenationInjector.java @@ -43,6 +43,7 @@ import org.intellij.plugins.intelliLang.inject.config.BaseInjection; import org.intellij.plugins.intelliLang.inject.config.InjectionPlace; import org.intellij.plugins.intelliLang.util.AnnotationUtilEx; import org.intellij.plugins.intelliLang.util.ContextComputationProcessor; +import org.intellij.plugins.intelliLang.util.PsiUtilEx; import org.jetbrains.annotations.NotNull; import java.util.*; @@ -117,6 +118,14 @@ public class ConcatenationInjector implements ConcatenationAwareInjector { public void getLanguagesToInject(@NotNull final MultiHostRegistrar registrar, @NotNull PsiElement... operands) { if (operands.length == 0) return; + boolean hasLiteral = false; + for (PsiElement operand : operands) { + if (PsiUtilEx.isStringOrCharacterLiteral(operand)) { + hasLiteral = true; + break; + } + } + if (!hasLiteral) return; final PsiFile containingFile = operands[0].getContainingFile(); new InjectionProcessor(myConfiguration, operands) { @Override From 650cca1a8c496a579dd73b128cfec54d5e622a02 Mon Sep 17 00:00:00 2001 From: Alexey Pegov Date: Tue, 5 Apr 2011 21:48:39 +0400 Subject: [PATCH 15/65] highlight search match: add little bit of transparency :) --- platform/util/src/com/intellij/util/ui/UIUtil.java | 4 ++++ 1 file changed, 4 insertions(+) diff --git a/platform/util/src/com/intellij/util/ui/UIUtil.java b/platform/util/src/com/intellij/util/ui/UIUtil.java index b0b2350e19c5..81aa592c7ddd 100644 --- a/platform/util/src/com/intellij/util/ui/UIUtil.java +++ b/platform/util/src/com/intellij/util/ui/UIUtil.java @@ -788,6 +788,8 @@ public class UIUtil { public static void drawSearchMatch(Graphics2D g, int startX, int endX, int height, Color c1, Color c2) { final boolean drawRound = endX - startX > 4; + final Composite oldComposite = g.getComposite(); + g.setComposite(AlphaComposite.getInstance(AlphaComposite.SRC_OVER, 0.7f)); g.setPaint(new GradientPaint(startX, 2, c1, startX, height - 5, c2)); g.fillRect(startX, 3, endX - startX, height - 5); @@ -802,6 +804,8 @@ public class UIUtil { g.drawLine(startX, 3, endX - 1, 3); g.drawLine(startX, height - 3, endX - 1, height - 3); } + + g.setComposite(oldComposite); } public static void drawRectPickedOut(Graphics2D g, int x, int y, int w, int h) { From 699e2f423914e9f0517b0c037d6aa0c0d18c010d Mon Sep 17 00:00:00 2001 From: Roman Shevchenko Date: Tue, 5 Apr 2011 15:56:59 +0200 Subject: [PATCH 16/65] IDEA-67552 (typo) --- .../InsertLiteralUnderscoresAction/description.html | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/resources-en/src/intentionDescriptions/InsertLiteralUnderscoresAction/description.html b/resources-en/src/intentionDescriptions/InsertLiteralUnderscoresAction/description.html index aba45639d8a2..409f70280849 100644 --- a/resources-en/src/intentionDescriptions/InsertLiteralUnderscoresAction/description.html +++ b/resources-en/src/intentionDescriptions/InsertLiteralUnderscoresAction/description.html @@ -1,5 +1,5 @@ -This intention inserts underscores into numeric literals (supported in JDK7 amd higher). +This intention inserts underscores into numeric literals (supported in JDK7 and higher). From 0c4b85124be4fde453830d7dd7fed986e27fe2e8 Mon Sep 17 00:00:00 2001 From: Roman Shevchenko Date: Tue, 5 Apr 2011 18:44:23 +0200 Subject: [PATCH 17/65] IDEA-67549 (convert to plain/engineering to respect literal underscores) --- .../siyeh/IntentionPowerPackBundle.properties | 6 +-- ...ConvertToEngineeringNotationIntention.java | 51 +++++++------------ .../ipp/integer/ConvertToPlainIntention.java | 51 +++++-------------- .../test/com/siyeh/ipp/float/EngToPlain.java | 3 ++ .../com/siyeh/ipp/float/EngToPlain_after.java | 3 ++ .../siyeh/ipp/float/NegatedFloatToEng.java | 3 ++ .../ipp/float/NegatedFloatToEng_after.java | 3 ++ .../siyeh/ipp/float/NegatedFloatToPlain.java | 3 ++ .../ipp/float/NegatedFloatToPlain_after.java | 3 ++ .../test/com/siyeh/ipp/float/PlainToEng.java | 3 ++ .../com/siyeh/ipp/float/PlainToEng_after.java | 3 ++ .../siyeh/ipp/float/ToEngWithUnderscores.java | 3 ++ .../ipp/float/ToEngWithUnderscores_after.java | 3 ++ .../ipp/float/ToPlainWithUnderscores.java | 3 ++ .../float/ToPlainWithUnderscores_after.java | 3 ++ .../ConvertToEngineeringNotationTest.java | 35 +++++++++++++ .../siyeh/ipp/integer/ConvertToPlainTest.java | 35 +++++++++++++ 17 files changed, 140 insertions(+), 74 deletions(-) create mode 100644 plugins/IntentionPowerPak/test/com/siyeh/ipp/float/EngToPlain.java create mode 100644 plugins/IntentionPowerPak/test/com/siyeh/ipp/float/EngToPlain_after.java create mode 100644 plugins/IntentionPowerPak/test/com/siyeh/ipp/float/NegatedFloatToEng.java create mode 100644 plugins/IntentionPowerPak/test/com/siyeh/ipp/float/NegatedFloatToEng_after.java create mode 100644 plugins/IntentionPowerPak/test/com/siyeh/ipp/float/NegatedFloatToPlain.java create mode 100644 plugins/IntentionPowerPak/test/com/siyeh/ipp/float/NegatedFloatToPlain_after.java create mode 100644 plugins/IntentionPowerPak/test/com/siyeh/ipp/float/PlainToEng.java create mode 100644 plugins/IntentionPowerPak/test/com/siyeh/ipp/float/PlainToEng_after.java create mode 100644 plugins/IntentionPowerPak/test/com/siyeh/ipp/float/ToEngWithUnderscores.java create mode 100644 plugins/IntentionPowerPak/test/com/siyeh/ipp/float/ToEngWithUnderscores_after.java create mode 100644 plugins/IntentionPowerPak/test/com/siyeh/ipp/float/ToPlainWithUnderscores.java create mode 100644 plugins/IntentionPowerPak/test/com/siyeh/ipp/float/ToPlainWithUnderscores_after.java create mode 100644 plugins/IntentionPowerPak/testSrc/com/siyeh/ipp/integer/ConvertToEngineeringNotationTest.java create mode 100644 plugins/IntentionPowerPak/testSrc/com/siyeh/ipp/integer/ConvertToPlainTest.java diff --git a/plugins/IntentionPowerPak/src/com/siyeh/IntentionPowerPackBundle.properties b/plugins/IntentionPowerPak/src/com/siyeh/IntentionPowerPackBundle.properties index 1ed0651f4a90..3763cddaa34f 100644 --- a/plugins/IntentionPowerPak/src/com/siyeh/IntentionPowerPackBundle.properties +++ b/plugins/IntentionPowerPak/src/com/siyeh/IntentionPowerPackBundle.properties @@ -57,9 +57,9 @@ convert.integer.to.hex.intention.name=Convert to hex convert.integer.to.hex.intention.family.name=Convert to Hexadecimal convert.integer.to.binary.intention.name=Convert to binary convert.integer.to.binary.intention.family.name=Convert to Binary -convert.to.engineering.notation.intention.name=Convert to Engineering notation -convert.to.engineering.notation.intention.family.name=Convert to Engineering notation -convert.to.plain.intention.name=Convert to Plain +convert.to.engineering.notation.intention.name=Convert to engineering notation +convert.to.engineering.notation.intention.family.name=Convert to Engineering Notation +convert.to.plain.intention.name=Convert to plain convert.to.plain.intention.family.name=Convert to Plain string.to.char.intention.name=Replace string literal with character string.to.char.intention.family.name=Replace String with Char diff --git a/plugins/IntentionPowerPak/src/com/siyeh/ipp/integer/ConvertToEngineeringNotationIntention.java b/plugins/IntentionPowerPak/src/com/siyeh/ipp/integer/ConvertToEngineeringNotationIntention.java index 508f57e6b629..746800de5cdc 100644 --- a/plugins/IntentionPowerPak/src/com/siyeh/ipp/integer/ConvertToEngineeringNotationIntention.java +++ b/plugins/IntentionPowerPak/src/com/siyeh/ipp/integer/ConvertToEngineeringNotationIntention.java @@ -15,48 +15,31 @@ */ package com.siyeh.ipp.integer; -import com.intellij.psi.PsiElement; -import com.intellij.psi.PsiExpression; -import com.intellij.util.IncorrectOperationException; -import com.siyeh.ipp.base.Intention; +import com.intellij.psi.PsiType; import com.siyeh.ipp.base.PsiElementPredicate; import org.jetbrains.annotations.NotNull; import java.text.DecimalFormat; +import java.text.DecimalFormatSymbols; +import java.util.Locale; /** * @author Konstantin Bulenkov + * todo: actually it's a scientific notation, not an engineering one. */ -public class ConvertToEngineeringNotationIntention extends Intention { +public class ConvertToEngineeringNotationIntention extends ConvertNumberIntentionBase { + private static final DecimalFormat FORMAT = new DecimalFormat("0.0#############E00", new DecimalFormatSymbols(Locale.US)); - private static final DecimalFormat FORMAT = - new DecimalFormat("0.00000000000000E00"); - private static final ConvertToEngineeringNotationPredicate PREDICATE = - new ConvertToEngineeringNotationPredicate(); + @Override + protected String convertValue(final Number value, final PsiType type, final boolean negated) { + final double doubleValue = Double.parseDouble(value.toString()); // convert to double w/o adding parasitic digits + final String text = FORMAT.format(negated ? -doubleValue : doubleValue); + return PsiType.FLOAT.equals(type) ? text + "f" : text; + } - @Override - protected void processIntention(@NotNull PsiElement element) - throws IncorrectOperationException { - final String elementText = element.getText(); - if (elementText.length() == 0) { - return; - } - final int lastIndex = elementText.length() - 1; - final char lastChar = elementText.charAt(lastIndex); - String text = FORMAT.format(Double.parseDouble(elementText)).replace(',', '.'); - while (text.contains("0E") && !text.contains(".0E")) { - text = text.replace("0E", "E"); - } - if (lastChar == 'f' || lastChar == 'F') { - replaceExpression(text + lastChar, (PsiExpression)element); - } else { - replaceExpression(text, (PsiExpression)element); - } - } - - @NotNull - @Override - protected PsiElementPredicate getElementPredicate() { - return PREDICATE; - } + @NotNull + @Override + protected PsiElementPredicate getElementPredicate() { + return new ConvertToEngineeringNotationPredicate(); + } } diff --git a/plugins/IntentionPowerPak/src/com/siyeh/ipp/integer/ConvertToPlainIntention.java b/plugins/IntentionPowerPak/src/com/siyeh/ipp/integer/ConvertToPlainIntention.java index ea0d42785008..8540850ba4c8 100644 --- a/plugins/IntentionPowerPak/src/com/siyeh/ipp/integer/ConvertToPlainIntention.java +++ b/plugins/IntentionPowerPak/src/com/siyeh/ipp/integer/ConvertToPlainIntention.java @@ -15,10 +15,7 @@ */ package com.siyeh.ipp.integer; -import com.intellij.psi.PsiElement; -import com.intellij.psi.PsiExpression; -import com.intellij.util.IncorrectOperationException; -import com.siyeh.ipp.base.Intention; +import com.intellij.psi.PsiType; import com.siyeh.ipp.base.PsiElementPredicate; import org.jetbrains.annotations.NotNull; @@ -27,38 +24,18 @@ import java.math.BigDecimal; /** * @author Konstantin Bulenkov */ -public class ConvertToPlainIntention extends Intention { +public class ConvertToPlainIntention extends ConvertNumberIntentionBase { + @Override + protected String convertValue(final Number value, final PsiType type, final boolean negated) { + String text = new BigDecimal(value.toString()).toPlainString(); + if (negated) text = "-" + text; + if (PsiType.FLOAT.equals(type)) text += "f"; + return text; + } - private static final ConvertToPlainPredicate PREDICATE = - new ConvertToPlainPredicate(); - - @Override - protected void processIntention(@NotNull PsiElement element) - throws IncorrectOperationException { - try { - final String elementText = element.getText(); - if (elementText.length() == 0) { - return; - } - final int lastIndex = elementText.length() - 1; - final char lastChar = elementText.charAt(lastIndex); - if (lastChar == 'f' || lastChar == 'F') { - final BigDecimal bigDecimal = - new BigDecimal(elementText.substring(0, lastIndex)); - replaceExpression(bigDecimal.toPlainString() + lastChar, - (PsiExpression) element); - } else { - final BigDecimal bigDecimal = new BigDecimal(elementText); - replaceExpression(bigDecimal.toPlainString(), - (PsiExpression) element); - } - } catch (Exception e) {// - } - } - - @NotNull - @Override - protected PsiElementPredicate getElementPredicate() { - return PREDICATE; - } + @NotNull + @Override + protected PsiElementPredicate getElementPredicate() { + return new ConvertToPlainPredicate(); + } } diff --git a/plugins/IntentionPowerPak/test/com/siyeh/ipp/float/EngToPlain.java b/plugins/IntentionPowerPak/test/com/siyeh/ipp/float/EngToPlain.java new file mode 100644 index 000000000000..c7145df9242c --- /dev/null +++ b/plugins/IntentionPowerPak/test/com/siyeh/ipp/float/EngToPlain.java @@ -0,0 +1,3 @@ +class C { + double x = 1.23456789E03; +} \ No newline at end of file diff --git a/plugins/IntentionPowerPak/test/com/siyeh/ipp/float/EngToPlain_after.java b/plugins/IntentionPowerPak/test/com/siyeh/ipp/float/EngToPlain_after.java new file mode 100644 index 000000000000..7c6d5deb7eb6 --- /dev/null +++ b/plugins/IntentionPowerPak/test/com/siyeh/ipp/float/EngToPlain_after.java @@ -0,0 +1,3 @@ +class C { + double x = 1234.56789; +} \ No newline at end of file diff --git a/plugins/IntentionPowerPak/test/com/siyeh/ipp/float/NegatedFloatToEng.java b/plugins/IntentionPowerPak/test/com/siyeh/ipp/float/NegatedFloatToEng.java new file mode 100644 index 000000000000..5ec95cdb0952 --- /dev/null +++ b/plugins/IntentionPowerPak/test/com/siyeh/ipp/float/NegatedFloatToEng.java @@ -0,0 +1,3 @@ +class C { + float x = -12345.6789f; +} \ No newline at end of file diff --git a/plugins/IntentionPowerPak/test/com/siyeh/ipp/float/NegatedFloatToEng_after.java b/plugins/IntentionPowerPak/test/com/siyeh/ipp/float/NegatedFloatToEng_after.java new file mode 100644 index 000000000000..5d63e805aa2e --- /dev/null +++ b/plugins/IntentionPowerPak/test/com/siyeh/ipp/float/NegatedFloatToEng_after.java @@ -0,0 +1,3 @@ +class C { + float x = -1.2345679E04f; +} \ No newline at end of file diff --git a/plugins/IntentionPowerPak/test/com/siyeh/ipp/float/NegatedFloatToPlain.java b/plugins/IntentionPowerPak/test/com/siyeh/ipp/float/NegatedFloatToPlain.java new file mode 100644 index 000000000000..b523721e9305 --- /dev/null +++ b/plugins/IntentionPowerPak/test/com/siyeh/ipp/float/NegatedFloatToPlain.java @@ -0,0 +1,3 @@ +class C { + float x = -1.2345679E04f; +} \ No newline at end of file diff --git a/plugins/IntentionPowerPak/test/com/siyeh/ipp/float/NegatedFloatToPlain_after.java b/plugins/IntentionPowerPak/test/com/siyeh/ipp/float/NegatedFloatToPlain_after.java new file mode 100644 index 000000000000..2e9a15fdefb3 --- /dev/null +++ b/plugins/IntentionPowerPak/test/com/siyeh/ipp/float/NegatedFloatToPlain_after.java @@ -0,0 +1,3 @@ +class C { + float x = -12345.679f; +} \ No newline at end of file diff --git a/plugins/IntentionPowerPak/test/com/siyeh/ipp/float/PlainToEng.java b/plugins/IntentionPowerPak/test/com/siyeh/ipp/float/PlainToEng.java new file mode 100644 index 000000000000..d2121760f161 --- /dev/null +++ b/plugins/IntentionPowerPak/test/com/siyeh/ipp/float/PlainToEng.java @@ -0,0 +1,3 @@ +class C { + double x = 625347615293854987235496527432424234625347615293854987235496527432424234625347615293854987235496527432424234.42; +} \ No newline at end of file diff --git a/plugins/IntentionPowerPak/test/com/siyeh/ipp/float/PlainToEng_after.java b/plugins/IntentionPowerPak/test/com/siyeh/ipp/float/PlainToEng_after.java new file mode 100644 index 000000000000..1ba1367a2d28 --- /dev/null +++ b/plugins/IntentionPowerPak/test/com/siyeh/ipp/float/PlainToEng_after.java @@ -0,0 +1,3 @@ +class C { + double x = 6.25347615293855E107; +} \ No newline at end of file diff --git a/plugins/IntentionPowerPak/test/com/siyeh/ipp/float/ToEngWithUnderscores.java b/plugins/IntentionPowerPak/test/com/siyeh/ipp/float/ToEngWithUnderscores.java new file mode 100644 index 000000000000..59c7633a8902 --- /dev/null +++ b/plugins/IntentionPowerPak/test/com/siyeh/ipp/float/ToEngWithUnderscores.java @@ -0,0 +1,3 @@ +class C { + double x = 1234.567_89; +} \ No newline at end of file diff --git a/plugins/IntentionPowerPak/test/com/siyeh/ipp/float/ToEngWithUnderscores_after.java b/plugins/IntentionPowerPak/test/com/siyeh/ipp/float/ToEngWithUnderscores_after.java new file mode 100644 index 000000000000..9e6cde3a8dc1 --- /dev/null +++ b/plugins/IntentionPowerPak/test/com/siyeh/ipp/float/ToEngWithUnderscores_after.java @@ -0,0 +1,3 @@ +class C { + double x = 1.23456789E03; +} \ No newline at end of file diff --git a/plugins/IntentionPowerPak/test/com/siyeh/ipp/float/ToPlainWithUnderscores.java b/plugins/IntentionPowerPak/test/com/siyeh/ipp/float/ToPlainWithUnderscores.java new file mode 100644 index 000000000000..12060cc457fc --- /dev/null +++ b/plugins/IntentionPowerPak/test/com/siyeh/ipp/float/ToPlainWithUnderscores.java @@ -0,0 +1,3 @@ +class C { + double x = 1.234_567_890E03; +} \ No newline at end of file diff --git a/plugins/IntentionPowerPak/test/com/siyeh/ipp/float/ToPlainWithUnderscores_after.java b/plugins/IntentionPowerPak/test/com/siyeh/ipp/float/ToPlainWithUnderscores_after.java new file mode 100644 index 000000000000..7c6d5deb7eb6 --- /dev/null +++ b/plugins/IntentionPowerPak/test/com/siyeh/ipp/float/ToPlainWithUnderscores_after.java @@ -0,0 +1,3 @@ +class C { + double x = 1234.56789; +} \ No newline at end of file diff --git a/plugins/IntentionPowerPak/testSrc/com/siyeh/ipp/integer/ConvertToEngineeringNotationTest.java b/plugins/IntentionPowerPak/testSrc/com/siyeh/ipp/integer/ConvertToEngineeringNotationTest.java new file mode 100644 index 000000000000..f7b404ceb239 --- /dev/null +++ b/plugins/IntentionPowerPak/testSrc/com/siyeh/ipp/integer/ConvertToEngineeringNotationTest.java @@ -0,0 +1,35 @@ +/* + * Copyright 2000-2011 JetBrains s.r.o. + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ +package com.siyeh.ipp.integer; + +import com.siyeh.IntentionPowerPackBundle; +import com.siyeh.ipp.IPPTestCase; + +public class ConvertToEngineeringNotationTest extends IPPTestCase { + public void testPlainToEng() { doTest(); } + public void testNegatedFloatToEng() { doTest(); } + public void testToEngWithUnderscores() { doTest(); } + + @Override + protected String getIntentionName() { + return IntentionPowerPackBundle.message("convert.to.engineering.notation.intention.name"); + } + + @Override + protected String getRelativePath() { + return "float"; + } +} diff --git a/plugins/IntentionPowerPak/testSrc/com/siyeh/ipp/integer/ConvertToPlainTest.java b/plugins/IntentionPowerPak/testSrc/com/siyeh/ipp/integer/ConvertToPlainTest.java new file mode 100644 index 000000000000..fa2a26182735 --- /dev/null +++ b/plugins/IntentionPowerPak/testSrc/com/siyeh/ipp/integer/ConvertToPlainTest.java @@ -0,0 +1,35 @@ +/* + * Copyright 2000-2011 JetBrains s.r.o. + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ +package com.siyeh.ipp.integer; + +import com.siyeh.IntentionPowerPackBundle; +import com.siyeh.ipp.IPPTestCase; + +public class ConvertToPlainTest extends IPPTestCase { + public void testEngToPlain() { doTest(); } + public void testNegatedFloatToPlain() { doTest(); } + public void testToPlainWithUnderscores() { doTest(); } + + @Override + protected String getIntentionName() { + return IntentionPowerPackBundle.message("convert.to.plain.intention.name"); + } + + @Override + protected String getRelativePath() { + return "float"; + } +} From cce2c02db179df55b9755b9646039ffa0c296e1b Mon Sep 17 00:00:00 2001 From: Roman Shevchenko Date: Tue, 5 Apr 2011 20:45:12 +0200 Subject: [PATCH 18/65] IDEA-67556 (use highest language level in an artificial elements was a bad idea) --- .../psi/impl/PsiJavaParserFacadeImpl.java | 31 +++++++++++-------- .../psi/impl/compiled/ClsParsingUtil.java | 5 ++- .../psi/impl/source/JavaDummyElement.java | 16 +++++----- .../psi/impl/source/JavaFileElementType.java | 2 +- .../source/tree/JavaChangeUtilSupport.java | 4 ++- .../advHighlighting/notAKeywords/Test.java | 9 ++++++ .../advHighlighting/notAKeywords/pkg/Bar.java | 9 ++++++ .../notAKeywords/pkg/enum/Foo.java | 5 +++ .../daemon/AdvHighlightingTest.java | 5 +++ 9 files changed, 63 insertions(+), 23 deletions(-) create mode 100644 java/java-tests/testData/codeInsight/daemonCodeAnalyzer/advHighlighting/notAKeywords/Test.java create mode 100644 java/java-tests/testData/codeInsight/daemonCodeAnalyzer/advHighlighting/notAKeywords/pkg/Bar.java create mode 100644 java/java-tests/testData/codeInsight/daemonCodeAnalyzer/advHighlighting/notAKeywords/pkg/enum/Foo.java 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 d14200cece98..42dd27340cf9 100644 --- a/java/java-impl/src/com/intellij/psi/impl/PsiJavaParserFacadeImpl.java +++ b/java/java-impl/src/com/intellij/psi/impl/PsiJavaParserFacadeImpl.java @@ -39,6 +39,7 @@ import com.intellij.psi.util.PsiUtil; import com.intellij.util.IncorrectOperationException; import com.intellij.util.containers.HashMap; import org.jetbrains.annotations.NotNull; +import org.jetbrains.annotations.Nullable; import java.util.Map; import java.util.Properties; @@ -170,7 +171,7 @@ public class PsiJavaParserFacadeImpl extends PsiParserFacadeImpl implements PsiJ @NotNull @Override 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 DummyHolder holder = DummyHolderFactory.createHolder(myManager, new JavaDummyElement(text, ANNOTATION, level(context)), context); final PsiElement element = SourceTreeToPsiMap.treeElementToPsi(holder.getTreeElement().getFirstChildNode()); if (!(element instanceof PsiAnnotation)) { throw new IncorrectOperationException("Incorrect annotation \"" + text + "\"."); @@ -219,7 +220,7 @@ public class PsiJavaParserFacadeImpl extends PsiParserFacadeImpl implements PsiJ @NotNull @Override 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 DummyHolder holder = DummyHolderFactory.createHolder(myManager, new JavaDummyElement(text, DECLARATION, level(context)), context); final PsiElement element = SourceTreeToPsiMap.treeElementToPsi(holder.getTreeElement().getFirstChildNode()); if (!(element instanceof PsiField)) { throw new IncorrectOperationException("Incorrect field \"" + text + "\"."); @@ -230,7 +231,7 @@ public class PsiJavaParserFacadeImpl extends PsiParserFacadeImpl implements PsiJ @NotNull @Override 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 DummyHolder holder = DummyHolderFactory.createHolder(myManager, new JavaDummyElement(text, DECLARATION, level), context); final PsiElement element = SourceTreeToPsiMap.treeElementToPsi(holder.getTreeElement().getFirstChildNode()); if (!(element instanceof PsiMethod)) { throw new IncorrectOperationException("Incorrect method \"" + text + "\" (" + element + ")."); @@ -248,7 +249,7 @@ public class PsiJavaParserFacadeImpl extends PsiParserFacadeImpl implements PsiJ @NotNull @Override 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 DummyHolder holder = DummyHolderFactory.createHolder(myManager, new JavaDummyElement(text, PARAMETER, level(context)), context); final PsiElement element = SourceTreeToPsiMap.treeElementToPsi(holder.getTreeElement().getFirstChildNode()); if (!(element instanceof PsiParameter)) { throw new IncorrectOperationException("Incorrect parameter \"" + text + "\"."); @@ -259,7 +260,7 @@ public class PsiJavaParserFacadeImpl extends PsiParserFacadeImpl implements PsiJ @NotNull @Override public PsiResourceVariable createResourceFromText(@NotNull final String text, final PsiElement context) throws IncorrectOperationException { - final DummyHolder holder = DummyHolderFactory.createHolder(myManager, new JavaDummyElement(text, RESOURCE, false), context); + final DummyHolder holder = DummyHolderFactory.createHolder(myManager, new JavaDummyElement(text, RESOURCE, level(context)), context); final PsiElement element = SourceTreeToPsiMap.treeElementToPsi(holder.getTreeElement().getFirstChildNode()); if (!(element instanceof PsiResourceVariable)) { throw new IncorrectOperationException("Incorrect resource \"" + text + "\"."); @@ -276,7 +277,7 @@ public class PsiJavaParserFacadeImpl extends PsiParserFacadeImpl implements PsiJ @NotNull @Override public PsiTypeElement createTypeElementFromText(@NotNull final String text, final PsiElement context) throws IncorrectOperationException { - final DummyHolder holder = DummyHolderFactory.createHolder(myManager, new JavaDummyElement(text, TYPE, false), context); + final DummyHolder holder = DummyHolderFactory.createHolder(myManager, new JavaDummyElement(text, TYPE, level(context)), context); final PsiElement element = SourceTreeToPsiMap.treeElementToPsi(holder.getTreeElement().getFirstChildNode()); if (!(element instanceof PsiTypeElement)) { throw new IncorrectOperationException("Incorrect type \"" + text + "\"."); @@ -303,7 +304,7 @@ public class PsiJavaParserFacadeImpl extends PsiParserFacadeImpl implements PsiJ final boolean mayHaveDiamonds = context instanceof PsiNewExpression && PsiUtil.getLanguageLevel(context).isAtLeast(LanguageLevel.JDK_1_7); final JavaParserUtil.ParserWrapper wrapper = isStaticImport ? STATIC_IMPORT_REF : mayHaveDiamonds ? DIAMOND_REF : REFERENCE; - final DummyHolder holder = DummyHolderFactory.createHolder(myManager, new JavaDummyElement(text, wrapper, false), context); + final DummyHolder holder = DummyHolderFactory.createHolder(myManager, new JavaDummyElement(text, wrapper, level(context)), context); final PsiElement element = SourceTreeToPsiMap.treeElementToPsi(holder.getTreeElement().getFirstChildNode()); if (!(element instanceof PsiJavaCodeReferenceElement)) { throw new IncorrectOperationException("Incorrect reference \"" + text + "\"."); @@ -314,7 +315,7 @@ public class PsiJavaParserFacadeImpl extends PsiParserFacadeImpl implements PsiJ @NotNull @Override 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 DummyHolder holder = DummyHolderFactory.createHolder(myManager, new JavaDummyElement(text, CODE_BLOCK, level(context), true), context); final PsiElement element = SourceTreeToPsiMap.treeElementToPsi(holder.getTreeElement().getFirstChildNode()); if (!(element instanceof PsiCodeBlock)) { throw new IncorrectOperationException("Incorrect code block \"" + text + "\"."); @@ -325,7 +326,7 @@ public class PsiJavaParserFacadeImpl extends PsiParserFacadeImpl implements PsiJ @NotNull @Override 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 DummyHolder holder = DummyHolderFactory.createHolder(myManager, new JavaDummyElement(text, STATEMENT, level(context)), context); final PsiElement element = SourceTreeToPsiMap.treeElementToPsi(holder.getTreeElement().getFirstChildNode()); if (!(element instanceof PsiStatement)) { throw new IncorrectOperationException("Incorrect statement \"" + text + "\"."); @@ -336,7 +337,7 @@ public class PsiJavaParserFacadeImpl extends PsiParserFacadeImpl implements PsiJ @NotNull @Override 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 DummyHolder holder = DummyHolderFactory.createHolder(myManager, new JavaDummyElement(text, EXPRESSION, level(context)), context); final PsiElement element = SourceTreeToPsiMap.treeElementToPsi(holder.getTreeElement().getFirstChildNode()); if (!(element instanceof PsiExpression)) { throw new IncorrectOperationException("Incorrect expression \"" + text + "\"."); @@ -353,7 +354,7 @@ public class PsiJavaParserFacadeImpl extends PsiParserFacadeImpl implements PsiJ @NotNull @Override 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 DummyHolder holder = DummyHolderFactory.createHolder(myManager, new JavaDummyElement(text, TYPE_PARAMETER, level(context)), context); final PsiElement element = SourceTreeToPsiMap.treeElementToPsi(holder.getTreeElement().getFirstChildNode()); if (!(element instanceof PsiTypeParameter)) { throw new IncorrectOperationException("Incorrect type parameter \"" + text + "\"."); @@ -382,7 +383,7 @@ public class PsiJavaParserFacadeImpl extends PsiParserFacadeImpl implements PsiJ @NotNull @Override 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 DummyHolder holder = DummyHolderFactory.createHolder(myManager, new JavaDummyElement(text, ENUM_CONSTANT, level(context)), context); final PsiElement element = SourceTreeToPsiMap.treeElementToPsi(holder.getTreeElement().getFirstChildNode()); if (!(element instanceof PsiEnumConstant)) { throw new IncorrectOperationException("Incorrect enum constant \"" + text + "\"."); @@ -396,7 +397,7 @@ public class PsiJavaParserFacadeImpl extends PsiParserFacadeImpl implements PsiJ final PsiElement context) throws IncorrectOperationException { final String text = StringUtil .join("catch (", exceptionType.getCanonicalText(), " ", exceptionName, ") {}"); - final DummyHolder holder = DummyHolderFactory.createHolder(myManager, new JavaDummyElement(text, CATCH_SECTION, false), context); + final DummyHolder holder = DummyHolderFactory.createHolder(myManager, new JavaDummyElement(text, CATCH_SECTION, level(context)), context); final PsiElement element = SourceTreeToPsiMap.treeElementToPsi(holder.getTreeElement().getFirstChildNode()); if (!(element instanceof PsiCatchSection)) { throw new IncorrectOperationException("Incorrect catch section '" + text + "'. Parsed element: "+element); @@ -444,4 +445,8 @@ public class PsiJavaParserFacadeImpl extends PsiParserFacadeImpl implements PsiJ public static PsiPrimitiveType getPrimitiveType(final String text) { return PRIMITIVE_TYPES.get(text); } + + private static LanguageLevel level(@Nullable final PsiElement context) { + return context != null ? PsiUtil.getLanguageLevel(context) : LanguageLevel.HIGHEST; + } } diff --git a/java/java-impl/src/com/intellij/psi/impl/compiled/ClsParsingUtil.java b/java/java-impl/src/com/intellij/psi/impl/compiled/ClsParsingUtil.java index 5ee27af19e31..7063c1cb75fc 100644 --- a/java/java-impl/src/com/intellij/psi/impl/compiled/ClsParsingUtil.java +++ b/java/java-impl/src/com/intellij/psi/impl/compiled/ClsParsingUtil.java @@ -21,12 +21,14 @@ import com.intellij.lang.java.parser.JavaParserUtil; import com.intellij.openapi.diagnostic.Logger; import com.intellij.openapi.util.text.CharFilter; import com.intellij.openapi.util.text.StringUtil; +import com.intellij.pom.java.LanguageLevel; import com.intellij.psi.*; import com.intellij.psi.impl.PsiElementFactoryImpl; 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.util.PsiUtil; import com.intellij.util.IncorrectOperationException; import org.jetbrains.annotations.NotNull; @@ -85,7 +87,8 @@ public class ClsParsingUtil { final String exprText = mapIndeterminate(text); final PsiElementFactory factory = JavaPsiFacade.getInstance(manager.getProject()).getElementFactory(); final PsiJavaFile context = ((PsiElementFactoryImpl)factory).getDummyJavaFile(); // to resolve classes from java.lang - final DummyHolder holder = DummyHolderFactory.createHolder(manager, new JavaDummyElement(exprText, ANNOTATION_VALUE, false), context); + final LanguageLevel level = PsiUtil.getLanguageLevel(parent); + final DummyHolder holder = DummyHolderFactory.createHolder(manager, new JavaDummyElement(exprText, ANNOTATION_VALUE, level), context); final PsiElement element = SourceTreeToPsiMap.treeElementToPsi(holder.getTreeElement().getFirstChildNode()); if (!(element instanceof PsiAnnotationMemberValue)) { LOG.error("Could not parse initializer:'" + exprText + "'"); 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 index c54c4e18eba8..0ac0f50edee2 100644 --- a/java/java-impl/src/com/intellij/psi/impl/source/JavaDummyElement.java +++ b/java/java-impl/src/com/intellij/psi/impl/source/JavaDummyElement.java @@ -28,22 +28,24 @@ import org.jetbrains.annotations.Nullable; * See {@link com.intellij.psi.impl.PsiJavaParserFacadeImpl} for details. */ public class JavaDummyElement extends FileElement { - @NotNull private final JavaParserUtil.ParserWrapper myParser; + private final JavaParserUtil.ParserWrapper myParser; + private final LanguageLevel myLanguageLevel; 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, + @NotNull final LanguageLevel level) { + this(text, parser, level, false); } public JavaDummyElement(@Nullable final CharSequence text, @NotNull final JavaParserUtil.ParserWrapper parser, - final boolean consumeAll, - @NotNull final LanguageLevel level) { + @NotNull final LanguageLevel level, + final boolean consumeAll) { super(JavaElementType.DUMMY_ELEMENT, text); myParser = parser; - myConsumeAll = consumeAll; myLanguageLevel = level; + myConsumeAll = consumeAll; } @NotNull diff --git a/java/java-impl/src/com/intellij/psi/impl/source/JavaFileElementType.java b/java/java-impl/src/com/intellij/psi/impl/source/JavaFileElementType.java index 018d3d77fa28..914cb425773d 100644 --- a/java/java-impl/src/com/intellij/psi/impl/source/JavaFileElementType.java +++ b/java/java-impl/src/com/intellij/psi/impl/source/JavaFileElementType.java @@ -43,7 +43,7 @@ import java.io.IOException; public class JavaFileElementType extends ILightStubFileElementType { public static boolean USE_NEW_STUB_BUILDER = true; - public static final int STUB_VERSION = (USE_NEW_STUB_BUILDER ? 6 : 5) + 2; + public static final int STUB_VERSION = (USE_NEW_STUB_BUILDER ? 6 : 5) + 3; public JavaFileElementType() { super("java.FILE", StdLanguages.JAVA); diff --git a/java/java-impl/src/com/intellij/psi/impl/source/tree/JavaChangeUtilSupport.java b/java/java-impl/src/com/intellij/psi/impl/source/tree/JavaChangeUtilSupport.java index a3230d6a2094..f73cd6bb916a 100644 --- a/java/java-impl/src/com/intellij/psi/impl/source/tree/JavaChangeUtilSupport.java +++ b/java/java-impl/src/com/intellij/psi/impl/source/tree/JavaChangeUtilSupport.java @@ -36,6 +36,7 @@ import com.intellij.psi.impl.source.codeStyle.CodeEditUtil; import com.intellij.psi.impl.source.parsing.ParseUtilBase; import com.intellij.psi.templateLanguages.OuterLanguageElement; import com.intellij.psi.tree.IElementType; +import com.intellij.psi.util.PsiUtil; import com.intellij.util.CharTable; import com.intellij.util.IncorrectOperationException; import org.jetbrains.annotations.NonNls; @@ -76,7 +77,8 @@ public class JavaChangeUtilSupport implements TreeGenerator, TreeCopyHandler { if (original instanceof PsiModifierList) { final String text = original.getText(); assert text != null : "Text is null for " + original + "; " + original.getClass(); - final DummyHolder holder = DummyHolderFactory.createHolder(original.getManager(), new JavaDummyElement(text, MOD_LIST, false), null); + final LanguageLevel level = PsiUtil.getLanguageLevel(original); + final DummyHolder holder = DummyHolderFactory.createHolder(original.getManager(), new JavaDummyElement(text, MOD_LIST, level), null); final TreeElement modifierListElement = holder.getTreeElement().getFirstChildNode(); if (CodeEditUtil.isNodeGenerated(original.getNode())) modifierListElement.acceptTree(new GeneratedMarkerVisitor()); return modifierListElement; diff --git a/java/java-tests/testData/codeInsight/daemonCodeAnalyzer/advHighlighting/notAKeywords/Test.java b/java/java-tests/testData/codeInsight/daemonCodeAnalyzer/advHighlighting/notAKeywords/Test.java new file mode 100644 index 000000000000..2423099880fc --- /dev/null +++ b/java/java-tests/testData/codeInsight/daemonCodeAnalyzer/advHighlighting/notAKeywords/Test.java @@ -0,0 +1,9 @@ +import pkg.Bar; +import pkg.enum.Foo; + +class Test { + void m() { + Bar b = new Bar(); + b.doSomething(Foo.FOO); // with language level JDK 1.4 'enum' shouldn't be a keyword (see IDEA-67556) + } +} \ No newline at end of file diff --git a/java/java-tests/testData/codeInsight/daemonCodeAnalyzer/advHighlighting/notAKeywords/pkg/Bar.java b/java/java-tests/testData/codeInsight/daemonCodeAnalyzer/advHighlighting/notAKeywords/pkg/Bar.java new file mode 100644 index 000000000000..dd23607a3ebf --- /dev/null +++ b/java/java-tests/testData/codeInsight/daemonCodeAnalyzer/advHighlighting/notAKeywords/pkg/Bar.java @@ -0,0 +1,9 @@ +package pkg; + +import pkg.enum.Foo; + +public class Bar { + public void doSomething(Foo foo) { + System.out.println("foo=" + foo); + } +} \ No newline at end of file diff --git a/java/java-tests/testData/codeInsight/daemonCodeAnalyzer/advHighlighting/notAKeywords/pkg/enum/Foo.java b/java/java-tests/testData/codeInsight/daemonCodeAnalyzer/advHighlighting/notAKeywords/pkg/enum/Foo.java new file mode 100644 index 000000000000..0173b12d4c62 --- /dev/null +++ b/java/java-tests/testData/codeInsight/daemonCodeAnalyzer/advHighlighting/notAKeywords/pkg/enum/Foo.java @@ -0,0 +1,5 @@ +package pkg.enum; + +public class Foo { + public static Foo FOO = new Foo(); +} \ No newline at end of file diff --git a/java/java-tests/testSrc/com/intellij/codeInsight/daemon/AdvHighlightingTest.java b/java/java-tests/testSrc/com/intellij/codeInsight/daemon/AdvHighlightingTest.java index 9d9cf6b7253d..00ddf6298151 100644 --- a/java/java-tests/testSrc/com/intellij/codeInsight/daemon/AdvHighlightingTest.java +++ b/java/java-tests/testSrc/com/intellij/codeInsight/daemon/AdvHighlightingTest.java @@ -196,4 +196,9 @@ public class AdvHighlightingTest extends DaemonAnalyzerTestCase { assert vFile2 != null; assertEquals(vFile1.getParent(), vFile2.getParent()); } + + public void testNotAKeywords() throws Exception { + LanguageLevelProjectExtension.getInstance(myProject).setLanguageLevel(LanguageLevel.JDK_1_4); + doTest(BASE_PATH + "/notAKeywords/Test.java", BASE_PATH + "/notAKeywords", false, false); + } } From f2b140e83382c60a4c52b3afe4192a1c3cef4f38 Mon Sep 17 00:00:00 2001 From: nik Date: Tue, 5 Apr 2011 16:38:32 +0400 Subject: [PATCH 19/65] allow to add module test compile output into artifact (IDEA-53226) --- .../ArtifactAntGenerationContextImpl.java | 5 ++ .../ArtifactBySourceFileFinderImpl.java | 8 +- .../impl/artifacts/ArtifactUtil.java | 25 ++---- .../JarArtifactFromModulesDialog.form | 14 ++- .../JarArtifactFromModulesDialog.java | 26 +++--- .../artifacts/JarFromModulesTemplate.java | 19 ++-- .../impl/compiler/ArtifactCompileScope.java | 4 +- ....java => ModuleOutputElementTypeBase.java} | 43 ++++------ .../ModuleOutputPackagingElement.java | 7 ++ ... => ModuleOutputPackagingElementBase.java} | 45 ++++------ .../elements/PackagingElementFactoryImpl.java | 13 ++- .../ProductionModuleOutputElementType.java | 65 ++++++++++++++ ...roductionModuleOutputPackagingElement.java | 75 ++++++++++++++++ .../elements/TestModuleOutputElementType.java | 78 +++++++++++++++++ .../TestModuleOutputPackagingElement.java | 86 +++++++++++++++++++ .../impl/ui/ModuleElementPresentation.java | 17 ++-- .../ArtifactAntGenerationContext.java | 2 + .../elements/PackagingElementFactory.java | 3 + .../sourceItems/ModuleOutputSourceItem.java | 6 +- ...odulesAndLibrariesSourceItemsProvider.java | 4 +- .../src/messages/CompilerBundle.properties | 2 + 21 files changed, 435 insertions(+), 112 deletions(-) rename java/compiler/impl/src/com/intellij/packaging/impl/elements/{ModuleOutputElementType.java => ModuleOutputElementTypeBase.java} (58%) rename java/compiler/impl/src/com/intellij/packaging/impl/elements/{ModuleOutputPackagingElementImpl.java => ModuleOutputPackagingElementBase.java} (77%) create mode 100644 java/compiler/impl/src/com/intellij/packaging/impl/elements/ProductionModuleOutputElementType.java create mode 100644 java/compiler/impl/src/com/intellij/packaging/impl/elements/ProductionModuleOutputPackagingElement.java create mode 100644 java/compiler/impl/src/com/intellij/packaging/impl/elements/TestModuleOutputElementType.java create mode 100644 java/compiler/impl/src/com/intellij/packaging/impl/elements/TestModuleOutputPackagingElement.java diff --git a/java/compiler/impl/src/com/intellij/compiler/ant/artifacts/ArtifactAntGenerationContextImpl.java b/java/compiler/impl/src/com/intellij/compiler/ant/artifacts/ArtifactAntGenerationContextImpl.java index e70a69a75722..b422760a1cf2 100644 --- a/java/compiler/impl/src/com/intellij/compiler/ant/artifacts/ArtifactAntGenerationContextImpl.java +++ b/java/compiler/impl/src/com/intellij/compiler/ant/artifacts/ArtifactAntGenerationContextImpl.java @@ -151,6 +151,11 @@ public class ArtifactAntGenerationContextImpl implements ArtifactAntGenerationCo return BuildProperties.getOutputPathProperty(moduleName); } + @Override + public String getModuleTestOutputPath(@NonNls String moduleName) { + return BuildProperties.getOutputPathForTestsProperty(moduleName); + } + public List getBeforeBuildGenerators() { return myBeforeBuildGenerators; } diff --git a/java/compiler/impl/src/com/intellij/packaging/impl/artifacts/ArtifactBySourceFileFinderImpl.java b/java/compiler/impl/src/com/intellij/packaging/impl/artifacts/ArtifactBySourceFileFinderImpl.java index cbff9ef68971..0083ead2e389 100644 --- a/java/compiler/impl/src/com/intellij/packaging/impl/artifacts/ArtifactBySourceFileFinderImpl.java +++ b/java/compiler/impl/src/com/intellij/packaging/impl/artifacts/ArtifactBySourceFileFinderImpl.java @@ -15,9 +15,7 @@ */ package com.intellij.packaging.impl.artifacts; -import com.intellij.openapi.module.Module; import com.intellij.openapi.project.Project; -import com.intellij.openapi.roots.ModuleRootModel; import com.intellij.openapi.util.ModificationTracker; import com.intellij.openapi.util.MultiValuesMap; import com.intellij.openapi.vfs.VirtualFile; @@ -85,12 +83,8 @@ public class ArtifactBySourceFileFinderImpl extends ArtifactBySourceFileFinder { } } else if (element instanceof ModuleOutputPackagingElement) { - final Module module = ((ModuleOutputPackagingElement)element).findModule(context); - if (module != null) { - final ModuleRootModel rootModel = context.getModulesProvider().getRootModel(module); - for (VirtualFile sourceRoot : rootModel.getSourceRoots(false)) { + for (VirtualFile sourceRoot : ((ModuleOutputPackagingElement)element).getSourceRoots(context)) { result.put(sourceRoot, artifact); - } } } return true; diff --git a/java/compiler/impl/src/com/intellij/packaging/impl/artifacts/ArtifactUtil.java b/java/compiler/impl/src/com/intellij/packaging/impl/artifacts/ArtifactUtil.java index c8bcf0192b3f..c333b135da30 100644 --- a/java/compiler/impl/src/com/intellij/packaging/impl/artifacts/ArtifactUtil.java +++ b/java/compiler/impl/src/com/intellij/packaging/impl/artifacts/ArtifactUtil.java @@ -19,7 +19,6 @@ import com.intellij.compiler.CompilerConfiguration; import com.intellij.openapi.module.Module; import com.intellij.openapi.project.Project; import com.intellij.openapi.roots.CompilerProjectExtension; -import com.intellij.openapi.roots.ModuleRootModel; import com.intellij.openapi.util.Condition; import com.intellij.openapi.util.Pair; import com.intellij.openapi.util.Trinity; @@ -360,13 +359,9 @@ public class ArtifactUtil { @Nullable private static String getRelativePathInSources(@NotNull VirtualFile file, final @NotNull ModuleOutputPackagingElement moduleElement, @NotNull PackagingElementResolvingContext context) { - final Module module = moduleElement.findModule(context); - if (module != null) { - final ModuleRootModel rootModel = context.getModulesProvider().getRootModel(module); - for (VirtualFile sourceRoot : rootModel.getSourceRoots(false)) { - if (VfsUtil.isAncestor(sourceRoot, file, true)) { - return VfsUtil.getRelativePath(file, sourceRoot, '/'); - } + for (VirtualFile sourceRoot : moduleElement.getSourceRoots(context)) { + if (VfsUtil.isAncestor(sourceRoot, file, true)) { + return VfsUtil.getRelativePath(file, sourceRoot, '/'); } } return null; @@ -420,15 +415,11 @@ public class ArtifactUtil { } } else if (element instanceof ModuleOutputPackagingElement) { - final Module module = ((ModuleOutputPackagingElement)element).findModule(context); - if (module != null) { - final CompilerConfiguration compilerConfiguration = CompilerConfiguration.getInstance(context.getProject()); - final ModuleRootModel rootModel = context.getModulesProvider().getRootModel(module); - for (VirtualFile sourceRoot : rootModel.getSourceRoots(false)) { - final VirtualFile sourceFile = sourceRoot.findFileByRelativePath(path); - if (sourceFile != null && compilerConfiguration.isResourceFile(sourceFile)) { - result.add(sourceFile); - } + final CompilerConfiguration compilerConfiguration = CompilerConfiguration.getInstance(context.getProject()); + for (VirtualFile sourceRoot : ((ModuleOutputPackagingElement)element).getSourceRoots(context)) { + final VirtualFile sourceFile = sourceRoot.findFileByRelativePath(path); + if (sourceFile != null && compilerConfiguration.isResourceFile(sourceFile)) { + result.add(sourceFile); } } } diff --git a/java/compiler/impl/src/com/intellij/packaging/impl/artifacts/JarArtifactFromModulesDialog.form b/java/compiler/impl/src/com/intellij/packaging/impl/artifacts/JarArtifactFromModulesDialog.form index 16d474ec1c9f..59003f1a0353 100644 --- a/java/compiler/impl/src/com/intellij/packaging/impl/artifacts/JarArtifactFromModulesDialog.form +++ b/java/compiler/impl/src/com/intellij/packaging/impl/artifacts/JarArtifactFromModulesDialog.form @@ -1,9 +1,9 @@
- + - + @@ -18,7 +18,7 @@ - + @@ -90,6 +90,14 @@ + + + + + + + + diff --git a/java/compiler/impl/src/com/intellij/packaging/impl/artifacts/JarArtifactFromModulesDialog.java b/java/compiler/impl/src/com/intellij/packaging/impl/artifacts/JarArtifactFromModulesDialog.java index fab2d0833a6b..c53df72d68d9 100644 --- a/java/compiler/impl/src/com/intellij/packaging/impl/artifacts/JarArtifactFromModulesDialog.java +++ b/java/compiler/impl/src/com/intellij/packaging/impl/artifacts/JarArtifactFromModulesDialog.java @@ -15,6 +15,7 @@ */ package com.intellij.packaging.impl.artifacts; +import com.intellij.ide.ui.ListCellRendererWrapper; import com.intellij.openapi.module.Module; import com.intellij.openapi.project.Project; import com.intellij.openapi.roots.ui.configuration.ModulesAlphaComparator; @@ -30,7 +31,6 @@ import org.jetbrains.annotations.Nullable; import javax.swing.*; import javax.swing.event.DocumentEvent; -import java.awt.*; import java.awt.event.ActionEvent; import java.awt.event.ActionListener; import java.util.Arrays; @@ -47,6 +47,7 @@ public class JarArtifactFromModulesDialog extends DialogWrapper { private JLabel myManifestDirLabel; private JRadioButton myExtractJarsRadioButton; private JRadioButton myCopyJarsRadioButton; + private JCheckBox myIncludeTestsCheckBox; private PackagingElementResolvingContext myContext; public JarArtifactFromModulesDialog(PackagingElementResolvingContext context) { @@ -84,7 +85,7 @@ public class JarArtifactFromModulesDialog extends DialogWrapper { for (Module module : modules) { myModuleComboBox.addItem(module); } - myModuleComboBox.setRenderer(new ModuleListRenderer()); + myModuleComboBox.setRenderer(new ModuleListRenderer(myModuleComboBox)); init(); } @@ -122,6 +123,10 @@ public class JarArtifactFromModulesDialog extends DialogWrapper { return myExtractJarsRadioButton.isSelected(); } + public boolean isIncludeTests() { + return myIncludeTestsCheckBox.isSelected(); + } + public String getMainClassName() { return myMainClassField.getText(); } @@ -136,20 +141,21 @@ public class JarArtifactFromModulesDialog extends DialogWrapper { return myMainPanel; } - private static class ModuleListRenderer extends DefaultListCellRenderer { + private static class ModuleListRenderer extends ListCellRendererWrapper { + public ModuleListRenderer(JComboBox comboBox) { + super(comboBox); + } + @Override - public Component getListCellRendererComponent(JList list, Object value, int index, boolean isSelected, boolean cellHasFocus) { - final Component component = super.getListCellRendererComponent(list, value, index, isSelected, cellHasFocus); - if (value instanceof Module) { - final Module module = (Module)value; - setIcon(module.getModuleType().getNodeIcon(false)); - setText(module.getName()); + public void customize(JList list, Module value, int index, boolean selected, boolean hasFocus) { + if (value != null) { + setIcon(value.getModuleType().getNodeIcon(false)); + setText(value.getName()); } else { setText(""); setIcon(null); } - return component; } } } diff --git a/java/compiler/impl/src/com/intellij/packaging/impl/artifacts/JarFromModulesTemplate.java b/java/compiler/impl/src/com/intellij/packaging/impl/artifacts/JarFromModulesTemplate.java index 30d6468c4ffa..b0fcd6390b24 100644 --- a/java/compiler/impl/src/com/intellij/packaging/impl/artifacts/JarFromModulesTemplate.java +++ b/java/compiler/impl/src/com/intellij/packaging/impl/artifacts/JarFromModulesTemplate.java @@ -59,12 +59,14 @@ public class JarFromModulesTemplate extends ArtifactTemplate { } return doCreateArtifact(dialog.getSelectedModules(), dialog.getMainClassName(), dialog.getDirectoryForManifest(), - dialog.isExtractLibrariesToJar()); + dialog.isExtractLibrariesToJar(), dialog.isIncludeTests()); } @Nullable public NewArtifactConfiguration doCreateArtifact(final Module[] modules, final String mainClassName, - final String directoryForManifest, final boolean extractLibrariesToJar) { + final String directoryForManifest, + final boolean extractLibrariesToJar, + final boolean includeTests) { VirtualFile manifestFile = null; final Project project = myContext.getProject(); if (mainClassName != null && !mainClassName.isEmpty() || !extractLibrariesToJar) { @@ -92,14 +94,21 @@ public class JarFromModulesTemplate extends ArtifactTemplate { final PackagingElementFactory factory = PackagingElementFactory.getInstance(); final CompositePackagingElement archive = factory.createArchive(FileUtil.sanitizeFileName(name) + ".jar"); - final OrderEnumerator orderEnumerator = ProjectRootManager.getInstance(project).orderEntries(Arrays.asList(modules)); + OrderEnumerator orderEnumerator = ProjectRootManager.getInstance(project).orderEntries(Arrays.asList(modules)); final Set libraries = new THashSet(); - orderEnumerator.using(myContext.getModulesProvider()).withoutSdk().productionOnly().runtimeOnly().recursively().forEach(new Processor() { + if (!includeTests) { + orderEnumerator = orderEnumerator.productionOnly(); + } + orderEnumerator.using(myContext.getModulesProvider()).withoutSdk().runtimeOnly().recursively().forEach(new Processor() { @Override public boolean process(OrderEntry orderEntry) { if (orderEntry instanceof ModuleSourceOrderEntry) { - archive.addOrFindChild(factory.createModuleOutput(orderEntry.getOwnerModule())); + Module module = orderEntry.getOwnerModule(); + archive.addOrFindChild(factory.createModuleOutput(module)); + if (includeTests) { + archive.addOrFindChild(factory.createTestModuleOutput(module)); + } } else if (orderEntry instanceof LibraryOrderEntry) { ContainerUtil.addIfNotNull(((LibraryOrderEntry)orderEntry).getLibrary(), libraries); diff --git a/java/compiler/impl/src/com/intellij/packaging/impl/compiler/ArtifactCompileScope.java b/java/compiler/impl/src/com/intellij/packaging/impl/compiler/ArtifactCompileScope.java index 5497a3dc192f..879859bc8540 100644 --- a/java/compiler/impl/src/com/intellij/packaging/impl/compiler/ArtifactCompileScope.java +++ b/java/compiler/impl/src/com/intellij/packaging/impl/compiler/ArtifactCompileScope.java @@ -26,7 +26,7 @@ import com.intellij.packaging.artifacts.Artifact; import com.intellij.packaging.artifacts.ArtifactManager; import com.intellij.packaging.elements.PackagingElementResolvingContext; import com.intellij.packaging.impl.artifacts.ArtifactUtil; -import com.intellij.packaging.impl.elements.ModuleOutputElementType; +import com.intellij.packaging.impl.elements.ProductionModuleOutputElementType; import com.intellij.packaging.impl.elements.ModuleOutputPackagingElement; import com.intellij.util.Processor; import org.jetbrains.annotations.NotNull; @@ -94,7 +94,7 @@ public class ArtifactCompileScope { private static boolean containsModuleOutput(Artifact artifact, final Set modules, ArtifactManager artifactManager) { final PackagingElementResolvingContext context = artifactManager.getResolvingContext(); - return !ArtifactUtil.processPackagingElements(artifact, ModuleOutputElementType.MODULE_OUTPUT_ELEMENT_TYPE, + return !ArtifactUtil.processPackagingElements(artifact, ProductionModuleOutputElementType.ELEMENT_TYPE, new Processor() { public boolean process(ModuleOutputPackagingElement moduleOutputPackagingElement) { final Module module = moduleOutputPackagingElement.findModule(context); diff --git a/java/compiler/impl/src/com/intellij/packaging/impl/elements/ModuleOutputElementType.java b/java/compiler/impl/src/com/intellij/packaging/impl/elements/ModuleOutputElementTypeBase.java similarity index 58% rename from java/compiler/impl/src/com/intellij/packaging/impl/elements/ModuleOutputElementType.java rename to java/compiler/impl/src/com/intellij/packaging/impl/elements/ModuleOutputElementTypeBase.java index 83c3c0a444d0..87b08326e791 100644 --- a/java/compiler/impl/src/com/intellij/packaging/impl/elements/ModuleOutputElementType.java +++ b/java/compiler/impl/src/com/intellij/packaging/impl/elements/ModuleOutputElementTypeBase.java @@ -1,5 +1,5 @@ /* - * Copyright 2000-2009 JetBrains s.r.o. + * Copyright 2000-2011 JetBrains s.r.o. * * Licensed under the Apache License, Version 2.0 (the "License"); * you may not use this file except in compliance with the License. @@ -15,12 +15,11 @@ */ package com.intellij.packaging.impl.elements; -import com.intellij.openapi.compiler.CompilerBundle; import com.intellij.openapi.module.Module; +import com.intellij.openapi.module.ModulePointer; import com.intellij.openapi.module.ModulePointerManager; import com.intellij.openapi.project.Project; import com.intellij.openapi.project.ProjectBundle; -import com.intellij.openapi.util.IconLoader; import com.intellij.packaging.artifacts.Artifact; import com.intellij.packaging.elements.CompositePackagingElement; import com.intellij.packaging.elements.PackagingElement; @@ -28,49 +27,37 @@ import com.intellij.packaging.elements.PackagingElementType; import com.intellij.packaging.ui.ArtifactEditorContext; import org.jetbrains.annotations.NotNull; -import javax.swing.*; import java.util.ArrayList; -import java.util.Arrays; import java.util.List; /** -* @author nik -*/ -public class ModuleOutputElementType extends PackagingElementType { - public static final ModuleOutputElementType MODULE_OUTPUT_ELEMENT_TYPE = new ModuleOutputElementType(); - - ModuleOutputElementType() { - super("module-output", CompilerBundle.message("element.type.name.module.output")); - } - - @Override - public Icon getCreateElementIcon() { - return IconLoader.getIcon("/nodes/ModuleOpen.png"); + * @author nik + */ +public abstract class ModuleOutputElementTypeBase extends PackagingElementType { + public ModuleOutputElementTypeBase(String id, String presentableName) { + super(id, presentableName); } @Override public boolean canCreate(@NotNull ArtifactEditorContext context, @NotNull Artifact artifact) { - return context.getModulesProvider().getModules().length > 0; + return !getSuitableModules(context).isEmpty(); } @NotNull public List> chooseAndCreate(@NotNull ArtifactEditorContext context, @NotNull Artifact artifact, @NotNull CompositePackagingElement parent) { - List modules = chooseModules(context); + List suitableModules = getSuitableModules(context); + List selected = context.chooseModules(suitableModules, ProjectBundle.message("dialog.title.packaging.choose.module")); + final List> elements = new ArrayList>(); final ModulePointerManager pointerManager = ModulePointerManager.getInstance(context.getProject()); - for (Module module : modules) { - elements.add(new ModuleOutputPackagingElementImpl(context.getProject(), pointerManager.create(module))); + for (Module module : selected) { + elements.add(createElement(context.getProject(), pointerManager.create(module))); } return elements; } - public static List chooseModules(ArtifactEditorContext context) { - return context.chooseModules(Arrays.asList(context.getModulesProvider().getModules()), ProjectBundle.message("dialog.title.packaging.choose.module")); - } + protected abstract ModuleOutputPackagingElementBase createElement(@NotNull Project project, @NotNull ModulePointer pointer); - @NotNull - public ModuleOutputPackagingElementImpl createEmpty(@NotNull Project project) { - return new ModuleOutputPackagingElementImpl(project); - } + protected abstract List getSuitableModules(ArtifactEditorContext context); } diff --git a/java/compiler/impl/src/com/intellij/packaging/impl/elements/ModuleOutputPackagingElement.java b/java/compiler/impl/src/com/intellij/packaging/impl/elements/ModuleOutputPackagingElement.java index d2e0bb9da32f..d73572d36529 100644 --- a/java/compiler/impl/src/com/intellij/packaging/impl/elements/ModuleOutputPackagingElement.java +++ b/java/compiler/impl/src/com/intellij/packaging/impl/elements/ModuleOutputPackagingElement.java @@ -16,9 +16,13 @@ package com.intellij.packaging.impl.elements; import com.intellij.openapi.module.Module; +import com.intellij.openapi.vfs.VirtualFile; import com.intellij.packaging.elements.PackagingElementResolvingContext; +import org.jetbrains.annotations.NotNull; import org.jetbrains.annotations.Nullable; +import java.util.Collection; + /** * @author nik */ @@ -28,4 +32,7 @@ public interface ModuleOutputPackagingElement { @Nullable Module findModule(PackagingElementResolvingContext context); + + @NotNull + Collection getSourceRoots(PackagingElementResolvingContext context); } diff --git a/java/compiler/impl/src/com/intellij/packaging/impl/elements/ModuleOutputPackagingElementImpl.java b/java/compiler/impl/src/com/intellij/packaging/impl/elements/ModuleOutputPackagingElementBase.java similarity index 77% rename from java/compiler/impl/src/com/intellij/packaging/impl/elements/ModuleOutputPackagingElementImpl.java rename to java/compiler/impl/src/com/intellij/packaging/impl/elements/ModuleOutputPackagingElementBase.java index 3d6d71cea825..084cf6ebd456 100644 --- a/java/compiler/impl/src/com/intellij/packaging/impl/elements/ModuleOutputPackagingElementImpl.java +++ b/java/compiler/impl/src/com/intellij/packaging/impl/elements/ModuleOutputPackagingElementBase.java @@ -1,5 +1,5 @@ /* - * Copyright 2000-2009 JetBrains s.r.o. + * Copyright 2000-2011 JetBrains s.r.o. * * Licensed under the Apache License, Version 2.0 (the "License"); * you may not use this file except in compliance with the License. @@ -27,10 +27,6 @@ import com.intellij.openapi.roots.ui.configuration.ModulesProvider; import com.intellij.openapi.vfs.VirtualFile; import com.intellij.packaging.artifacts.ArtifactType; import com.intellij.packaging.elements.*; -import com.intellij.packaging.impl.ui.DelegatedPackagingElementPresentation; -import com.intellij.packaging.impl.ui.ModuleElementPresentation; -import com.intellij.packaging.ui.ArtifactEditorContext; -import com.intellij.packaging.ui.PackagingElementPresentation; import com.intellij.util.ArrayUtil; import com.intellij.util.xmlb.annotations.Attribute; import org.jetbrains.annotations.NonNls; @@ -43,25 +39,20 @@ import java.util.List; /** * @author nik */ -public class ModuleOutputPackagingElementImpl extends PackagingElement - implements ModuleOutputPackagingElement { +public abstract class ModuleOutputPackagingElementBase extends PackagingElement implements ModuleOutputPackagingElement { @NonNls public static final String MODULE_NAME_ATTRIBUTE = "name"; - private ModulePointer myModulePointer; - private final Project myProject; + protected ModulePointer myModulePointer; + protected final Project myProject; - public ModuleOutputPackagingElementImpl(@NotNull Project project) { - super(ModuleOutputElementType.MODULE_OUTPUT_ELEMENT_TYPE); - myProject = project; - } - - public ModuleOutputPackagingElementImpl(@NotNull Project project, @NotNull ModulePointer modulePointer) { - super(ModuleOutputElementType.MODULE_OUTPUT_ELEMENT_TYPE); + public ModuleOutputPackagingElementBase(PackagingElementType type, Project project, ModulePointer modulePointer) { + super(type); myProject = project; myModulePointer = modulePointer; } - public PackagingElementPresentation createPresentation(@NotNull ArtifactEditorContext context) { - return new DelegatedPackagingElementPresentation(new ModuleElementPresentation(myModulePointer, context)); + public ModuleOutputPackagingElementBase(PackagingElementType type, Project project) { + super(type); + myProject = project; } @Override @@ -69,12 +60,14 @@ public class ModuleOutputPackagingElementImpl extends PackagingElement element) { - return element instanceof ModuleOutputPackagingElementImpl && myModulePointer != null - && myModulePointer.equals(((ModuleOutputPackagingElementImpl)element).myModulePointer); + return element.getClass() == getClass() && myModulePointer != null + && myModulePointer.equals(((ModuleOutputPackagingElementBase)element).myModulePointer); } public ModuleOutputPackagingElementState getState() { @@ -116,11 +112,6 @@ public class ModuleOutputPackagingElementImpl extends PackagingElement> ARTIFACT_ROOT_ELEMENT_TYPE = new ArtifactRootElementType(); private static final PackagingElementType[] STANDARD_TYPES = { DIRECTORY_ELEMENT_TYPE, ARCHIVE_ELEMENT_TYPE, - LibraryElementType.LIBRARY_ELEMENT_TYPE, ModuleOutputElementType.MODULE_OUTPUT_ELEMENT_TYPE, + LibraryElementType.LIBRARY_ELEMENT_TYPE, ProductionModuleOutputElementType.ELEMENT_TYPE, TestModuleOutputElementType.ELEMENT_TYPE, ArtifactElementType.ARTIFACT_ELEMENT_TYPE, FILE_COPY_ELEMENT_TYPE, DIRECTORY_COPY_ELEMENT_TYPE, EXTRACTED_DIRECTORY_ELEMENT_TYPE }; @@ -181,14 +181,21 @@ public class PackagingElementFactoryImpl extends PackagingElementFactory { @NotNull public PackagingElement createModuleOutput(@NotNull String moduleName, @NotNull Project project) { final ModulePointer pointer = ModulePointerManager.getInstance(project).create(moduleName); - return new ModuleOutputPackagingElementImpl(project, pointer); + return new ProductionModuleOutputPackagingElement(project, pointer); } @NotNull @Override public PackagingElement createModuleOutput(@NotNull Module module) { final ModulePointer modulePointer = ModulePointerManager.getInstance(module.getProject()).create(module); - return new ModuleOutputPackagingElementImpl(module.getProject(), modulePointer); + return new ProductionModuleOutputPackagingElement(module.getProject(), modulePointer); + } + + @NotNull + @Override + public PackagingElement createTestModuleOutput(@NotNull Module module) { + ModulePointer pointer = ModulePointerManager.getInstance(module.getProject()).create(module); + return new TestModuleOutputPackagingElement(module.getProject(), pointer); } @NotNull diff --git a/java/compiler/impl/src/com/intellij/packaging/impl/elements/ProductionModuleOutputElementType.java b/java/compiler/impl/src/com/intellij/packaging/impl/elements/ProductionModuleOutputElementType.java new file mode 100644 index 000000000000..9545b365961e --- /dev/null +++ b/java/compiler/impl/src/com/intellij/packaging/impl/elements/ProductionModuleOutputElementType.java @@ -0,0 +1,65 @@ +/* + * Copyright 2000-2009 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.packaging.impl.elements; + +import com.intellij.openapi.compiler.CompilerBundle; +import com.intellij.openapi.module.Module; +import com.intellij.openapi.module.ModulePointer; +import com.intellij.openapi.project.Project; +import com.intellij.openapi.roots.ui.configuration.ModulesProvider; +import com.intellij.openapi.util.IconLoader; +import com.intellij.packaging.ui.ArtifactEditorContext; +import org.jetbrains.annotations.NotNull; + +import javax.swing.*; +import java.util.ArrayList; +import java.util.List; + +/** +* @author nik +*/ +public class ProductionModuleOutputElementType extends ModuleOutputElementTypeBase { + public static final ProductionModuleOutputElementType ELEMENT_TYPE = new ProductionModuleOutputElementType(); + + ProductionModuleOutputElementType() { + super("module-output", CompilerBundle.message("element.type.name.module.output")); + } + + @NotNull + public ProductionModuleOutputPackagingElement createEmpty(@NotNull Project project) { + return new ProductionModuleOutputPackagingElement(project); + } + + protected ModuleOutputPackagingElementBase createElement(@NotNull Project project, @NotNull ModulePointer pointer) { + return new ProductionModuleOutputPackagingElement(project, pointer); + } + + @Override + public Icon getCreateElementIcon() { + return IconLoader.getIcon("/nodes/ModuleOpen.png"); + } + + protected List getSuitableModules(ArtifactEditorContext context) { + ArrayList modules = new ArrayList(); + ModulesProvider modulesProvider = context.getModulesProvider(); + for (Module module : modulesProvider.getModules()) { + if (modulesProvider.getRootModel(module).getSourceRootUrls(false).length > 0) { + modules.add(module); + } + } + return modules; + } +} diff --git a/java/compiler/impl/src/com/intellij/packaging/impl/elements/ProductionModuleOutputPackagingElement.java b/java/compiler/impl/src/com/intellij/packaging/impl/elements/ProductionModuleOutputPackagingElement.java new file mode 100644 index 000000000000..6ee8e8c52231 --- /dev/null +++ b/java/compiler/impl/src/com/intellij/packaging/impl/elements/ProductionModuleOutputPackagingElement.java @@ -0,0 +1,75 @@ +/* + * Copyright 2000-2009 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.packaging.impl.elements; + +import com.intellij.openapi.module.Module; +import com.intellij.openapi.module.ModulePointer; +import com.intellij.openapi.project.Project; +import com.intellij.openapi.roots.CompilerModuleExtension; +import com.intellij.openapi.roots.ModuleRootModel; +import com.intellij.openapi.vfs.VirtualFile; +import com.intellij.packaging.elements.ArtifactAntGenerationContext; +import com.intellij.packaging.elements.PackagingElementResolvingContext; +import com.intellij.packaging.impl.ui.DelegatedPackagingElementPresentation; +import com.intellij.packaging.impl.ui.ModuleElementPresentation; +import com.intellij.packaging.ui.ArtifactEditorContext; +import com.intellij.packaging.ui.PackagingElementPresentation; +import org.jetbrains.annotations.NonNls; +import org.jetbrains.annotations.NotNull; + +import java.util.Arrays; +import java.util.Collection; +import java.util.Collections; + +/** + * @author nik + */ +public class ProductionModuleOutputPackagingElement extends ModuleOutputPackagingElementBase { + public ProductionModuleOutputPackagingElement(@NotNull Project project) { + super(ProductionModuleOutputElementType.ELEMENT_TYPE, project); + } + + public ProductionModuleOutputPackagingElement(@NotNull Project project, @NotNull ModulePointer modulePointer) { + super(ProductionModuleOutputElementType.ELEMENT_TYPE, project, modulePointer); + } + + @NonNls @Override + public String toString() { + return "module:" + getModuleName(); + } + + protected String getModuleOutputAntProperty(ArtifactAntGenerationContext generationContext) { + return generationContext.getModuleOutputPath(myModulePointer.getModuleName()); + } + + protected VirtualFile getModuleOutputPath(CompilerModuleExtension extension) { + return extension.getCompilerOutputPath(); + } + + @NotNull + @Override + public Collection getSourceRoots(PackagingElementResolvingContext context) { + Module module = findModule(context); + if (module == null) return Collections.emptyList(); + + ModuleRootModel rootModel = context.getModulesProvider().getRootModel(module); + return Arrays.asList(rootModel.getSourceRoots(false)); + } + + public PackagingElementPresentation createPresentation(@NotNull ArtifactEditorContext context) { + return new DelegatedPackagingElementPresentation(new ModuleElementPresentation(myModulePointer, context, false)); + } +} diff --git a/java/compiler/impl/src/com/intellij/packaging/impl/elements/TestModuleOutputElementType.java b/java/compiler/impl/src/com/intellij/packaging/impl/elements/TestModuleOutputElementType.java new file mode 100644 index 000000000000..b8ec5ecab07f --- /dev/null +++ b/java/compiler/impl/src/com/intellij/packaging/impl/elements/TestModuleOutputElementType.java @@ -0,0 +1,78 @@ +/* + * Copyright 2000-2011 JetBrains s.r.o. + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ +package com.intellij.packaging.impl.elements; + +import com.intellij.openapi.compiler.CompilerBundle; +import com.intellij.openapi.module.Module; +import com.intellij.openapi.module.ModulePointer; +import com.intellij.openapi.project.Project; +import com.intellij.openapi.roots.ContentEntry; +import com.intellij.openapi.roots.ModuleRootModel; +import com.intellij.openapi.roots.SourceFolder; +import com.intellij.openapi.roots.ui.configuration.ModulesProvider; +import com.intellij.packaging.ui.ArtifactEditorContext; +import com.intellij.util.Icons; +import org.jetbrains.annotations.NotNull; + +import javax.swing.*; +import java.util.ArrayList; +import java.util.List; + +/** + * @author nik + */ +public class TestModuleOutputElementType extends ModuleOutputElementTypeBase { + public static final TestModuleOutputElementType ELEMENT_TYPE = new TestModuleOutputElementType(); + + public TestModuleOutputElementType() { + super("module-test-output", CompilerBundle.message("element.type.name.module.test.output")); + } + + @NotNull + @Override + public TestModuleOutputPackagingElement createEmpty(@NotNull Project project) { + return new TestModuleOutputPackagingElement(project); + } + + protected ModuleOutputPackagingElementBase createElement(@NotNull Project project, @NotNull ModulePointer pointer) { + return new TestModuleOutputPackagingElement(project, pointer); + } + + @Override + public Icon getCreateElementIcon() { + return Icons.TEST_SOURCE_FOLDER; + } + + protected List getSuitableModules(ArtifactEditorContext context) { + ModulesProvider modulesProvider = context.getModulesProvider(); + ArrayList modules = new ArrayList(); + for (Module module : modulesProvider.getModules()) { + if (hasTestSourceRoots(modulesProvider.getRootModel(module))) { + modules.add(module); + } + } + return modules; + } + + private static boolean hasTestSourceRoots(final ModuleRootModel rootModel) { + for (ContentEntry entry : rootModel.getContentEntries()) { + for (SourceFolder folder : entry.getSourceFolders()) { + if (folder.isTestSource()) return true; + } + } + return false; + } +} diff --git a/java/compiler/impl/src/com/intellij/packaging/impl/elements/TestModuleOutputPackagingElement.java b/java/compiler/impl/src/com/intellij/packaging/impl/elements/TestModuleOutputPackagingElement.java new file mode 100644 index 000000000000..f3110a09f505 --- /dev/null +++ b/java/compiler/impl/src/com/intellij/packaging/impl/elements/TestModuleOutputPackagingElement.java @@ -0,0 +1,86 @@ +/* + * Copyright 2000-2011 JetBrains s.r.o. + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ +package com.intellij.packaging.impl.elements; + +import com.intellij.openapi.module.Module; +import com.intellij.openapi.module.ModulePointer; +import com.intellij.openapi.project.Project; +import com.intellij.openapi.roots.CompilerModuleExtension; +import com.intellij.openapi.roots.ContentEntry; +import com.intellij.openapi.roots.ModuleRootModel; +import com.intellij.openapi.roots.SourceFolder; +import com.intellij.openapi.vfs.VirtualFile; +import com.intellij.packaging.elements.ArtifactAntGenerationContext; +import com.intellij.packaging.elements.PackagingElementResolvingContext; +import com.intellij.packaging.impl.ui.DelegatedPackagingElementPresentation; +import com.intellij.packaging.impl.ui.ModuleElementPresentation; +import com.intellij.packaging.ui.ArtifactEditorContext; +import com.intellij.packaging.ui.PackagingElementPresentation; +import com.intellij.util.SmartList; +import com.intellij.util.containers.ContainerUtil; +import org.jetbrains.annotations.NotNull; + +import java.util.Collection; +import java.util.Collections; +import java.util.List; + +/** + * @author nik + */ +public class TestModuleOutputPackagingElement extends ModuleOutputPackagingElementBase { + public TestModuleOutputPackagingElement(Project project) { + super(TestModuleOutputElementType.ELEMENT_TYPE, project); + } + + public TestModuleOutputPackagingElement(Project project, ModulePointer modulePointer) { + super(TestModuleOutputElementType.ELEMENT_TYPE, project, modulePointer); + } + + @Override + public String toString() { + return "module-tests:" + getModuleName(); + } + + protected String getModuleOutputAntProperty(ArtifactAntGenerationContext generationContext) { + return generationContext.getModuleTestOutputPath(myModulePointer.getModuleName()); + } + + protected VirtualFile getModuleOutputPath(CompilerModuleExtension extension) { + return extension.getCompilerOutputPathForTests(); + } + + @NotNull + @Override + public Collection getSourceRoots(PackagingElementResolvingContext context) { + Module module = findModule(context); + if (module == null) return Collections.emptyList(); + + List roots = new SmartList(); + ModuleRootModel rootModel = context.getModulesProvider().getRootModel(module); + for (ContentEntry entry : rootModel.getContentEntries()) { + for (SourceFolder folder : entry.getSourceFolders()) { + if (folder.isTestSource()) { + ContainerUtil.addIfNotNull(folder.getFile(), roots); + } + } + } + return roots; + } + + public PackagingElementPresentation createPresentation(@NotNull ArtifactEditorContext context) { + return new DelegatedPackagingElementPresentation(new ModuleElementPresentation(myModulePointer, context, true)); + } +} diff --git a/java/compiler/impl/src/com/intellij/packaging/impl/ui/ModuleElementPresentation.java b/java/compiler/impl/src/com/intellij/packaging/impl/ui/ModuleElementPresentation.java index 48d8319dcf64..47c793ba7b28 100644 --- a/java/compiler/impl/src/com/intellij/packaging/impl/ui/ModuleElementPresentation.java +++ b/java/compiler/impl/src/com/intellij/packaging/impl/ui/ModuleElementPresentation.java @@ -20,10 +20,11 @@ import com.intellij.openapi.compiler.CompilerBundle; import com.intellij.openapi.module.ModifiableModuleModel; import com.intellij.openapi.module.Module; import com.intellij.openapi.module.ModulePointer; +import com.intellij.packaging.ui.ArtifactEditorContext; import com.intellij.packaging.ui.PackagingElementWeights; import com.intellij.packaging.ui.TreeNodePresentation; -import com.intellij.packaging.ui.ArtifactEditorContext; import com.intellij.ui.SimpleTextAttributes; +import com.intellij.util.Icons; import org.jetbrains.annotations.NotNull; import org.jetbrains.annotations.Nullable; @@ -33,10 +34,12 @@ import org.jetbrains.annotations.Nullable; public class ModuleElementPresentation extends TreeNodePresentation { private final ModulePointer myModulePointer; private final ArtifactEditorContext myContext; + private final boolean myTestOutput; - public ModuleElementPresentation(@Nullable ModulePointer modulePointer, @NotNull ArtifactEditorContext context) { + public ModuleElementPresentation(@Nullable ModulePointer modulePointer, @NotNull ArtifactEditorContext context, final boolean testOutput) { myModulePointer = modulePointer; myContext = context; + myTestOutput = testOutput; } public String getPresentableName() { @@ -68,7 +71,10 @@ public class ModuleElementPresentation extends TreeNodePresentation { public void render(@NotNull PresentationData presentationData, SimpleTextAttributes mainAttributes, SimpleTextAttributes commentAttributes) { final Module module = findModule(); - if (module != null) { + if (myTestOutput) { + presentationData.setIcons(Icons.TEST_SOURCE_FOLDER); + } + else if (module != null) { presentationData.setOpenIcon(module.getModuleType().getNodeIcon(true)); presentationData.setClosedIcon(module.getModuleType().getNodeIcon(false)); } @@ -90,8 +96,9 @@ public class ModuleElementPresentation extends TreeNodePresentation { moduleName = ""; } - presentationData.addText(CompilerBundle.message("node.text.0.compile.output", moduleName), - module != null ? mainAttributes : SimpleTextAttributes.ERROR_ATTRIBUTES); + String text = myTestOutput ? CompilerBundle.message("node.text.0.test.compile.output", moduleName) + : CompilerBundle.message("node.text.0.compile.output", moduleName); + presentationData.addText(text, module != null ? mainAttributes : SimpleTextAttributes.ERROR_ATTRIBUTES); } @Override diff --git a/java/compiler/openapi/src/com/intellij/packaging/elements/ArtifactAntGenerationContext.java b/java/compiler/openapi/src/com/intellij/packaging/elements/ArtifactAntGenerationContext.java index 9adf2bd89663..46864f3984d8 100644 --- a/java/compiler/openapi/src/com/intellij/packaging/elements/ArtifactAntGenerationContext.java +++ b/java/compiler/openapi/src/com/intellij/packaging/elements/ArtifactAntGenerationContext.java @@ -37,6 +37,8 @@ public interface ArtifactAntGenerationContext { String getModuleOutputPath(@NonNls String moduleName); + String getModuleTestOutputPath(@NonNls String moduleName); + String getSubstitutedPath(@NonNls String path); String getArtifactOutputProperty(@NotNull Artifact artifact); diff --git a/java/compiler/openapi/src/com/intellij/packaging/elements/PackagingElementFactory.java b/java/compiler/openapi/src/com/intellij/packaging/elements/PackagingElementFactory.java index eaf0c6f2554e..90fb5b610a55 100644 --- a/java/compiler/openapi/src/com/intellij/packaging/elements/PackagingElementFactory.java +++ b/java/compiler/openapi/src/com/intellij/packaging/elements/PackagingElementFactory.java @@ -52,6 +52,9 @@ public abstract class PackagingElementFactory { @NotNull public abstract PackagingElement createModuleOutput(@NotNull Module module); + @NotNull + public abstract PackagingElement createTestModuleOutput(@NotNull Module module); + @NotNull public abstract List> createLibraryElements(@NotNull Library library); diff --git a/java/idea-ui/src/com/intellij/openapi/roots/ui/configuration/artifacts/sourceItems/ModuleOutputSourceItem.java b/java/idea-ui/src/com/intellij/openapi/roots/ui/configuration/artifacts/sourceItems/ModuleOutputSourceItem.java index 9feefd1a5fb0..160f4c4e2599 100644 --- a/java/idea-ui/src/com/intellij/openapi/roots/ui/configuration/artifacts/sourceItems/ModuleOutputSourceItem.java +++ b/java/idea-ui/src/com/intellij/openapi/roots/ui/configuration/artifacts/sourceItems/ModuleOutputSourceItem.java @@ -20,7 +20,7 @@ import com.intellij.openapi.module.ModulePointer; import com.intellij.openapi.module.ModulePointerManager; import com.intellij.packaging.elements.PackagingElement; import com.intellij.packaging.elements.PackagingElementOutputKind; -import com.intellij.packaging.impl.elements.ModuleOutputPackagingElementImpl; +import com.intellij.packaging.impl.elements.ProductionModuleOutputPackagingElement; import com.intellij.packaging.impl.ui.ModuleElementPresentation; import com.intellij.packaging.ui.*; import org.jetbrains.annotations.NotNull; @@ -49,7 +49,7 @@ public class ModuleOutputSourceItem extends PackagingSourceItem { @Override public SourceItemPresentation createPresentation(@NotNull ArtifactEditorContext context) { final ModulePointer modulePointer = ModulePointerManager.getInstance(context.getProject()).create(myModule); - return new DelegatedSourceItemPresentation(new ModuleElementPresentation(modulePointer, context)) { + return new DelegatedSourceItemPresentation(new ModuleElementPresentation(modulePointer, context, false)) { @Override public int getWeight() { return SourceItemWeights.MODULE_OUTPUT_WEIGHT; @@ -60,7 +60,7 @@ public class ModuleOutputSourceItem extends PackagingSourceItem { @NotNull public List> createElements(@NotNull ArtifactEditorContext context) { final ModulePointer modulePointer = ModulePointerManager.getInstance(context.getProject()).create(myModule); - return Collections.singletonList(new ModuleOutputPackagingElementImpl(context.getProject(), modulePointer)); + return Collections.singletonList(new ProductionModuleOutputPackagingElement(context.getProject(), modulePointer)); } @NotNull diff --git a/java/idea-ui/src/com/intellij/openapi/roots/ui/configuration/artifacts/sourceItems/ModulesAndLibrariesSourceItemsProvider.java b/java/idea-ui/src/com/intellij/openapi/roots/ui/configuration/artifacts/sourceItems/ModulesAndLibrariesSourceItemsProvider.java index 48fd8edf35a2..8b3688dd8a25 100644 --- a/java/idea-ui/src/com/intellij/openapi/roots/ui/configuration/artifacts/sourceItems/ModulesAndLibrariesSourceItemsProvider.java +++ b/java/idea-ui/src/com/intellij/openapi/roots/ui/configuration/artifacts/sourceItems/ModulesAndLibrariesSourceItemsProvider.java @@ -24,7 +24,7 @@ import com.intellij.openapi.vfs.VirtualFile; import com.intellij.packaging.artifacts.Artifact; import com.intellij.packaging.impl.artifacts.ArtifactUtil; import com.intellij.packaging.impl.elements.FileCopyPackagingElement; -import com.intellij.packaging.impl.elements.ModuleOutputElementType; +import com.intellij.packaging.impl.elements.ProductionModuleOutputElementType; import com.intellij.packaging.impl.elements.ModuleOutputPackagingElement; import com.intellij.packaging.impl.elements.PackagingElementFactoryImpl; import com.intellij.packaging.ui.ArtifactEditorContext; @@ -109,7 +109,7 @@ public class ModulesAndLibrariesSourceItemsProvider extends PackagingSourceItems private static List getNotAddedModules(@NotNull final ArtifactEditorContext context, @NotNull Artifact artifact, final Module... allModules) { final Set modules = new HashSet(Arrays.asList(allModules)); - ArtifactUtil.processPackagingElements(artifact, ModuleOutputElementType.MODULE_OUTPUT_ELEMENT_TYPE, new Processor() { + ArtifactUtil.processPackagingElements(artifact, ProductionModuleOutputElementType.ELEMENT_TYPE, new Processor() { public boolean process(ModuleOutputPackagingElement moduleOutputPackagingElement) { modules.remove(moduleOutputPackagingElement.findModule(context)); return true; diff --git a/resources-en/src/messages/CompilerBundle.properties b/resources-en/src/messages/CompilerBundle.properties index b7ab2a5bfca9..154f2e72dc1c 100644 --- a/resources-en/src/messages/CompilerBundle.properties +++ b/resources-en/src/messages/CompilerBundle.properties @@ -159,8 +159,10 @@ dialog.title.choose.artifacts=Choose Artifacts node.text.0.directory.content=''{0}'' directory content element.type.name.library.files=Library Files node.text.0.compile.output=''{0}'' compile output +node.text.0.test.compile.output=''{0}'' test compile output node.text.0.with.dependencies=''{0}'' with dependencies element.type.name.module.output=Module Output +element.type.name.module.test.output=Module Test Output element.type.name.directory=Directory element.type.name.archive=Archive artifact.type.plain=Other From 8dbceed8dae68735cd045764f602d92fe936514b Mon Sep 17 00:00:00 2001 From: Dmitry Avdeev Date: Tue, 5 Apr 2011 11:53:39 +0400 Subject: [PATCH 20/65] cleanup --- .../src/com/intellij/util/xml/DomDocumentationProvider.java | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/xml/dom-impl/src/com/intellij/util/xml/DomDocumentationProvider.java b/xml/dom-impl/src/com/intellij/util/xml/DomDocumentationProvider.java index 77ae5cb36ca7..0daaf2d95612 100644 --- a/xml/dom-impl/src/com/intellij/util/xml/DomDocumentationProvider.java +++ b/xml/dom-impl/src/com/intellij/util/xml/DomDocumentationProvider.java @@ -53,7 +53,7 @@ public class DomDocumentationProvider implements DocumentationProvider { String documentation = template.createPresentation(domElement).getDocumentation(); if (documentation != null) return documentation; } - return ElementPresentationManagerImpl.getDocumentationForElement(domElement); + return ElementPresentationManager.getDocumentationForElement(domElement); } public PsiElement getDocumentationElementForLookupItem(final PsiManager psiManager, final Object object, final PsiElement element) { From 7731bcd245196de379bc873268ca9971675bc8e7 Mon Sep 17 00:00:00 2001 From: Dmitry Avdeev Date: Tue, 5 Apr 2011 12:54:00 +0400 Subject: [PATCH 21/65] quick navigation info from ElementPresentationUtil --- .../navigation/CtrlMouseHandler.java | 22 +++++++++++++++++++ .../XmlDocumentationProvider.java | 14 +----------- 2 files changed, 23 insertions(+), 13 deletions(-) diff --git a/platform/lang-impl/src/com/intellij/codeInsight/navigation/CtrlMouseHandler.java b/platform/lang-impl/src/com/intellij/codeInsight/navigation/CtrlMouseHandler.java index 2cba06de1b5d..21e4ffdd5685 100644 --- a/platform/lang-impl/src/com/intellij/codeInsight/navigation/CtrlMouseHandler.java +++ b/platform/lang-impl/src/com/intellij/codeInsight/navigation/CtrlMouseHandler.java @@ -59,6 +59,7 @@ import com.intellij.openapi.project.Project; import com.intellij.openapi.startup.StartupManager; import com.intellij.openapi.util.Comparing; import com.intellij.openapi.util.TextRange; +import com.intellij.openapi.util.text.StringUtil; import com.intellij.openapi.vfs.VirtualFile; import com.intellij.pom.Navigatable; import com.intellij.psi.*; @@ -66,6 +67,8 @@ import com.intellij.psi.impl.source.tree.injected.InjectedLanguageUtil; import com.intellij.psi.search.searches.DefinitionsSearch; import com.intellij.psi.util.PsiUtilBase; import com.intellij.ui.LightweightHint; +import com.intellij.usageView.UsageViewShortNameLocation; +import com.intellij.usageView.UsageViewTypeLocation; import com.intellij.util.Processor; import org.jetbrains.annotations.NotNull; import org.jetbrains.annotations.Nullable; @@ -84,6 +87,21 @@ public class CtrlMouseHandler extends AbstractProjectComponent { private TooltipProvider myTooltipProvider = null; private final FileEditorManager myFileEditorManager; + @Nullable + public static String getQuickNavigateInfo(PsiElement element) { + final String name = ElementDescriptionUtil.getElementDescription(element, UsageViewShortNameLocation.INSTANCE); + if (StringUtil.isEmpty(name)) return null; + final String typeName = ElementDescriptionUtil.getElementDescription(element, UsageViewTypeLocation.INSTANCE); + final PsiFile file = element.getContainingFile(); + final StringBuilder sb = new StringBuilder(); + if (StringUtil.isNotEmpty(typeName)) sb.append(typeName).append(" "); + sb.append("\"").append(name).append("\""); + if (file != null && file.isPhysical()) { + sb.append(" [").append(file.getName()).append("]"); + } + return sb.toString(); + } + private enum BrowseMode {None, Declaration, TypeDeclaration, Implementation} private final KeyListener myEditorKeyListener = new KeyAdapter() { @@ -231,6 +249,10 @@ public class CtrlMouseHandler extends AbstractProjectComponent { final DocumentationProvider documentationProvider = DocumentationManager.getProviderFromElement(element, atPointer); String info = documentationProvider.getQuickNavigateInfo(element, atPointer); + if (info == null) { + info = getQuickNavigateInfo(element); + } + if (info != null) { return info; } diff --git a/xml/impl/src/com/intellij/xml/util/documentation/XmlDocumentationProvider.java b/xml/impl/src/com/intellij/xml/util/documentation/XmlDocumentationProvider.java index 7446c52e97d4..0b5a7f28c5b2 100644 --- a/xml/impl/src/com/intellij/xml/util/documentation/XmlDocumentationProvider.java +++ b/xml/impl/src/com/intellij/xml/util/documentation/XmlDocumentationProvider.java @@ -32,8 +32,6 @@ import com.intellij.psi.templateLanguages.TemplateLanguageFileViewProvider; import com.intellij.psi.tree.IElementType; import com.intellij.psi.util.PsiTreeUtil; import com.intellij.psi.xml.*; -import com.intellij.usageView.UsageViewShortNameLocation; -import com.intellij.usageView.UsageViewTypeLocation; import com.intellij.util.IncorrectOperationException; import com.intellij.util.Processor; import com.intellij.xml.XmlAttributeDescriptor; @@ -66,17 +64,7 @@ public class XmlDocumentationProvider implements DocumentationProvider { if (element instanceof SchemaPrefix) { return ((SchemaPrefix)element).getQuickNavigateInfo(); } - final String name = ElementDescriptionUtil.getElementDescription(element, UsageViewShortNameLocation.INSTANCE); - if (StringUtil.isEmpty(name)) return null; - final String typeName = ElementDescriptionUtil.getElementDescription(element, UsageViewTypeLocation.INSTANCE); - final PsiFile file = element.getContainingFile(); - final StringBuilder sb = new StringBuilder(); - if (StringUtil.isNotEmpty(typeName)) sb.append(typeName).append(" "); - sb.append("\"").append(name).append("\""); - if (file != null && file.isPhysical()) { - sb.append(" [").append(file.getName()).append("]"); - } - return sb.toString(); + return null; } public List getUrlFor(PsiElement element, PsiElement originalElement) { From 029bfb86f102204af6913864638b8bc9f195ae99 Mon Sep 17 00:00:00 2001 From: Dmitry Avdeev Date: Tue, 5 Apr 2011 13:01:13 +0400 Subject: [PATCH 22/65] quick navigation info from ElementPresentationUtil --- .../navigation/CtrlMouseHandler.java | 36 +++++++++---------- 1 file changed, 17 insertions(+), 19 deletions(-) diff --git a/platform/lang-impl/src/com/intellij/codeInsight/navigation/CtrlMouseHandler.java b/platform/lang-impl/src/com/intellij/codeInsight/navigation/CtrlMouseHandler.java index 21e4ffdd5685..f1342f4bcb70 100644 --- a/platform/lang-impl/src/com/intellij/codeInsight/navigation/CtrlMouseHandler.java +++ b/platform/lang-impl/src/com/intellij/codeInsight/navigation/CtrlMouseHandler.java @@ -87,23 +87,9 @@ public class CtrlMouseHandler extends AbstractProjectComponent { private TooltipProvider myTooltipProvider = null; private final FileEditorManager myFileEditorManager; - @Nullable - public static String getQuickNavigateInfo(PsiElement element) { - final String name = ElementDescriptionUtil.getElementDescription(element, UsageViewShortNameLocation.INSTANCE); - if (StringUtil.isEmpty(name)) return null; - final String typeName = ElementDescriptionUtil.getElementDescription(element, UsageViewTypeLocation.INSTANCE); - final PsiFile file = element.getContainingFile(); - final StringBuilder sb = new StringBuilder(); - if (StringUtil.isNotEmpty(typeName)) sb.append(typeName).append(" "); - sb.append("\"").append(name).append("\""); - if (file != null && file.isPhysical()) { - sb.append(" [").append(file.getName()).append("]"); - } - return sb.toString(); - } - private enum BrowseMode {None, Declaration, TypeDeclaration, Implementation} + private enum BrowseMode {None, Declaration, TypeDeclaration, Implementation;} private final KeyListener myEditorKeyListener = new KeyAdapter() { public void keyPressed(final KeyEvent e) { handleKey(e); @@ -249,9 +235,6 @@ public class CtrlMouseHandler extends AbstractProjectComponent { final DocumentationProvider documentationProvider = DocumentationManager.getProviderFromElement(element, atPointer); String info = documentationProvider.getQuickNavigateInfo(element, atPointer); - if (info == null) { - info = getQuickNavigateInfo(element); - } if (info != null) { return info; @@ -271,7 +254,22 @@ public class CtrlMouseHandler extends AbstractProjectComponent { } } - return null; + return getQuickNavigateInfo(element); + } + + @Nullable + private static String getQuickNavigateInfo(PsiElement element) { + final String name = ElementDescriptionUtil.getElementDescription(element, UsageViewShortNameLocation.INSTANCE); + if (StringUtil.isEmpty(name)) return null; + final String typeName = ElementDescriptionUtil.getElementDescription(element, UsageViewTypeLocation.INSTANCE); + final PsiFile file = element.getContainingFile(); + final StringBuilder sb = new StringBuilder(); + if (StringUtil.isNotEmpty(typeName)) sb.append(typeName).append(" "); + sb.append("\"").append(name).append("\""); + if (file != null && file.isPhysical()) { + sb.append(" [").append(file.getName()).append("]"); + } + return sb.toString(); } private abstract static class Info { From 02cb0e467c118392635d276f2592608d353607c9 Mon Sep 17 00:00:00 2001 From: Dmitry Avdeev Date: Tue, 5 Apr 2011 13:02:06 +0400 Subject: [PATCH 23/65] cleanup --- .../com/intellij/codeInsight/navigation/CtrlMouseHandler.java | 4 +--- 1 file changed, 1 insertion(+), 3 deletions(-) diff --git a/platform/lang-impl/src/com/intellij/codeInsight/navigation/CtrlMouseHandler.java b/platform/lang-impl/src/com/intellij/codeInsight/navigation/CtrlMouseHandler.java index f1342f4bcb70..d66d4c1812a4 100644 --- a/platform/lang-impl/src/com/intellij/codeInsight/navigation/CtrlMouseHandler.java +++ b/platform/lang-impl/src/com/intellij/codeInsight/navigation/CtrlMouseHandler.java @@ -87,9 +87,7 @@ public class CtrlMouseHandler extends AbstractProjectComponent { private TooltipProvider myTooltipProvider = null; private final FileEditorManager myFileEditorManager; - - - private enum BrowseMode {None, Declaration, TypeDeclaration, Implementation;} + private enum BrowseMode {None, Declaration, TypeDeclaration, Implementation} private final KeyListener myEditorKeyListener = new KeyAdapter() { public void keyPressed(final KeyEvent e) { handleKey(e); From c56d169cccf2eef9de96af3819c14d48c3123959 Mon Sep 17 00:00:00 2001 From: Dmitry Avdeev Date: Tue, 5 Apr 2011 13:15:27 +0400 Subject: [PATCH 24/65] javadoc --- platform/lang-api/src/com/intellij/pom/PomTargetPsiElement.java | 1 + 1 file changed, 1 insertion(+) diff --git a/platform/lang-api/src/com/intellij/pom/PomTargetPsiElement.java b/platform/lang-api/src/com/intellij/pom/PomTargetPsiElement.java index 3e8c4ac13f54..1c6faf159503 100644 --- a/platform/lang-api/src/com/intellij/pom/PomTargetPsiElement.java +++ b/platform/lang-api/src/com/intellij/pom/PomTargetPsiElement.java @@ -20,6 +20,7 @@ import org.jetbrains.annotations.NotNull; /** * @author peter + * @see com.intellij.pom.references.PomService#convertToPsi(PomTarget) */ public interface PomTargetPsiElement extends PsiElement { From 6988a8b69925f28354ee20f11337f63259667556 Mon Sep 17 00:00:00 2001 From: Dmitry Avdeev Date: Tue, 5 Apr 2011 13:21:00 +0400 Subject: [PATCH 25/65] quick navigation info from ElementPresentationUtil --- .../intellij/codeInsight/navigation/CtrlMouseHandler.java | 6 ++++-- 1 file changed, 4 insertions(+), 2 deletions(-) diff --git a/platform/lang-impl/src/com/intellij/codeInsight/navigation/CtrlMouseHandler.java b/platform/lang-impl/src/com/intellij/codeInsight/navigation/CtrlMouseHandler.java index d66d4c1812a4..382e653c7945 100644 --- a/platform/lang-impl/src/com/intellij/codeInsight/navigation/CtrlMouseHandler.java +++ b/platform/lang-impl/src/com/intellij/codeInsight/navigation/CtrlMouseHandler.java @@ -233,7 +233,9 @@ public class CtrlMouseHandler extends AbstractProjectComponent { final DocumentationProvider documentationProvider = DocumentationManager.getProviderFromElement(element, atPointer); String info = documentationProvider.getQuickNavigateInfo(element, atPointer); - + if (info == null) { + info = getQuickNavigateInfo(element); + } if (info != null) { return info; } @@ -252,7 +254,7 @@ public class CtrlMouseHandler extends AbstractProjectComponent { } } - return getQuickNavigateInfo(element); + return null; } @Nullable From b55d580726c0d6cf3e2c1a6a8af3a88ee710cdfa Mon Sep 17 00:00:00 2001 From: Dmitry Avdeev Date: Tue, 5 Apr 2011 13:23:49 +0400 Subject: [PATCH 26/65] quick navigation info from ElementPresentationUtil --- .../intellij/codeInsight/navigation/CtrlMouseHandler.java | 8 +++++--- 1 file changed, 5 insertions(+), 3 deletions(-) diff --git a/platform/lang-impl/src/com/intellij/codeInsight/navigation/CtrlMouseHandler.java b/platform/lang-impl/src/com/intellij/codeInsight/navigation/CtrlMouseHandler.java index 382e653c7945..fe72849f38f1 100644 --- a/platform/lang-impl/src/com/intellij/codeInsight/navigation/CtrlMouseHandler.java +++ b/platform/lang-impl/src/com/intellij/codeInsight/navigation/CtrlMouseHandler.java @@ -233,9 +233,6 @@ public class CtrlMouseHandler extends AbstractProjectComponent { final DocumentationProvider documentationProvider = DocumentationManager.getProviderFromElement(element, atPointer); String info = documentationProvider.getQuickNavigateInfo(element, atPointer); - if (info == null) { - info = getQuickNavigateInfo(element); - } if (info != null) { return info; } @@ -247,6 +244,11 @@ public class CtrlMouseHandler extends AbstractProjectComponent { } } + info = getQuickNavigateInfo(element); + if (info != null) { + return info; + } + if (element instanceof NavigationItem) { final ItemPresentation presentation = ((NavigationItem)element).getPresentation(); if (presentation != null) { From 057be17c9b367ffa681ab9e2bc5a7f478e96f438 Mon Sep 17 00:00:00 2001 From: irengrig Date: Wed, 6 Apr 2011 11:45:14 +0400 Subject: [PATCH 27/65] http://ea.jetbrains.com/browser/ea_reports/268036 --- .../openapi/vcs/checkin/TodoCheckinHandlerWorker.java | 8 ++++++-- 1 file changed, 6 insertions(+), 2 deletions(-) diff --git a/platform/lang-impl/src/com/intellij/openapi/vcs/checkin/TodoCheckinHandlerWorker.java b/platform/lang-impl/src/com/intellij/openapi/vcs/checkin/TodoCheckinHandlerWorker.java index 9a6f9aef0d04..e823573ef26e 100644 --- a/platform/lang-impl/src/com/intellij/openapi/vcs/checkin/TodoCheckinHandlerWorker.java +++ b/platform/lang-impl/src/com/intellij/openapi/vcs/checkin/TodoCheckinHandlerWorker.java @@ -34,6 +34,7 @@ import com.intellij.openapi.util.text.StringUtil; import com.intellij.openapi.vcs.FilePath; import com.intellij.openapi.vcs.VcsException; import com.intellij.openapi.vcs.changes.Change; +import com.intellij.openapi.vfs.LocalFileSystem; import com.intellij.openapi.vfs.VirtualFile; import com.intellij.psi.PsiFile; import com.intellij.psi.PsiFileFactory; @@ -104,8 +105,11 @@ public class TodoCheckinHandlerWorker { for (Change change : changes) { ProgressManager.checkCanceled(); if (change.getAfterRevision() == null) continue; - final VirtualFile afterFile = change.getAfterRevision().getFile().getVirtualFile(); - if (afterFile.isDirectory() || afterFile.getFileType().isBinary()) continue; + VirtualFile afterFile = change.getAfterRevision().getFile().getVirtualFile(); + if (afterFile == null) { + afterFile = LocalFileSystem.getInstance().refreshAndFindFileByIoFile(change.getAfterRevision().getFile().getIOFile()); + } + if (afterFile == null || afterFile.isDirectory() || afterFile.getFileType().isBinary()) continue; myPsiFile = null; if (afterFile.isValid()) { From 0836d5ff07b0937563ba57ef1140f9877dae5314 Mon Sep 17 00:00:00 2001 From: Bas Leijdekkers Date: Wed, 6 Apr 2011 09:54:38 +0200 Subject: [PATCH 28/65] IDEA-67522 (array equals inspection misses == operator on two arrays) Added "Array comparison using '==', instead of 'Arrays.equals()'" inspection --- .../siyeh/InspectionGadgetsBundle.properties | 3 + .../com/siyeh/ig/InspectionGadgetsPlugin.java | 1 + .../ig/bugs/ArrayEqualityInspection.java | 131 ++++++++++++++++++ .../ig/bugs/NumberEqualityInspection.java | 10 +- .../inspectionDescriptions/ArrayEquality.html | 8 ++ 5 files changed, 148 insertions(+), 5 deletions(-) create mode 100644 plugins/InspectionGadgets/src/com/siyeh/ig/bugs/ArrayEqualityInspection.java create mode 100644 plugins/InspectionGadgets/src/inspectionDescriptions/ArrayEquality.html diff --git a/plugins/InspectionGadgets/src/com/siyeh/InspectionGadgetsBundle.properties b/plugins/InspectionGadgets/src/com/siyeh/InspectionGadgetsBundle.properties index 9b8042e92c18..b958c1a993ee 100644 --- a/plugins/InspectionGadgets/src/com/siyeh/InspectionGadgetsBundle.properties +++ b/plugins/InspectionGadgets/src/com/siyeh/InspectionGadgetsBundle.properties @@ -1867,3 +1867,6 @@ html.tag.can.be.javadoc.tag.quickfix=Replace with '{@code ...}' try.finally.can.be.try.with.resources.display.name='try finally' replaceable with 'try' with resources try.finally.can.be.try.with.resources.problem.descriptor=#ref can use automatic resource management try.finally.can.be.try.with.resources.quickfix=Replace with 'try' with resources +array.comparison.display.name=Array comparison using '==', instead of 'Arrays.equals()' +array.comparison.problem.descriptor=Array objects are compared using #ref, not 'Arrays.equals()' #loc +array.comparison.quickfix=Replace with 'Arrays.equals()' diff --git a/plugins/InspectionGadgets/src/com/siyeh/ig/InspectionGadgetsPlugin.java b/plugins/InspectionGadgets/src/com/siyeh/ig/InspectionGadgetsPlugin.java index 4b98f6fa552b..53afc9934869 100644 --- a/plugins/InspectionGadgets/src/com/siyeh/ig/InspectionGadgetsPlugin.java +++ b/plugins/InspectionGadgets/src/com/siyeh/ig/InspectionGadgetsPlugin.java @@ -516,6 +516,7 @@ public class InspectionGadgetsPlugin implements ApplicationComponent, private void registerBugInspections() { m_inspectionClasses.add(ArchaicSystemPropertyAccessInspection.class); + m_inspectionClasses.add(ArrayEqualityInspection.class); m_inspectionClasses.add(ArrayEqualsInspection.class); m_inspectionClasses.add(AssertWithSideEffectsInspection.class); m_inspectionClasses.add(ConstantAssertConditionInspection.class); diff --git a/plugins/InspectionGadgets/src/com/siyeh/ig/bugs/ArrayEqualityInspection.java b/plugins/InspectionGadgets/src/com/siyeh/ig/bugs/ArrayEqualityInspection.java new file mode 100644 index 000000000000..7e13f97ba92b --- /dev/null +++ b/plugins/InspectionGadgets/src/com/siyeh/ig/bugs/ArrayEqualityInspection.java @@ -0,0 +1,131 @@ +/* + * Copyright 2003-2011 Dave Griffith, Bas Leijdekkers + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ +package com.siyeh.ig.bugs; + +import com.intellij.codeInspection.ProblemDescriptor; +import com.intellij.openapi.project.Project; +import com.intellij.psi.*; +import com.intellij.psi.tree.IElementType; +import com.intellij.util.IncorrectOperationException; +import com.siyeh.InspectionGadgetsBundle; +import com.siyeh.ig.BaseInspection; +import com.siyeh.ig.BaseInspectionVisitor; +import com.siyeh.ig.InspectionGadgetsFix; +import com.siyeh.ig.psiutils.ComparisonUtils; +import org.jetbrains.annotations.NonNls; +import org.jetbrains.annotations.NotNull; + +public class ArrayEqualityInspection extends BaseInspection { + + @Override + @NotNull + public String getDisplayName() { + return InspectionGadgetsBundle.message( + "array.comparison.display.name"); + } + + @Override + @NotNull + public String buildErrorString(Object... infos) { + return InspectionGadgetsBundle.message( + "array.comparison.problem.descriptor"); + } + + @Override + public InspectionGadgetsFix buildFix(Object... infos) { + return new ArrayEqualityFix(); + } + + private static class ArrayEqualityFix extends InspectionGadgetsFix { + + @NotNull + @Override + public String getName() { + return InspectionGadgetsBundle.message("array.comparison.quickfix"); + } + + @Override + protected void doFix(Project project, ProblemDescriptor descriptor) + throws IncorrectOperationException { + final PsiElement element = descriptor.getPsiElement(); + final PsiElement parent = element.getParent(); + if (!(parent instanceof PsiBinaryExpression)) { + return; + } + final PsiBinaryExpression binaryExpression = + (PsiBinaryExpression) parent; + final IElementType tokenType = + binaryExpression.getOperationTokenType(); + @NonNls final StringBuilder newExpressionText = new StringBuilder(); + if (JavaTokenType.NE.equals(tokenType)) { + newExpressionText.append('!'); + } else if (!JavaTokenType.EQEQ.equals(tokenType)) { + return; + } + newExpressionText.append("java.util.Arrays.equals("); + newExpressionText.append(binaryExpression.getLOperand().getText()); + newExpressionText.append(','); + final PsiExpression rhs = binaryExpression.getROperand(); + if (rhs == null) { + return; + } + newExpressionText.append(rhs.getText()); + newExpressionText.append(')'); + replaceExpressionAndShorten(binaryExpression, + newExpressionText.toString()); + } + } + + @Override + public BaseInspectionVisitor buildVisitor() { + return new ArrayEqualityVisitor(); + } + + private static class ArrayEqualityVisitor extends BaseInspectionVisitor { + + @Override public void visitBinaryExpression( + @NotNull PsiBinaryExpression expression) { + super.visitBinaryExpression(expression); + if(!(expression.getROperand() != null)){ + return; + } + if (!ComparisonUtils.isEqualityComparison(expression)) { + return; + } + final PsiExpression lhs = expression.getLOperand(); + if (!(lhs.getType() instanceof PsiArrayType)) { + return; + } + final PsiExpression rhs = expression.getROperand(); + if (rhs == null) { + return; + } + if (!(rhs.getType() instanceof PsiArrayType)) { + return; + } + final String lhsText = lhs.getText(); + if (PsiKeyword.NULL.equals(lhsText)) { + return; + } + final String rhsText = rhs.getText(); + if (PsiKeyword.NULL.equals(rhsText)) { + return; + } + final PsiJavaToken sign = expression.getOperationSign(); + registerError(sign); + } + } +} \ No newline at end of file diff --git a/plugins/InspectionGadgets/src/com/siyeh/ig/bugs/NumberEqualityInspection.java b/plugins/InspectionGadgets/src/com/siyeh/ig/bugs/NumberEqualityInspection.java index 3d9b4922c0c4..9ef8c6cf0fd0 100644 --- a/plugins/InspectionGadgets/src/com/siyeh/ig/bugs/NumberEqualityInspection.java +++ b/plugins/InspectionGadgets/src/com/siyeh/ig/bugs/NumberEqualityInspection.java @@ -1,5 +1,5 @@ /* - * Copyright 2003-2010 Dave Griffith, Bas Leijdekkers + * Copyright 2003-2011 Dave Griffith, Bas Leijdekkers * * Licensed under the Apache License, Version 2.0 (the "License"); * you may not use this file except in compliance with the License. @@ -48,7 +48,7 @@ public class NumberEqualityInspection extends BaseInspection { @Override public BaseInspectionVisitor buildVisitor() { - return new ObjectEqualityVisitor(); + return new NumberEqualityVisitor(); } @Override @@ -56,7 +56,7 @@ public class NumberEqualityInspection extends BaseInspection { return new EqualityToEqualsFix(); } - private static class ObjectEqualityVisitor extends BaseInspectionVisitor { + private static class NumberEqualityVisitor extends BaseInspectionVisitor { @Override public void visitBinaryExpression( @NotNull PsiBinaryExpression expression) { @@ -90,8 +90,8 @@ public class NumberEqualityInspection extends BaseInspection { registerError(sign); } - private static boolean hasNumberType(PsiExpression lhs) { - return TypeUtils.expressionHasTypeOrSubtype(lhs, + private static boolean hasNumberType(PsiExpression expression) { + return TypeUtils.expressionHasTypeOrSubtype(expression, CommonClassNames.JAVA_LANG_NUMBER); } } diff --git a/plugins/InspectionGadgets/src/inspectionDescriptions/ArrayEquality.html b/plugins/InspectionGadgets/src/inspectionDescriptions/ArrayEquality.html new file mode 100644 index 000000000000..515d2d82489e --- /dev/null +++ b/plugins/InspectionGadgets/src/inspectionDescriptions/ArrayEquality.html @@ -0,0 +1,8 @@ + + +This inspection reports any use of == to test for Array equality, +rather than the "java.util.Arrays.equals()" method. +

+New in 10.5, Powered by InspectionGadgets + + \ No newline at end of file From bb0fa00b6e25462dd28ec9391dcef7b508d1c192 Mon Sep 17 00:00:00 2001 From: Alexey Kudravtsev Date: Tue, 5 Apr 2011 18:18:19 +0400 Subject: [PATCH 29/65] concurrent injected highlight --- .../daemon/impl/GeneralHighlightingPass.java | 18 ++++++++++++------ 1 file changed, 12 insertions(+), 6 deletions(-) diff --git a/platform/lang-impl/src/com/intellij/codeInsight/daemon/impl/GeneralHighlightingPass.java b/platform/lang-impl/src/com/intellij/codeInsight/daemon/impl/GeneralHighlightingPass.java index d0a9bacbfa29..0a3f4c394c8d 100644 --- a/platform/lang-impl/src/com/intellij/codeInsight/daemon/impl/GeneralHighlightingPass.java +++ b/platform/lang-impl/src/com/intellij/codeInsight/daemon/impl/GeneralHighlightingPass.java @@ -316,15 +316,21 @@ public class GeneralHighlightingPass extends ProgressableTextEditorHighlightingP hosts.addAll(elements1); hosts.addAll(elements2); - PsiLanguageInjectionHost.InjectedPsiVisitor visitor = new PsiLanguageInjectionHost.InjectedPsiVisitor() { + final PsiLanguageInjectionHost.InjectedPsiVisitor visitor = new PsiLanguageInjectionHost.InjectedPsiVisitor() { public void visit(@NotNull PsiFile injectedPsi, @NotNull List places) { - outInjected.add(injectedPsi); + synchronized (outInjected) { + outInjected.add(injectedPsi); + } } }; - for (PsiElement element : hosts) { - progress.checkCanceled(); - InjectedLanguageUtil.enumerate(element, myFile, visitor, false); - } + if (!JobUtil.invokeConcurrentlyUnderProgress(new ArrayList(hosts), new Processor() { + @Override + public boolean process(PsiElement element) { + progress.checkCanceled(); + InjectedLanguageUtil.enumerate(element, myFile, visitor, false); + return true; + } + }, false, progress)) throw new ProcessCanceledException(); } // returns false if canceled From 8650883ee21d13e8209a5ff367f609c66ace0664 Mon Sep 17 00:00:00 2001 From: Alexey Kudravtsev Date: Wed, 6 Apr 2011 11:50:33 +0400 Subject: [PATCH 30/65] PSI element leak fix --- .../quickfix/MakeTypeExplicitFix.java | 37 ++++++++------- .../quickfix/RemoveExplicitConversionFix.java | 24 +++++----- .../quickfix/ReplaceElementFix.java | 4 +- .../quickfix/XPathQuickFixFactory.java | 45 ++++++++----------- 4 files changed, 56 insertions(+), 54 deletions(-) diff --git a/plugins/xpath/xpath-lang/src/org/intellij/lang/xpath/validation/inspections/quickfix/MakeTypeExplicitFix.java b/plugins/xpath/xpath-lang/src/org/intellij/lang/xpath/validation/inspections/quickfix/MakeTypeExplicitFix.java index 52a1b75b1525..d752989aebfe 100644 --- a/plugins/xpath/xpath-lang/src/org/intellij/lang/xpath/validation/inspections/quickfix/MakeTypeExplicitFix.java +++ b/plugins/xpath/xpath-lang/src/org/intellij/lang/xpath/validation/inspections/quickfix/MakeTypeExplicitFix.java @@ -51,24 +51,27 @@ public class MakeTypeExplicitFix extends ReplaceElementFix { } public void invokeImpl(Project project, PsiFile file) throws IncorrectOperationException { - if (myType == XPathType.BOOLEAN) { - if (myElement.getType() == XPathType.STRING) { - final String text; - if (ExpectedTypeUtil.isExplicitConversion(myElement)) { - final XPathExpression expr = ExpectedTypeUtil.unparenthesize(myElement); - assert expr != null; + XPathExpression myElement = (XPathExpression)getStartElement(); + if (myType == XPathType.BOOLEAN) { + if (myElement.getType() == XPathType.STRING) { + final String text; + if (ExpectedTypeUtil.isExplicitConversion(myElement)) { + final XPathExpression expr = ExpectedTypeUtil.unparenthesize(myElement); + assert expr != null; - text = ((XPathFunctionCall)expr).getArgumentList()[0].getText(); - } else { - text = myElement.getText(); - } - replace("string-length(" + text + ") > 0"); - return; - } else if (myElement.getType() == XPathType.NODESET) { - replace("count(" + myElement.getText() + ") > 0"); - return; - } + text = ((XPathFunctionCall)expr).getArgumentList()[0].getText(); + } + else { + text = myElement.getText(); + } + replace("string-length(" + text + ") > 0"); + return; } - replace(myType.getName() + "(" + myElement.getText() + ")"); + else if (myElement.getType() == XPathType.NODESET) { + replace("count(" + myElement.getText() + ") > 0"); + return; + } + } + replace(myType.getName() + "(" + myElement.getText() + ")"); } } diff --git a/plugins/xpath/xpath-lang/src/org/intellij/lang/xpath/validation/inspections/quickfix/RemoveExplicitConversionFix.java b/plugins/xpath/xpath-lang/src/org/intellij/lang/xpath/validation/inspections/quickfix/RemoveExplicitConversionFix.java index 7d98ad084c78..beaccc72605f 100644 --- a/plugins/xpath/xpath-lang/src/org/intellij/lang/xpath/validation/inspections/quickfix/RemoveExplicitConversionFix.java +++ b/plugins/xpath/xpath-lang/src/org/intellij/lang/xpath/validation/inspections/quickfix/RemoveExplicitConversionFix.java @@ -15,16 +15,15 @@ */ package org.intellij.lang.xpath.validation.inspections.quickfix; -import org.intellij.lang.xpath.psi.XPathExpression; -import org.intellij.lang.xpath.psi.XPathFunctionCall; -import org.intellij.lang.xpath.psi.XPathBinaryExpression; -import org.intellij.lang.xpath.validation.ExpectedTypeUtil; - import com.intellij.openapi.project.Project; -import com.intellij.openapi.editor.Editor; +import com.intellij.psi.PsiElement; import com.intellij.psi.PsiFile; import com.intellij.psi.util.PsiTreeUtil; import com.intellij.util.IncorrectOperationException; +import org.intellij.lang.xpath.psi.XPathBinaryExpression; +import org.intellij.lang.xpath.psi.XPathExpression; +import org.intellij.lang.xpath.psi.XPathFunctionCall; +import org.intellij.lang.xpath.validation.ExpectedTypeUtil; import org.jetbrains.annotations.NotNull; public class RemoveExplicitConversionFix extends ReplaceElementFix { @@ -43,13 +42,18 @@ public class RemoveExplicitConversionFix extends ReplaceElementFix extends XPath } protected void replace(String expressionText) throws IncorrectOperationException { - myElement.replace(XPathChangeUtil.createExpression(myElement, expressionText)); + PsiElement myElement = getStartElement(); + myElement.replace(XPathChangeUtil.createExpression(myElement, expressionText)); } } diff --git a/plugins/xpath/xpath-lang/src/org/intellij/lang/xpath/validation/inspections/quickfix/XPathQuickFixFactory.java b/plugins/xpath/xpath-lang/src/org/intellij/lang/xpath/validation/inspections/quickfix/XPathQuickFixFactory.java index 40d7651c8464..e477d503a71a 100644 --- a/plugins/xpath/xpath-lang/src/org/intellij/lang/xpath/validation/inspections/quickfix/XPathQuickFixFactory.java +++ b/plugins/xpath/xpath-lang/src/org/intellij/lang/xpath/validation/inspections/quickfix/XPathQuickFixFactory.java @@ -23,22 +23,18 @@ package org.intellij.lang.xpath.validation.inspections.quickfix; import com.intellij.codeInsight.CodeInsightUtilBase; -import com.intellij.codeInsight.intention.IntentionAction; -import com.intellij.codeInspection.LocalQuickFix; -import com.intellij.codeInspection.ProblemDescriptor; +import com.intellij.codeInspection.LocalQuickFixAndIntentionActionOnPsiElement; import com.intellij.codeInspection.SuppressIntentionAction; import com.intellij.openapi.diagnostic.Logger; -import com.intellij.openapi.editor.Editor; import com.intellij.openapi.project.Project; import com.intellij.psi.PsiElement; import com.intellij.psi.PsiFile; import com.intellij.util.IncorrectOperationException; -import org.jetbrains.annotations.NotNull; - import org.intellij.lang.xpath.psi.XPathExpression; import org.intellij.lang.xpath.psi.XPathNodeTest; import org.intellij.lang.xpath.psi.XPathType; import org.intellij.lang.xpath.validation.inspections.XPathInspection; +import org.jetbrains.annotations.NotNull; public interface XPathQuickFixFactory { Fix[] createImplicitTypeConversionFixes(XPathExpression expression, XPathType type, boolean explicit); @@ -51,23 +47,21 @@ public interface XPathQuickFixFactory { boolean isSuppressedFor(PsiElement element, XPathInspection inspection); - abstract class Fix implements LocalQuickFix, IntentionAction { - protected final E myElement; - + abstract class Fix extends LocalQuickFixAndIntentionActionOnPsiElement { protected Fix(E element) { - myElement = element; + super(element); } public boolean startInWriteAction() { return true; } - public boolean isAvailable(@NotNull Project project, Editor editor, PsiFile file) { - return isAvailableImpl(); - } - - protected boolean isAvailableImpl() { - return myElement.isValid() && myElement.getParent().isValid(); + @Override + public boolean isAvailable(@NotNull Project project, + @NotNull PsiFile file, + @NotNull PsiElement startElement, + @NotNull PsiElement endElement) { + return startElement.isValid() && startElement.getParent().isValid(); } @NotNull @@ -75,23 +69,22 @@ public interface XPathQuickFixFactory { return getName(); } - public final void applyFix(@NotNull Project project, @NotNull ProblemDescriptor descriptor) { - assert myElement == descriptor.getPsiElement(); - if (!isAvailableImpl()) return; + @Override + public void invoke(@NotNull Project project, + @NotNull PsiFile file, + @NotNull PsiElement startElement, + @NotNull PsiElement endElement) { + if(!CodeInsightUtilBase.prepareFileForWrite(file)) { + return; + } try { - invokeImpl(project, descriptor.getPsiElement().getContainingFile()); + invokeImpl(project, file); } catch (IncorrectOperationException e) { Logger.getInstance(getClass().getName()).error(e); } } - public final void invoke(@NotNull Project project, Editor editor, PsiFile file) throws IncorrectOperationException { - if(!CodeInsightUtilBase.prepareFileForWrite(file)) { - return; - } - invokeImpl(project, file); - } protected abstract void invokeImpl(Project project, PsiFile file) throws IncorrectOperationException; } From b2c56292fb7ca1e26c3546f872faec4e2246cbab Mon Sep 17 00:00:00 2001 From: Alexey Kudravtsev Date: Wed, 6 Apr 2011 11:55:36 +0400 Subject: [PATCH 31/65] optimization: lockfree --- .../src/com/intellij/openapi/util/FieldCache.java | 6 +++--- .../com/intellij/openapi/util/UserDataCache.java | 15 +++++++++++++++ 2 files changed, 18 insertions(+), 3 deletions(-) diff --git a/platform/util/src/com/intellij/openapi/util/FieldCache.java b/platform/util/src/com/intellij/openapi/util/FieldCache.java index 1c4e86815b6c..23e70510eadc 100644 --- a/platform/util/src/com/intellij/openapi/util/FieldCache.java +++ b/platform/util/src/com/intellij/openapi/util/FieldCache.java @@ -30,7 +30,7 @@ public abstract class FieldCache { w = ourLock.writeLock(); } - public final T get(AccessorParameter a, Owner owner, Parameter p) { + public T get(AccessorParameter a, Owner owner, Parameter p) { r.lock(); T result; try { @@ -68,7 +68,7 @@ public abstract class FieldCache { } } - public final void clear(AccessorParameter a, Owner owner) { + public void clear(AccessorParameter a, Owner owner) { w.lock(); try { putValue(null, owner, a); @@ -81,4 +81,4 @@ public abstract class FieldCache { protected abstract T compute(Owner owner, Parameter p); protected abstract T getValue(Owner owner, AccessorParameter p); protected abstract void putValue(T t, Owner owner, AccessorParameter p); -} \ No newline at end of file +} diff --git a/platform/util/src/com/intellij/openapi/util/UserDataCache.java b/platform/util/src/com/intellij/openapi/util/UserDataCache.java index 3264461148af..c4da2c94525f 100644 --- a/platform/util/src/com/intellij/openapi/util/UserDataCache.java +++ b/platform/util/src/com/intellij/openapi/util/UserDataCache.java @@ -44,4 +44,19 @@ public abstract class UserDataCache exte protected final void putValue(final T t, final Owner owner, final Key key) { owner.putUserData(key, t); } + + @Override + public T get(Key a, Owner owner, Param p) { + T value = owner.getUserData(a); + if (value == null) { + value = compute(owner, p); + value = ((UserDataHolderEx)owner).putUserDataIfAbsent(a, value); + } + return value; + } + + @Override + public void clear(Key key, Owner owner) { + owner.putUserData(key, null); + } } From d9a3b96bbcb6bcfe839a99d2d32c81ae55e62a5b Mon Sep 17 00:00:00 2001 From: Kirill Kalishev Date: Wed, 6 Apr 2011 12:10:59 +0400 Subject: [PATCH 32/65] Check for updates menu action for mac --- .../ide/MacOSApplicationProvider.java | 53 +++++++++++++++++++ 1 file changed, 53 insertions(+) diff --git a/platform/platform-impl/src/com/intellij/ide/MacOSApplicationProvider.java b/platform/platform-impl/src/com/intellij/ide/MacOSApplicationProvider.java index 99fce836ee07..85ff981f7651 100644 --- a/platform/platform-impl/src/com/intellij/ide/MacOSApplicationProvider.java +++ b/platform/platform-impl/src/com/intellij/ide/MacOSApplicationProvider.java @@ -22,6 +22,8 @@ import com.intellij.ide.actions.AboutAction; import com.intellij.ide.actions.OpenFileAction; import com.intellij.ide.impl.ProjectUtil; import com.intellij.openapi.actionSystem.PlatformDataKeys; +import com.intellij.openapi.actionSystem.ex.ActionManagerEx; +import com.intellij.openapi.actionSystem.impl.ActionManagerImpl; import com.intellij.openapi.application.ex.ApplicationManagerEx; import com.intellij.openapi.components.ApplicationComponent; import com.intellij.openapi.options.ConfigurableGroup; @@ -31,14 +33,37 @@ import com.intellij.openapi.options.ex.ProjectConfigurablesGroup; import com.intellij.openapi.project.Project; import com.intellij.openapi.project.ProjectManager; import com.intellij.openapi.util.SystemInfo; +import com.intellij.ui.mac.foundation.Foundation; +import com.intellij.ui.mac.foundation.ID; +import com.sun.java.swing.action.ActionManager; +import com.sun.jna.Callback; +import com.sun.jna.Pointer; import org.jetbrains.annotations.NotNull; +import javax.swing.*; +import java.awt.event.InputEvent; +import java.awt.event.MouseEvent; import java.io.File; /** * @author max */ public class MacOSApplicationProvider implements ApplicationComponent { + + private static final Callback IMPL = new Callback() { + public void callback(ID self, String selector) { + SwingUtilities.invokeLater(new Runnable() { + @Override + public void run() { + ActionManagerEx am = ActionManagerEx.getInstanceEx(); + MouseEvent me = + new MouseEvent(JOptionPane.getRootFrame(), MouseEvent.MOUSE_CLICKED, System.currentTimeMillis(), 0, 0, 0, 1, false); + am.tryToExecute(am.getAction("CheckForUpdate"), me, null, null, false); + } + }); + } + }; + @NotNull public String getComponentName() { return "MACOSApplicationProvider"; @@ -108,6 +133,34 @@ public class MacOSApplicationProvider implements ApplicationComponent { application.addPreferencesMenuItem(); application.setEnabledAboutMenu(true); application.setEnabledPreferencesMenu(true); + + + installAutoUpdateMenu(); + } + + private static void installAutoUpdateMenu() { + ID pool = Foundation.invoke("NSAutoreleasePool", "new"); + + ID app = Foundation.invoke("NSApplication", "sharedApplication"); + ID menu = Foundation.invoke(app, Foundation.createSelector("menu")); + ID item = Foundation.invoke(menu, Foundation.createSelector("itemAtIndex:"), 0); + ID appMenu = Foundation.invoke(item, Foundation.createSelector("submenu")); + + + final ID checkForUpdatesClass = Foundation.registerObjcClass(Foundation.getClass("NSMenuItem"), "NSCheckForUpdates"); + Foundation.addMethod(checkForUpdatesClass, Foundation.createSelector("checkForUpdates"), IMPL, "v"); + + Foundation.registerObjcClassPair(checkForUpdatesClass); + + ID checkForUpdates = Foundation.invoke("NSCheckForUpdates", "alloc"); + Foundation.invoke(checkForUpdates, Foundation.createSelector("initWithTitle:action:keyEquivalent:"), Foundation.cfString("Check for Updates..."), + Foundation.createSelector("checkForUpdates"), Foundation.cfString("")); + Foundation.invoke(checkForUpdates, Foundation.createSelector("setTarget:"), checkForUpdates); + + Foundation.invoke(appMenu, Foundation.createSelector("insertItem:atIndex:"), checkForUpdates, 1); + Foundation.invoke(checkForUpdates, Foundation.createSelector("release")); + + Foundation.invoke(pool, Foundation.createSelector("release")); } private static Project getProject() { From cecdce204c4baab725407b996923095afb95b5a8 Mon Sep 17 00:00:00 2001 From: Kirill Kalishev Date: Wed, 6 Apr 2011 12:59:10 +0400 Subject: [PATCH 33/65] Revert "Need 'check for updates' action on macs back." This reverts commit 6633bb49d2f93e36f2a61d6ce5cfd473d7f98a21. --- .../openapi/updateSettings/impl/CheckForUpdateAction.java | 5 +++++ 1 file changed, 5 insertions(+) diff --git a/platform/platform-impl/src/com/intellij/openapi/updateSettings/impl/CheckForUpdateAction.java b/platform/platform-impl/src/com/intellij/openapi/updateSettings/impl/CheckForUpdateAction.java index 2b3618927f41..c78d54abe30f 100644 --- a/platform/platform-impl/src/com/intellij/openapi/updateSettings/impl/CheckForUpdateAction.java +++ b/platform/platform-impl/src/com/intellij/openapi/updateSettings/impl/CheckForUpdateAction.java @@ -31,6 +31,11 @@ import org.jetbrains.annotations.Nullable; import java.util.List; public class CheckForUpdateAction extends AnAction implements DumbAware { + + public void update(AnActionEvent e) { + e.getPresentation().setVisible(!SystemInfo.isMacSystemMenu); + } + public void actionPerformed(AnActionEvent e) { Project project = e.getData(PlatformDataKeys.PROJECT); actionPerformed(project, true, null); From 528abcfe564e03645bfcb5e8faedfa171416d32b Mon Sep 17 00:00:00 2001 From: Dmitry Avdeev Date: Wed, 6 Apr 2011 13:16:53 +0400 Subject: [PATCH 34/65] test fixed --- .../intellij/codeInsight/navigation/CtrlMouseHandler.java | 6 ++++++ 1 file changed, 6 insertions(+) diff --git a/platform/lang-impl/src/com/intellij/codeInsight/navigation/CtrlMouseHandler.java b/platform/lang-impl/src/com/intellij/codeInsight/navigation/CtrlMouseHandler.java index fe72849f38f1..1e4dab6bf7e3 100644 --- a/platform/lang-impl/src/com/intellij/codeInsight/navigation/CtrlMouseHandler.java +++ b/platform/lang-impl/src/com/intellij/codeInsight/navigation/CtrlMouseHandler.java @@ -72,6 +72,7 @@ import com.intellij.usageView.UsageViewTypeLocation; import com.intellij.util.Processor; import org.jetbrains.annotations.NotNull; import org.jetbrains.annotations.Nullable; +import org.jetbrains.annotations.TestOnly; import javax.swing.*; import java.awt.*; @@ -228,6 +229,11 @@ public class CtrlMouseHandler extends AbstractProjectComponent { return false; } + @TestOnly + public static String getInfo(PsiElement element, PsiElement atPointer) { + return generateInfo(element, atPointer); + } + @Nullable private static String generateInfo(PsiElement element, PsiElement atPointer) { final DocumentationProvider documentationProvider = DocumentationManager.getProviderFromElement(element, atPointer); From 30cad00559b122905e06d753adf74b5e4a6e8b8d Mon Sep 17 00:00:00 2001 From: Kirill Kalishev Date: Wed, 6 Apr 2011 13:21:02 +0400 Subject: [PATCH 35/65] compilation fix --- .../src/com/intellij/ide/MacOSApplicationProvider.java | 4 ---- 1 file changed, 4 deletions(-) diff --git a/platform/platform-impl/src/com/intellij/ide/MacOSApplicationProvider.java b/platform/platform-impl/src/com/intellij/ide/MacOSApplicationProvider.java index 85ff981f7651..0c62421c0bda 100644 --- a/platform/platform-impl/src/com/intellij/ide/MacOSApplicationProvider.java +++ b/platform/platform-impl/src/com/intellij/ide/MacOSApplicationProvider.java @@ -23,7 +23,6 @@ import com.intellij.ide.actions.OpenFileAction; import com.intellij.ide.impl.ProjectUtil; import com.intellij.openapi.actionSystem.PlatformDataKeys; import com.intellij.openapi.actionSystem.ex.ActionManagerEx; -import com.intellij.openapi.actionSystem.impl.ActionManagerImpl; import com.intellij.openapi.application.ex.ApplicationManagerEx; import com.intellij.openapi.components.ApplicationComponent; import com.intellij.openapi.options.ConfigurableGroup; @@ -35,13 +34,10 @@ import com.intellij.openapi.project.ProjectManager; import com.intellij.openapi.util.SystemInfo; import com.intellij.ui.mac.foundation.Foundation; import com.intellij.ui.mac.foundation.ID; -import com.sun.java.swing.action.ActionManager; import com.sun.jna.Callback; -import com.sun.jna.Pointer; import org.jetbrains.annotations.NotNull; import javax.swing.*; -import java.awt.event.InputEvent; import java.awt.event.MouseEvent; import java.io.File; From cb215cb63982b7ded3ec524def53f2f6e58be021 Mon Sep 17 00:00:00 2001 From: Bas Leijdekkers Date: Wed, 6 Apr 2011 12:05:50 +0200 Subject: [PATCH 36/65] cleanup --- .../com/siyeh/ig/bugs/NumberEqualityInspection.java | 12 +++--------- 1 file changed, 3 insertions(+), 9 deletions(-) diff --git a/plugins/InspectionGadgets/src/com/siyeh/ig/bugs/NumberEqualityInspection.java b/plugins/InspectionGadgets/src/com/siyeh/ig/bugs/NumberEqualityInspection.java index 9ef8c6cf0fd0..180e82650c7a 100644 --- a/plugins/InspectionGadgets/src/com/siyeh/ig/bugs/NumberEqualityInspection.java +++ b/plugins/InspectionGadgets/src/com/siyeh/ig/bugs/NumberEqualityInspection.java @@ -61,27 +61,21 @@ public class NumberEqualityInspection extends BaseInspection { @Override public void visitBinaryExpression( @NotNull PsiBinaryExpression expression) { super.visitBinaryExpression(expression); - if(!(expression.getROperand() != null)){ + final PsiExpression rhs = expression.getROperand(); + if (rhs == null) { return; } if (!ComparisonUtils.isEqualityComparison(expression)) { return; } final PsiExpression lhs = expression.getLOperand(); - if (!hasNumberType(lhs)) { - return; - } - final PsiExpression rhs = expression.getROperand(); - if (!hasNumberType(rhs)) { + if (!hasNumberType(lhs) || !hasNumberType(rhs)) { return; } final String lhsText = lhs.getText(); if (PsiKeyword.NULL.equals(lhsText)) { return; } - if (rhs == null) { - return; - } final String rhsText = rhs.getText(); if (PsiKeyword.NULL.equals(rhsText)) { return; From d26ca9f4e7561da4b9eb3a0d935b2f023aee5e17 Mon Sep 17 00:00:00 2001 From: Bas Leijdekkers Date: Wed, 6 Apr 2011 12:07:08 +0200 Subject: [PATCH 37/65] better quickfixes Use Arrays.deepEquals() on arrays with more than one dimension --- .../siyeh/InspectionGadgetsBundle.properties | 10 +-- .../ig/bugs/ArrayEqualityInspection.java | 43 ++++++++---- .../siyeh/ig/bugs/ArrayEqualsInspection.java | 69 ++++++++++++++----- 3 files changed, 86 insertions(+), 36 deletions(-) diff --git a/plugins/InspectionGadgets/src/com/siyeh/InspectionGadgetsBundle.properties b/plugins/InspectionGadgets/src/com/siyeh/InspectionGadgetsBundle.properties index b958c1a993ee..690b6719133d 100644 --- a/plugins/InspectionGadgets/src/com/siyeh/InspectionGadgetsBundle.properties +++ b/plugins/InspectionGadgets/src/com/siyeh/InspectionGadgetsBundle.properties @@ -55,7 +55,8 @@ archaic.system.property.accessors.replace.parse.quickfix=Replace with parse meth archaic.system.property.accessors.replace.standard.quickfix=Replace with standard property access equals.called.on.array.display.name='equals()' called on array type equals.called.on.array.problem.descriptor=#ref() between arrays should probably be 'Arrays.equals()' #loc -equals.called.on.array.replace.quickfix=Replace with 'Arrays.equals()' +replace.with.arrays.equals=Replace with 'Arrays.equals()' +replace.with.arrays.deep.equals=Replace with 'Arrays.deepEquals()' assignment.to.null.display.name=Assignment to 'null' assignment.to.null.problem.descriptor=Assignment of variable #ref to null #loc assignment.to.static.field.from.instance.method.display.name=Assignment to static field from instance method @@ -887,7 +888,7 @@ nested.switch.statement.problem.descriptor=Nested #ref statement #l chained.method.call.problem.descriptor=Chained method call #ref() #loc nested.method.call.problem.descriptor=Nested method call #ref() #loc octal.literal.problem.descriptor=Octal integer #ref #loc -implicit.call.to.super.problem.descriptor=Implicit call to super() #ref #loc +implicit.call.to.super.problem.descriptor=Implicit call to 'super()' #loc negated.if.else.problem.descriptor=#ref statement with negated condition #loc negated.conditional.problem.descriptor=Conditional expression with negated condition #loc confusing.else.problem.descriptor=#ref branch may be unwrapped, as the 'if' branch never completes #loc @@ -1346,7 +1347,7 @@ flip.comparison.quickfix=Flip comparison control.flow.statement.without.braces.add.quickfix=Add braces extends.object.remove.quickfix=Remove redundant 'extends Object' implicit.call.to.super.ignore.option=Ignore for direct subclasses of java.lang.Object -implicit.call.to.super.make.explicit.quickfix=Make construction of super() explicit +implicit.call.to.super.make.explicit.quickfix=Make call to 'super()' explicit missorted.modifiers.require.option=Require annotations to be sorted before keywords missorted.modifiers.sort.quickfix=Sort modifiers nested.method.call.ignore.option=Ignore nested method calls in field initializers @@ -1598,7 +1599,7 @@ collection.contains.url.problem.decriptor={0} #ref may contain URL collection.contains.url.display.name=Map or Set may contain java.net.URL objects implicit.array.to.string.problem.descriptor=Implicit call to method 'toString()' on array #ref #loc implicit.array.to.string.method.call.problem.descriptor=Implicit call to method 'toString()' on array returned by #ref call #loc -implicit.array.to.string.display.name=Implicit call to array '.toString()' +implicit.array.to.string.display.name=Call to array '.toString()' implicit.array.to.string.quickfix=Wrap with ''{0}'' expression suspicious.indent.after.control.statement.problem.descriptor=#ref statement has suspicious indentation #loc suspicious.indent.after.control.statement.display.name=Suspicious indentation after control statement without braces @@ -1869,4 +1870,3 @@ try.finally.can.be.try.with.resources.problem.descriptor=#ref can u try.finally.can.be.try.with.resources.quickfix=Replace with 'try' with resources array.comparison.display.name=Array comparison using '==', instead of 'Arrays.equals()' array.comparison.problem.descriptor=Array objects are compared using #ref, not 'Arrays.equals()' #loc -array.comparison.quickfix=Replace with 'Arrays.equals()' diff --git a/plugins/InspectionGadgets/src/com/siyeh/ig/bugs/ArrayEqualityInspection.java b/plugins/InspectionGadgets/src/com/siyeh/ig/bugs/ArrayEqualityInspection.java index 7e13f97ba92b..6790e89fc667 100644 --- a/plugins/InspectionGadgets/src/com/siyeh/ig/bugs/ArrayEqualityInspection.java +++ b/plugins/InspectionGadgets/src/com/siyeh/ig/bugs/ArrayEqualityInspection.java @@ -1,5 +1,5 @@ /* - * Copyright 2003-2011 Dave Griffith, Bas Leijdekkers + * Copyright 2011 Dave Griffith, Bas Leijdekkers * * Licensed under the Apache License, Version 2.0 (the "License"); * you may not use this file except in compliance with the License. @@ -46,15 +46,32 @@ public class ArrayEqualityInspection extends BaseInspection { @Override public InspectionGadgetsFix buildFix(Object... infos) { - return new ArrayEqualityFix(); + final PsiArrayType type = (PsiArrayType) infos[0]; + final PsiType componentType = type.getComponentType(); + if (componentType instanceof PsiArrayType) { + return new ArrayEqualityFix(true); + } + return new ArrayEqualityFix(false); } private static class ArrayEqualityFix extends InspectionGadgetsFix { - + + private final boolean deepEquals; + + public ArrayEqualityFix(boolean deepEquals) { + this.deepEquals = deepEquals; + } + @NotNull @Override public String getName() { - return InspectionGadgetsBundle.message("array.comparison.quickfix"); + if (deepEquals) { + return InspectionGadgetsBundle.message( + "replace.with.arrays.deep.equals"); + } else { + return InspectionGadgetsBundle.message( + "replace.with.arrays.equals"); + } } @Override @@ -75,7 +92,11 @@ public class ArrayEqualityInspection extends BaseInspection { } else if (!JavaTokenType.EQEQ.equals(tokenType)) { return; } - newExpressionText.append("java.util.Arrays.equals("); + if (deepEquals) { + newExpressionText.append("java.util.Arrays.deepEquals("); + } else { + newExpressionText.append("java.util.Arrays.equals("); + } newExpressionText.append(binaryExpression.getLOperand().getText()); newExpressionText.append(','); final PsiExpression rhs = binaryExpression.getROperand(); @@ -99,18 +120,16 @@ public class ArrayEqualityInspection extends BaseInspection { @Override public void visitBinaryExpression( @NotNull PsiBinaryExpression expression) { super.visitBinaryExpression(expression); - if(!(expression.getROperand() != null)){ + final PsiExpression rhs = expression.getROperand(); + if (rhs == null) { return; } if (!ComparisonUtils.isEqualityComparison(expression)) { return; } final PsiExpression lhs = expression.getLOperand(); - if (!(lhs.getType() instanceof PsiArrayType)) { - return; - } - final PsiExpression rhs = expression.getROperand(); - if (rhs == null) { + final PsiType lhsType = lhs.getType(); + if (!(lhsType instanceof PsiArrayType)) { return; } if (!(rhs.getType() instanceof PsiArrayType)) { @@ -125,7 +144,7 @@ public class ArrayEqualityInspection extends BaseInspection { return; } final PsiJavaToken sign = expression.getOperationSign(); - registerError(sign); + registerError(sign, lhsType); } } } \ No newline at end of file diff --git a/plugins/InspectionGadgets/src/com/siyeh/ig/bugs/ArrayEqualsInspection.java b/plugins/InspectionGadgets/src/com/siyeh/ig/bugs/ArrayEqualsInspection.java index 1dd14f3c2e4c..fad4e57a6d69 100644 --- a/plugins/InspectionGadgets/src/com/siyeh/ig/bugs/ArrayEqualsInspection.java +++ b/plugins/InspectionGadgets/src/com/siyeh/ig/bugs/ArrayEqualsInspection.java @@ -1,5 +1,5 @@ /* - * Copyright 2003-2008 Dave Griffith, Bas Leijdekkers + * Copyright 2003-2011 Dave Griffith, Bas Leijdekkers * * Licensed under the Apache License, Version 2.0 (the "License"); * you may not use this file except in compliance with the License. @@ -29,34 +29,57 @@ import org.jetbrains.annotations.NotNull; public class ArrayEqualsInspection extends BaseInspection { + @Override @NotNull public String getDisplayName(){ return InspectionGadgetsBundle.message( "equals.called.on.array.display.name"); } + @Override @NotNull public String buildErrorString(Object... infos){ return InspectionGadgetsBundle.message( "equals.called.on.array.problem.descriptor"); } + @Override public boolean isEnabledByDefault() { return true; } + @Override public InspectionGadgetsFix buildFix(Object... infos){ - return new ArrayEqualsFix(); + final PsiArrayType type = (PsiArrayType)infos[0]; + if (type != null) { + final PsiType componentType = type.getComponentType(); + if (componentType instanceof PsiArrayType) { + return new ArrayEqualsFix(true); + } + } + return new ArrayEqualsFix(false); } private static class ArrayEqualsFix extends InspectionGadgetsFix{ - @NotNull - public String getName(){ - return InspectionGadgetsBundle.message( - "equals.called.on.array.replace.quickfix"); + private final boolean deepEquals; + + public ArrayEqualsFix(boolean deepEquals) { + this.deepEquals = deepEquals; } + @NotNull + public String getName(){ + if (deepEquals) { + return InspectionGadgetsBundle.message( + "replace.with.arrays.deep.equals"); + } else { + return InspectionGadgetsBundle.message( + "replace.with.arrays.equals"); + } + } + + @Override public void doFix(Project project, ProblemDescriptor descriptor) throws IncorrectOperationException{ final PsiIdentifier name = @@ -71,15 +94,23 @@ public class ArrayEqualsInspection extends BaseInspection { final String qualifierText = qualifier.getText(); assert call != null; final PsiExpressionList argumentList = call.getArgumentList(); - final PsiExpression[] args = argumentList.getExpressions(); - final String argText = args[0].getText(); - @NonNls final String newExpressionText = - "java.util.Arrays.equals(" + qualifierText + ", " + - argText + ')'; - replaceExpressionAndShorten(call, newExpressionText); + final PsiExpression[] arguments = argumentList.getExpressions(); + final String argumentText = arguments[0].getText(); + @NonNls final StringBuilder newExpressionText = new StringBuilder(); + if (deepEquals) { + newExpressionText.append("java.util.Arrays.deepEquals("); + } else { + newExpressionText.append("java.util.Arrays.equals("); + } + newExpressionText.append(qualifierText); + newExpressionText.append(", "); + newExpressionText.append(argumentText); + newExpressionText.append(')'); + replaceExpressionAndShorten(call, newExpressionText.toString()); } } + @Override public BaseInspectionVisitor buildVisitor(){ return new ArrayEqualsVisitor(); } @@ -95,16 +126,16 @@ public class ArrayEqualsInspection extends BaseInspection { final PsiReferenceExpression methodExpression = expression.getMethodExpression(); final PsiExpressionList argumentList = expression.getArgumentList(); - final PsiExpression[] args = argumentList.getExpressions(); - if (args.length == 0) { + final PsiExpression[] arguments = argumentList.getExpressions(); + if (arguments.length == 0) { return; } - final PsiExpression arg = args[0]; - if(arg == null){ + final PsiExpression argument = arguments[0]; + if(argument == null){ return; } - final PsiType argType = arg.getType(); - if(!(argType instanceof PsiArrayType)){ + final PsiType argumentType = argument.getType(); + if(!(argumentType instanceof PsiArrayType)){ return; } final PsiExpression qualifier = @@ -116,7 +147,7 @@ public class ArrayEqualsInspection extends BaseInspection { if(!(qualifierType instanceof PsiArrayType)){ return; } - registerMethodCallError(expression); + registerMethodCallError(expression, qualifierType); } } } \ No newline at end of file From 697b974fc6369e4dff9a183f892c72621fd8e26a Mon Sep 17 00:00:00 2001 From: irengrig Date: Wed, 6 Apr 2011 14:22:20 +0400 Subject: [PATCH 38/65] VCS: check TODO before commit: when inspection is canceled, don't commit -> cancel commit --- .../com/intellij/openapi/vcs/checkin/TodoCheckinHandler.java | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/platform/lang-impl/src/com/intellij/openapi/vcs/checkin/TodoCheckinHandler.java b/platform/lang-impl/src/com/intellij/openapi/vcs/checkin/TodoCheckinHandler.java index 073c90ac0794..6ee90b6401f3 100644 --- a/platform/lang-impl/src/com/intellij/openapi/vcs/checkin/TodoCheckinHandler.java +++ b/platform/lang-impl/src/com/intellij/openapi/vcs/checkin/TodoCheckinHandler.java @@ -149,9 +149,9 @@ public class TodoCheckinHandler extends CheckinHandler { } }; final boolean completed = ProgressManager.getInstance().runProcessWithProgressSynchronously(runnable, "Looking for new and edited TODO items...", true, myProject); - if (! completed || (worker.getAddedOrEditedTodos().isEmpty() && worker.getInChangedTodos().isEmpty() && + if (completed && (worker.getAddedOrEditedTodos().isEmpty() && worker.getInChangedTodos().isEmpty() && worker.getSkipped().isEmpty())) return ReturnResult.COMMIT; - + if (! completed) return ReturnResult.CANCEL; return showResults(worker, executor); } From 6a12b9c4de4af9df2666791a033fba71853352c3 Mon Sep 17 00:00:00 2001 From: peter Date: Mon, 4 Apr 2011 15:05:25 +0200 Subject: [PATCH 39/65] IDEA-67445 no smart completion for "new Ex" --- .../codeInsight/completion/JavaSmartCompletionContributor.java | 2 +- .../codeInsight/completion/smartType/afterNew/after15.java | 2 +- 2 files changed, 2 insertions(+), 2 deletions(-) diff --git a/java/java-impl/src/com/intellij/codeInsight/completion/JavaSmartCompletionContributor.java b/java/java-impl/src/com/intellij/codeInsight/completion/JavaSmartCompletionContributor.java index 1866660fc41d..2379251a7fdd 100644 --- a/java/java-impl/src/com/intellij/codeInsight/completion/JavaSmartCompletionContributor.java +++ b/java/java-impl/src/com/intellij/codeInsight/completion/JavaSmartCompletionContributor.java @@ -81,7 +81,7 @@ public class JavaSmartCompletionContributor extends CompletionContributor { static final ElementPattern AFTER_THROW_NEW = psiElement().afterLeaf(psiElement().withText(PsiKeyword.NEW).afterLeaf(PsiKeyword.THROW)); private static final OrFilter THROWABLE_TYPE_FILTER = new OrFilter( new GeneratorFilter(AssignableGroupFilter.class, new ThrowsListGetter()), - new AssignableFromFilter(CommonClassNames.JAVA_LANG_RUNTIME_EXCEPTION)); + new AssignableFromFilter(CommonClassNames.JAVA_LANG_THROWABLE)); public static final ElementPattern INSIDE_EXPRESSION = or( psiElement().withParent(PsiExpression.class).andNot(psiElement().withParent(PsiLiteralExpression.class)), psiElement().inside(PsiClassObjectAccessExpression.class), diff --git a/java/java-tests/testData/codeInsight/completion/smartType/afterNew/after15.java b/java/java-tests/testData/codeInsight/completion/smartType/afterNew/after15.java index cb778f9c2393..d0cf0a8bba2a 100644 --- a/java/java-tests/testData/codeInsight/completion/smartType/afterNew/after15.java +++ b/java/java-tests/testData/codeInsight/completion/smartType/afterNew/after15.java @@ -1,6 +1,6 @@ class A{ void foo() throws MyException{ - throw new Erro + throw new Error(); } class MyException extends Exception{} From 885ec01362af2ebb02518651ac71de13b4f5fb2d Mon Sep 17 00:00:00 2001 From: peter Date: Mon, 4 Apr 2011 17:25:24 +0200 Subject: [PATCH 40/65] don't let live templates prevent case-insensitive matching items don't accept live template variants by commas and other strange characters --- .../completion/JavaAutoPopupTest.groovy | 20 +++++++ .../RelaxedMatchingContributor.java | 3 +- .../template/impl/LiveTemplateCharFilter.java | 33 ++++++++++++ .../LiveTemplateCompletionContributor.java | 12 +---- .../impl/LiveTemplateLookupElement.java | 53 +++++++++++++++++++ .../src/META-INF/LangExtensions.xml | 1 + 6 files changed, 110 insertions(+), 12 deletions(-) create mode 100644 platform/lang-impl/src/com/intellij/codeInsight/template/impl/LiveTemplateCharFilter.java create mode 100644 platform/lang-impl/src/com/intellij/codeInsight/template/impl/LiveTemplateLookupElement.java diff --git a/java/java-tests/testSrc/com/intellij/codeInsight/completion/JavaAutoPopupTest.groovy b/java/java-tests/testSrc/com/intellij/codeInsight/completion/JavaAutoPopupTest.groovy index 49efa9ee6dca..0fb5bb923416 100644 --- a/java/java-tests/testSrc/com/intellij/codeInsight/completion/JavaAutoPopupTest.groovy +++ b/java/java-tests/testSrc/com/intellij/codeInsight/completion/JavaAutoPopupTest.groovy @@ -631,4 +631,24 @@ public interface Test { assert !lookup } + public void testTemplateSelection() { + myFixture.configureByText("a.java", """ +class Foo { + int ITER = 2; + int itea = 2; + + { + it + } +} +""") + type 'e' + assertOrderedEquals myFixture.lookupElementStrings, "itea" + type 'r' + assertOrderedEquals myFixture.lookupElementStrings, "iter", "ITER", "Iterable", "Iterator" + type ',' + assert !lookup + assert myFixture.editor.document.text.contains('iter,') + } + } diff --git a/platform/lang-impl/src/com/intellij/codeInsight/completion/RelaxedMatchingContributor.java b/platform/lang-impl/src/com/intellij/codeInsight/completion/RelaxedMatchingContributor.java index 94b00f7f950e..76b9ef68f4bf 100644 --- a/platform/lang-impl/src/com/intellij/codeInsight/completion/RelaxedMatchingContributor.java +++ b/platform/lang-impl/src/com/intellij/codeInsight/completion/RelaxedMatchingContributor.java @@ -16,6 +16,7 @@ package com.intellij.codeInsight.completion; import com.intellij.codeInsight.lookup.LookupElement; +import com.intellij.codeInsight.template.impl.LiveTemplateLookupElement; import com.intellij.patterns.PatternCondition; import com.intellij.patterns.StandardPatterns; import com.intellij.util.Consumer; @@ -63,7 +64,7 @@ public class RelaxedMatchingContributor extends CompletionContributor { } CompletionParameters relaxed; - if (elements.isEmpty() && parameters.getInvocationCount() == 0) { + if (parameters.getInvocationCount() == 0 && (elements.isEmpty() || elements.size() == 1 && elements.iterator().next() instanceof LiveTemplateLookupElement)) { relaxed = parameters.withRelaxedMatching(); } else if (parameters.getInvocationCount() >= 2) { diff --git a/platform/lang-impl/src/com/intellij/codeInsight/template/impl/LiveTemplateCharFilter.java b/platform/lang-impl/src/com/intellij/codeInsight/template/impl/LiveTemplateCharFilter.java new file mode 100644 index 000000000000..a34084de0e0f --- /dev/null +++ b/platform/lang-impl/src/com/intellij/codeInsight/template/impl/LiveTemplateCharFilter.java @@ -0,0 +1,33 @@ +/* + * Copyright 2000-2011 JetBrains s.r.o. + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ +package com.intellij.codeInsight.template.impl; + +import com.intellij.codeInsight.lookup.CharFilter; +import com.intellij.codeInsight.lookup.Lookup; + +/** + * @author peter + */ +public class LiveTemplateCharFilter extends CharFilter { + @Override + public Result acceptChar(char c, int prefixLength, Lookup lookup) { + if (lookup.getCurrentItem() instanceof LiveTemplateLookupElement && c != ' ') { + return Result.HIDE_LOOKUP; + } + + return null; + } +} diff --git a/platform/lang-impl/src/com/intellij/codeInsight/template/impl/LiveTemplateCompletionContributor.java b/platform/lang-impl/src/com/intellij/codeInsight/template/impl/LiveTemplateCompletionContributor.java index bb3b5915a753..70d741d5351f 100644 --- a/platform/lang-impl/src/com/intellij/codeInsight/template/impl/LiveTemplateCompletionContributor.java +++ b/platform/lang-impl/src/com/intellij/codeInsight/template/impl/LiveTemplateCompletionContributor.java @@ -16,9 +16,6 @@ package com.intellij.codeInsight.template.impl; import com.intellij.codeInsight.completion.*; -import com.intellij.codeInsight.lookup.LookupElement; -import com.intellij.codeInsight.lookup.LookupElementBuilder; -import com.intellij.codeInsight.template.TemplateManager; import com.intellij.openapi.util.Condition; import com.intellij.patterns.PlatformPatterns; import com.intellij.psi.PsiFile; @@ -48,14 +45,7 @@ public class LiveTemplateCompletionContributor extends CompletionContributor { final String prefix = result.getPrefixMatcher().getPrefix(); final TemplateImpl template = findApplicableTemplate(file, offset, prefix); if (template != null) { - result.addElement(LookupElementBuilder.create(prefix).setTypeText(template.getDescription()).setInsertHandler(new InsertHandler() { - @Override - public void handleInsert(InsertionContext context, LookupElement item) { - context.getDocument().deleteString(context.getStartOffset(), context.getTailOffset()); - context.setAddCompletionChar(false); - TemplateManager.getInstance(context.getProject()).startTemplate(context.getEditor(), template); - } - })); + result.addElement(new LiveTemplateLookupElement(prefix, template)); } else { for (final TemplateImpl possible : listApplicableTemplates(file, offset)) { result.restartCompletionOnPrefixChange(possible.getKey()); diff --git a/platform/lang-impl/src/com/intellij/codeInsight/template/impl/LiveTemplateLookupElement.java b/platform/lang-impl/src/com/intellij/codeInsight/template/impl/LiveTemplateLookupElement.java new file mode 100644 index 000000000000..9257262c328c --- /dev/null +++ b/platform/lang-impl/src/com/intellij/codeInsight/template/impl/LiveTemplateLookupElement.java @@ -0,0 +1,53 @@ +/* + * Copyright 2000-2011 JetBrains s.r.o. + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ +package com.intellij.codeInsight.template.impl; + +import com.intellij.codeInsight.completion.InsertionContext; +import com.intellij.codeInsight.lookup.LookupElement; +import com.intellij.codeInsight.lookup.LookupElementPresentation; +import com.intellij.codeInsight.template.TemplateManager; +import org.jetbrains.annotations.NotNull; + +/** + * @author peter + */ +public class LiveTemplateLookupElement extends LookupElement { + private final String myPrefix; + private final TemplateImpl myTemplate; + + public LiveTemplateLookupElement(String prefix, TemplateImpl template) { + myPrefix = prefix; + myTemplate = template; + } + @NotNull + @Override + public String getLookupString() { + return myPrefix; + } + + @Override + public void renderElement(LookupElementPresentation presentation) { + super.renderElement(presentation); + presentation.setTypeText(myTemplate.getDescription()); + } + + @Override + public void handleInsert(InsertionContext context) { + context.getDocument().deleteString(context.getStartOffset(), context.getTailOffset()); + context.setAddCompletionChar(false); + TemplateManager.getInstance(context.getProject()).startTemplate(context.getEditor(), myTemplate); + } +} diff --git a/platform/platform-resources/src/META-INF/LangExtensions.xml b/platform/platform-resources/src/META-INF/LangExtensions.xml index a5fa52cf904c..a5c953e1988c 100644 --- a/platform/platform-resources/src/META-INF/LangExtensions.xml +++ b/platform/platform-resources/src/META-INF/LangExtensions.xml @@ -402,6 +402,7 @@ + From 8a43662c93edaa67f28bad84cf89de44d3878afe Mon Sep 17 00:00:00 2001 From: peter Date: Mon, 4 Apr 2011 17:33:58 +0200 Subject: [PATCH 41/65] restore substring match in file structure popup (IDEA-67486) --- .../src/com/intellij/ide/util/FileStructureDialog.java | 7 ++++++- 1 file changed, 6 insertions(+), 1 deletion(-) diff --git a/platform/lang-impl/src/com/intellij/ide/util/FileStructureDialog.java b/platform/lang-impl/src/com/intellij/ide/util/FileStructureDialog.java index b4da40061a95..68a98aefcc82 100644 --- a/platform/lang-impl/src/com/intellij/ide/util/FileStructureDialog.java +++ b/platform/lang-impl/src/com/intellij/ide/util/FileStructureDialog.java @@ -342,6 +342,7 @@ public class FileStructureDialog extends DialogWrapper { myList.repaint(); // to update match highlighting } }); + myListSpeedSearch.setComparator(createSpeedSearchComparator()); } private boolean hasPrefixShortened(final PropertyChangeEvent evt) { @@ -412,7 +413,7 @@ public class FileStructureDialog extends DialogWrapper { } ArrayList filteredElements = new ArrayList(childElements.length); - SpeedSearchBase.SpeedSearchComparator speedSearchComparator = new SpeedSearchBase.SpeedSearchComparator(); + SpeedSearchBase.SpeedSearchComparator speedSearchComparator = createSpeedSearchComparator(); for (Object child : childElements) { if (child instanceof AbstractTreeNode) { @@ -438,6 +439,10 @@ public class FileStructureDialog extends DialogWrapper { } } + private static SpeedSearchBase.SpeedSearchComparator createSpeedSearchComparator() { + return new SpeedSearchBase.SpeedSearchComparator(false); + } + private class MyTreeActionsOwner implements TreeActionsOwner { private final Set myFilters = new HashSet(); From 4c4254e496495b1ff4bb95d4c1353143b20bf471 Mon Sep 17 00:00:00 2001 From: peter Date: Mon, 4 Apr 2011 17:36:58 +0200 Subject: [PATCH 42/65] substring match in members chooser (IDEA-67486) --- .../lang-impl/src/com/intellij/ide/util/MemberChooser.java | 6 ++---- 1 file changed, 2 insertions(+), 4 deletions(-) diff --git a/platform/lang-impl/src/com/intellij/ide/util/MemberChooser.java b/platform/lang-impl/src/com/intellij/ide/util/MemberChooser.java index 3c0f494533c2..ff53a20c3d1e 100644 --- a/platform/lang-impl/src/com/intellij/ide/util/MemberChooser.java +++ b/platform/lang-impl/src/com/intellij/ide/util/MemberChooser.java @@ -29,10 +29,7 @@ import com.intellij.openapi.util.Ref; import com.intellij.openapi.util.SystemInfo; import com.intellij.psi.codeStyle.CodeStyleSettings; import com.intellij.psi.codeStyle.CodeStyleSettingsManager; -import com.intellij.ui.ColoredTreeCellRenderer; -import com.intellij.ui.NonFocusableCheckBox; -import com.intellij.ui.ScrollPaneFactory; -import com.intellij.ui.TreeSpeedSearch; +import com.intellij.ui.*; import com.intellij.ui.treeStructure.Tree; import com.intellij.util.Icons; import com.intellij.util.SmartList; @@ -306,6 +303,7 @@ public class MemberChooser extends DialogWrapper implemen return delegate.getText(); } }); + treeSpeedSearch.setComparator(new SpeedSearchBase.SpeedSearchComparator(false)); treeSpeedSearch.addChangeListener(new PropertyChangeListener() { @Override From a2d4cceb11c1e60e90c7cc204a5f25c90019064f Mon Sep 17 00:00:00 2001 From: peter Date: Mon, 4 Apr 2011 17:47:51 +0200 Subject: [PATCH 43/65] skip digits in matching --- platform/util/src/com/intellij/psi/codeStyle/NameUtil.java | 3 +++ 1 file changed, 3 insertions(+) diff --git a/platform/util/src/com/intellij/psi/codeStyle/NameUtil.java b/platform/util/src/com/intellij/psi/codeStyle/NameUtil.java index 1a128e1c9a5d..beb01bfb5d12 100644 --- a/platform/util/src/com/intellij/psi/codeStyle/NameUtil.java +++ b/platform/util/src/com/intellij/psi/codeStyle/NameUtil.java @@ -505,6 +505,9 @@ public class NameUtil { } if (StringUtil.toLowerCase(name.charAt(nameIndex)) != StringUtil.toLowerCase(myPattern[patternIndex])) { + if (Character.isDigit(name.charAt(nameIndex))) { + return matchName(name, patternIndex, nameIndex + 1); + } return null; } From 4be6f749305e98883591fe651c981cd2875823e8 Mon Sep 17 00:00:00 2001 From: peter Date: Mon, 4 Apr 2011 17:51:45 +0200 Subject: [PATCH 44/65] IDEA-67482 In Groovy, the code "L:{ x + y }.getClass()" should be red --- .../groovy/lang/parser/GroovyParser.java | 2 +- .../lang/parser/StatementsParsingTest.groovy | 1 + .../statements/blocks/labeledClosure.test | 26 +++++++++++++++++++ .../groovy/statements/labeled/label1.test | 23 ++++++++-------- 4 files changed, 39 insertions(+), 13 deletions(-) create mode 100644 plugins/groovy/testdata/parsing/groovy/statements/blocks/labeledClosure.test diff --git a/plugins/groovy/src/org/jetbrains/plugins/groovy/lang/parser/GroovyParser.java b/plugins/groovy/src/org/jetbrains/plugins/groovy/lang/parser/GroovyParser.java index 69d78c4dbae2..dc76717b2322 100644 --- a/plugins/groovy/src/org/jetbrains/plugins/groovy/lang/parser/GroovyParser.java +++ b/plugins/groovy/src/org/jetbrains/plugins/groovy/lang/parser/GroovyParser.java @@ -455,7 +455,7 @@ public class GroovyParser implements PsiParser { ParserUtils.getToken(builder, GroovyTokenTypes.mNLS); - parseStatement(builder, false); + parseStatement(builder, true); marker.done(LABELED_STATEMENT); return true; diff --git a/plugins/groovy/test/org/jetbrains/plugins/groovy/lang/parser/StatementsParsingTest.groovy b/plugins/groovy/test/org/jetbrains/plugins/groovy/lang/parser/StatementsParsingTest.groovy index 95806baff56a..8e212ef6bb03 100644 --- a/plugins/groovy/test/org/jetbrains/plugins/groovy/lang/parser/StatementsParsingTest.groovy +++ b/plugins/groovy/test/org/jetbrains/plugins/groovy/lang/parser/StatementsParsingTest.groovy @@ -20,6 +20,7 @@ public class StatementsParsingTest extends GroovyParsingTestCase { public void testBlocks$clos5() throws Throwable { doTest(); } public void testBlocks$clos6() throws Throwable { doTest(); } public void testBlocks$form() throws Throwable { doTest(); } + public void testBlocks$labeledClosure() throws Throwable { doTest(); } public void testBranch$assert1() throws Throwable { doTest(); } public void testBranch$assert2() throws Throwable { doTest(); } public void testBranch$break1() throws Throwable { doTest(); } diff --git a/plugins/groovy/testdata/parsing/groovy/statements/blocks/labeledClosure.test b/plugins/groovy/testdata/parsing/groovy/statements/blocks/labeledClosure.test new file mode 100644 index 000000000000..2e00e2c25ae8 --- /dev/null +++ b/plugins/groovy/testdata/parsing/groovy/statements/blocks/labeledClosure.test @@ -0,0 +1,26 @@ +L:{ x + y }.getClass() +----- +Groovy script + Labeled statement + Label + PsiElement(identifier)('L') + PsiElement(:)(':') + Block statement + Open block + PsiElement({)('{') + PsiWhiteSpace(' ') + Additive expression + Reference expression + PsiElement(identifier)('x') + PsiWhiteSpace(' ') + PsiElement(+)('+') + PsiWhiteSpace(' ') + Reference expression + PsiElement(identifier)('y') + PsiWhiteSpace(' ') + PsiElement(})('}') + PsiErrorElement:';' or new line expected + PsiElement(.)('.') + PsiElement(identifier)('getClass') + PsiElement(()('(') + PsiElement())(')') \ No newline at end of file diff --git a/plugins/groovy/testdata/parsing/groovy/statements/labeled/label1.test b/plugins/groovy/testdata/parsing/groovy/statements/labeled/label1.test index 3b0e4b0ef9b7..db6b6f12b705 100644 --- a/plugins/groovy/testdata/parsing/groovy/statements/labeled/label1.test +++ b/plugins/groovy/testdata/parsing/groovy/statements/labeled/label1.test @@ -10,15 +10,14 @@ Groovy script PsiElement(identifier)('l') PsiElement(:)(':') PsiWhiteSpace(' ') - Closable block - PsiElement({)('{') - Parameter list - - Call expression - Reference expression - PsiElement(identifier)('println') - PsiWhiteSpace(' ') - Command arguments - Literal - PsiElement(string)(''bugaga'') - PsiElement(})('}') \ No newline at end of file + Block statement + Open block + PsiElement({)('{') + Call expression + Reference expression + PsiElement(identifier)('println') + PsiWhiteSpace(' ') + Command arguments + Literal + PsiElement(string)(''bugaga'') + PsiElement(})('}') \ No newline at end of file From aa2842ced02cd96f54b9125fdf9eff9602dc4bd7 Mon Sep 17 00:00:00 2001 From: peter Date: Mon, 4 Apr 2011 19:12:10 +0200 Subject: [PATCH 45/65] don't show bulb in a non-focused lookup --- .../src/com/intellij/codeInsight/lookup/impl/LookupImpl.java | 4 ++++ 1 file changed, 4 insertions(+) diff --git a/platform/lang-impl/src/com/intellij/codeInsight/lookup/impl/LookupImpl.java b/platform/lang-impl/src/com/intellij/codeInsight/lookup/impl/LookupImpl.java index 4d9048cbd6c0..e3e7c79f5371 100644 --- a/platform/lang-impl/src/com/intellij/codeInsight/lookup/impl/LookupImpl.java +++ b/platform/lang-impl/src/com/intellij/codeInsight/lookup/impl/LookupImpl.java @@ -807,6 +807,10 @@ public class LookupImpl extends LightweightHint implements Lookup, Disposable { } myElementHint = null; } + if (!isFocused()) { + return; + } + final Collection actions = myModel.getActionsFor(item); if (!actions.isEmpty()) { myHintAlarm.addRequest(new Runnable() { From 396cc5be42cc551676ef916216d00cbd280a72cc Mon Sep 17 00:00:00 2001 From: peter Date: Mon, 4 Apr 2011 19:38:30 +0200 Subject: [PATCH 46/65] remember the last selected item in goto popups --- .../intellij/ide/actions/GotoActionBase.java | 18 +++++++----- .../ide/util/gotoByName/ChooseByNameBase.java | 29 +++++++++++++------ .../util/gotoByName/ChooseByNameFilter.java | 8 ++--- .../util/gotoByName/ChooseByNamePopup.java | 17 +++++++---- 4 files changed, 45 insertions(+), 27 deletions(-) diff --git a/platform/lang-impl/src/com/intellij/ide/actions/GotoActionBase.java b/platform/lang-impl/src/com/intellij/ide/actions/GotoActionBase.java index 5b3d926df277..f63dda52cd08 100644 --- a/platform/lang-impl/src/com/intellij/ide/actions/GotoActionBase.java +++ b/platform/lang-impl/src/com/intellij/ide/actions/GotoActionBase.java @@ -28,12 +28,13 @@ import com.intellij.openapi.editor.Editor; import com.intellij.openapi.fileEditor.FileEditorManager; import com.intellij.openapi.fileEditor.ex.FileEditorManagerEx; import com.intellij.openapi.project.Project; +import com.intellij.openapi.util.Pair; import com.intellij.psi.PsiDocumentManager; import com.intellij.psi.PsiElement; import com.intellij.psi.PsiFile; +import com.intellij.util.containers.CollectionFactory; import org.jetbrains.annotations.Nullable; -import java.util.HashMap; import java.util.Map; /** @@ -43,7 +44,7 @@ public abstract class GotoActionBase extends AnAction { private static final Logger LOG = Logger.getInstance("#com.intellij.ide.actions.GotoActionBase"); protected static Class myInAction = null; - private static Map ourLastStrings = new HashMap(); + private static Map> ourLastStrings = CollectionFactory.hashMap(); public final void actionPerformed(AnActionEvent e) { @@ -98,22 +99,22 @@ public abstract class GotoActionBase extends AnAction { public abstract void elementChosen(ChooseByNamePopup popup, Object element); } - private static String getInitialText(Editor editor) { + private static Pair getInitialText(Editor editor) { if (editor != null) { final String selectedText = editor.getSelectionModel().getSelectedText(); if (selectedText != null && selectedText.indexOf("\n") < 0) { - return selectedText; + return Pair.create(selectedText, 0); } } if (myInAction != null) { - final String lastString = ourLastStrings.get(myInAction); + final Pair lastString = ourLastStrings.get(myInAction); if (lastString != null) { return lastString; } } - return ""; + return Pair.create("", 0); } protected static void showNavigationPopup(AnActionEvent e, ChooseByNameModel model, final GotoActionCallback callback) { @@ -122,14 +123,15 @@ public abstract class GotoActionBase extends AnAction { boolean mayRequestOpenInCurrentWindow = model.willOpenEditor() && FileEditorManagerEx.getInstanceEx(project).hasSplitOrUndockedWindows(); final Class startedAction = myInAction; LOG.assertTrue(startedAction != null); - final ChooseByNamePopup popup = ChooseByNamePopup.createPopup(project, model, getPsiContext(e), getInitialText(e.getData(PlatformDataKeys.EDITOR)), mayRequestOpenInCurrentWindow); + Pair start = getInitialText(e.getData(PlatformDataKeys.EDITOR)); + final ChooseByNamePopup popup = ChooseByNamePopup.createPopup(project, model, getPsiContext(e), start.first, mayRequestOpenInCurrentWindow, start.second); final ChooseByNameFilter filter = callback.createFilter(popup); popup.invoke(new ChooseByNamePopupComponent.Callback() { @Override public void onClose() { - ourLastStrings.put(myInAction, popup.getEnteredText()); + ourLastStrings.put(myInAction, Pair.create(popup.getEnteredText(), popup.getSelectedIndex())); if (startedAction.equals(myInAction)) { myInAction = null; } diff --git a/platform/lang-impl/src/com/intellij/ide/util/gotoByName/ChooseByNameBase.java b/platform/lang-impl/src/com/intellij/ide/util/gotoByName/ChooseByNameBase.java index ab40f6580374..0d7ed191cb03 100644 --- a/platform/lang-impl/src/com/intellij/ide/util/gotoByName/ChooseByNameBase.java +++ b/platform/lang-impl/src/com/intellij/ide/util/gotoByName/ChooseByNameBase.java @@ -131,6 +131,7 @@ public abstract class ChooseByNameBase { protected JBPopup myDropdownPopup; private boolean myClosedByShiftEnter = false; + protected final int myInitialIndex; private static class MatchesComparator implements Comparator { private final String myOriginalPattern; @@ -154,10 +155,20 @@ public abstract class ChooseByNameBase { * @param context */ protected ChooseByNameBase(Project project, ChooseByNameModel model, String initialText, final PsiElement context) { + this(project, model, initialText, context, 0); + } + + /** + * @param initialText initial text which will be in the lookup text field + * @param context + * @param initialIndex + */ + protected ChooseByNameBase(Project project, ChooseByNameModel model, String initialText, final PsiElement context, final int initialIndex) { myProject = project; myModel = model; myInitialText = initialText; myContext = new WeakReference(context); + myInitialIndex = initialIndex; } public boolean isPreselectInitialText() { @@ -418,7 +429,7 @@ public abstract class ChooseByNameBase { myCheckBox.addItemListener(new ItemListener() { public void itemStateChanged(ItemEvent e) { - rebuildList(); + rebuildList(false); } }); myCheckBox.setFocusable(false); @@ -426,7 +437,7 @@ public abstract class ChooseByNameBase { myTextField.getDocument().addDocumentListener(new DocumentAdapter() { protected void textChanged(DocumentEvent e) { clearPosponedOkAction(false); - rebuildList(); + rebuildList(false); } }); @@ -514,7 +525,7 @@ public abstract class ChooseByNameBase { showTextFieldPanel(); if (modalityState != null) { - rebuildList(0, 0, null, modalityState, null); + rebuildList(myInitialIndex, 0, null, modalityState, null); } } @@ -528,9 +539,9 @@ public abstract class ChooseByNameBase { /** * Default rebuild list. It uses {@link #REBUILD_DELAY} and current modality state. */ - public void rebuildList() { + public void rebuildList(boolean initial) { // TODO this method is public, because the chooser does not listed for the model. - rebuildList(0, REBUILD_DELAY, null, ModalityState.current(), null); + rebuildList(initial ? myInitialIndex : 0, REBUILD_DELAY, null, ModalityState.current(), null); } private void updateDocumentation() { @@ -577,7 +588,7 @@ public abstract class ChooseByNameBase { return false; } - protected boolean isToFixLostTyping() { + protected static boolean isToFixLostTyping() { return Registry.is("actionSystem.fixLostTyping"); } @@ -793,7 +804,7 @@ public abstract class ChooseByNameBase { myListUpdater.appendToModel(commands, pos); } else { - if (pos == 0) { + if (pos <= 0) { pos = detectBestStatisticalPosition(); } @@ -915,7 +926,7 @@ public abstract class ChooseByNameBase { myList.setVisibleRowCount(Math.min(VISIBLE_LIST_SIZE_LIMIT, myList.getModel().getSize())); if (!myListModel.isEmpty()) { - int pos = selectionPos == 0 ? detectBestStatisticalPosition() : selectionPos; + int pos = selectionPos <= 0 ? detectBestStatisticalPosition() : selectionPos; ListScrollingUtil.selectItem(myList, Math.min(pos, myListModel.size() - 1)); } @@ -1116,7 +1127,7 @@ public abstract class ChooseByNameBase { myTextField.setText(newPattern); myTextField.setCaretPosition(newPattern.length()); - rebuildList(); + rebuildList(false); } private boolean isComplexPattern(final String pattern) { diff --git a/platform/lang-impl/src/com/intellij/ide/util/gotoByName/ChooseByNameFilter.java b/platform/lang-impl/src/com/intellij/ide/util/gotoByName/ChooseByNameFilter.java index fe5feb4ff8de..cbfadfb1782e 100644 --- a/platform/lang-impl/src/com/intellij/ide/util/gotoByName/ChooseByNameFilter.java +++ b/platform/lang-impl/src/com/intellij/ide/util/gotoByName/ChooseByNameFilter.java @@ -173,11 +173,11 @@ public abstract class ChooseByNameFilter { chooser.setElementMarked(type, false); } } - updateModel(model, chooser); + updateModel(model, chooser, true); chooser.addElementsMarkListener(new ElementsChooser.ElementsMarkListener() { public void elementMarkChanged(final T element, final boolean isMarked) { filterConfiguration.setVisible(element, isMarked); - updateModel(model, chooser); + updateModel(model, chooser, false); } }); return chooser; @@ -197,10 +197,10 @@ public abstract class ChooseByNameFilter { * @param gotoFileModel a model * @param chooser a file type chooser */ - protected void updateModel(final FilteringGotoByModel gotoFileModel, ElementsChooser chooser) { + protected void updateModel(final FilteringGotoByModel gotoFileModel, ElementsChooser chooser, boolean initial) { final List markedElements = chooser.getMarkedElements(); gotoFileModel.setFilterItems(markedElements); - myParentPopup.rebuildList(); + myParentPopup.rebuildList(initial); } /** diff --git a/platform/lang-impl/src/com/intellij/ide/util/gotoByName/ChooseByNamePopup.java b/platform/lang-impl/src/com/intellij/ide/util/gotoByName/ChooseByNamePopup.java index 3057d7cf724b..db6fd479016c 100644 --- a/platform/lang-impl/src/com/intellij/ide/util/gotoByName/ChooseByNamePopup.java +++ b/platform/lang-impl/src/com/intellij/ide/util/gotoByName/ChooseByNamePopup.java @@ -51,8 +51,8 @@ public class ChooseByNamePopup extends ChooseByNameBase implements ChooseByNameP private boolean myMayRequestCurrentWindow; protected ChooseByNamePopup(final Project project, final ChooseByNameModel model, final ChooseByNamePopup oldPopup, - final PsiElement context, @Nullable final String predefinedText, boolean mayRequestOpenInCurrentWundow) { - super(project, model, oldPopup != null ? oldPopup.getEnteredText() : predefinedText, context); + final PsiElement context, @Nullable final String predefinedText, boolean mayRequestOpenInCurrentWundow, int initialIndex) { + super(project, model, oldPopup != null ? oldPopup.getEnteredText() : predefinedText, context, initialIndex); if (oldPopup == null && predefinedText != null) { setPreselectInitialText(true); } @@ -66,11 +66,15 @@ public class ChooseByNamePopup extends ChooseByNameBase implements ChooseByNameP return myTextField.getText(); } + public int getSelectedIndex() { + return myList.getSelectedIndex(); + } + protected void initUI(final Callback callback, final ModalityState modalityState, boolean allowMultipleSelection) { super.initUI(callback, modalityState, allowMultipleSelection); //LaterInvocator.enterModal(myTextFieldPanel); if (myInitialText != null) { - rebuildList(0, 0, null, ModalityState.current(), null); + rebuildList(myInitialIndex, 0, null, ModalityState.current(), null); } if (myOldFocusOwner != null){ myPreviouslyFocusedComponent = myOldFocusOwner; @@ -228,18 +232,19 @@ public class ChooseByNamePopup extends ChooseByNameBase implements ChooseByNameP } public static ChooseByNamePopup createPopup(final Project project, final ChooseByNameModel model, final PsiElement context, @Nullable final String predefinedText) { - return createPopup(project, model, context, predefinedText, false); + return createPopup(project, model, context, predefinedText, false, 0); } public static ChooseByNamePopup createPopup(final Project project, final ChooseByNameModel model, final PsiElement context, @Nullable final String predefinedText, - boolean mayRequestOpenInCurrentWindow) { + boolean mayRequestOpenInCurrentWindow, final int initialIndex) { final ChooseByNamePopup oldPopup = project.getUserData(CHOOSE_BY_NAME_POPUP_IN_PROJECT_KEY); if (oldPopup != null) { oldPopup.close(false); } - ChooseByNamePopup newPopup = new ChooseByNamePopup(project, model, oldPopup, context, predefinedText, mayRequestOpenInCurrentWindow); + ChooseByNamePopup newPopup = new ChooseByNamePopup(project, model, oldPopup, context, predefinedText, mayRequestOpenInCurrentWindow, + initialIndex); project.putUserData(CHOOSE_BY_NAME_POPUP_IN_PROJECT_KEY, newPopup); return newPopup; From 66df947193a8b8a59685c172c811cd3616196e19 Mon Sep 17 00:00:00 2001 From: peter Date: Mon, 4 Apr 2011 20:01:40 +0200 Subject: [PATCH 47/65] don't double space when completing 'assert' by space --- .../lang/completion/GroovyInsertHandler.java | 5 ++- .../control/ControlStructureFilter.java | 38 +++++-------------- .../completion/GroovyCompletionTest.groovy | 4 ++ 3 files changed, 18 insertions(+), 29 deletions(-) diff --git a/plugins/groovy/src/org/jetbrains/plugins/groovy/lang/completion/GroovyInsertHandler.java b/plugins/groovy/src/org/jetbrains/plugins/groovy/lang/completion/GroovyInsertHandler.java index d3c280db6494..7923eeee9886 100644 --- a/plugins/groovy/src/org/jetbrains/plugins/groovy/lang/completion/GroovyInsertHandler.java +++ b/plugins/groovy/src/org/jetbrains/plugins/groovy/lang/completion/GroovyInsertHandler.java @@ -109,12 +109,15 @@ public class GroovyInsertHandler implements InsertHandler { return; } - if (obj instanceof String && !"assert".equals(obj)) { + if (obj instanceof String) { Editor editor = context.getEditor(); Document document = editor.getDocument(); if (context.getCompletionChar() == Lookup.REPLACE_SELECT_CHAR) { handleOverwrite(editor.getCaretModel().getOffset(), document); } + else if (context.getCompletionChar() == ' ') { + context.setAddCompletionChar(false); + } } else if (obj instanceof PsiClass) { final PsiClass clazz = (PsiClass)obj; Editor editor = context.getEditor(); diff --git a/plugins/groovy/src/org/jetbrains/plugins/groovy/lang/completion/filters/control/ControlStructureFilter.java b/plugins/groovy/src/org/jetbrains/plugins/groovy/lang/completion/filters/control/ControlStructureFilter.java index 1f91f7d414ad..6977e801f912 100644 --- a/plugins/groovy/src/org/jetbrains/plugins/groovy/lang/completion/filters/control/ControlStructureFilter.java +++ b/plugins/groovy/src/org/jetbrains/plugins/groovy/lang/completion/filters/control/ControlStructureFilter.java @@ -16,23 +16,20 @@ package org.jetbrains.plugins.groovy.lang.completion.filters.control; +import com.intellij.lang.ASTNode; import com.intellij.psi.PsiElement; import com.intellij.psi.filters.ElementFilter; -import com.intellij.lang.ASTNode; import org.jetbrains.annotations.NonNls; import org.jetbrains.plugins.groovy.lang.completion.GroovyCompletionUtil; -import org.jetbrains.plugins.groovy.lang.psi.GroovyFile; +import org.jetbrains.plugins.groovy.lang.lexer.GroovyTokenTypes; import org.jetbrains.plugins.groovy.lang.psi.GrReferenceElement; +import org.jetbrains.plugins.groovy.lang.psi.GroovyFile; import org.jetbrains.plugins.groovy.lang.psi.api.statements.GrForStatement; import org.jetbrains.plugins.groovy.lang.psi.api.statements.GrIfStatement; import org.jetbrains.plugins.groovy.lang.psi.api.statements.GrWhileStatement; -import org.jetbrains.plugins.groovy.lang.psi.api.statements.GrLoopStatement; -import org.jetbrains.plugins.groovy.lang.psi.api.statements.blocks.GrClosableBlock; -import org.jetbrains.plugins.groovy.lang.psi.api.statements.blocks.GrOpenBlock; -import org.jetbrains.plugins.groovy.lang.psi.api.statements.clauses.GrCaseSection; import org.jetbrains.plugins.groovy.lang.psi.api.statements.expressions.GrExpression; import org.jetbrains.plugins.groovy.lang.psi.api.statements.expressions.GrReferenceExpression; -import org.jetbrains.plugins.groovy.lang.lexer.GroovyTokenTypes; +import org.jetbrains.plugins.groovy.lang.psi.api.util.GrStatementOwner; /** * @author ilyas @@ -49,16 +46,8 @@ public class ControlStructureFilter implements ElementFilter { } if (GroovyCompletionUtil.isNewStatement(context, true)) { final PsiElement leaf = GroovyCompletionUtil.getLeafByOffset(offset - 1, context); - if (leaf != null) { - PsiElement parent = leaf.getParent(); - if (parent instanceof GroovyFile || - parent instanceof GrOpenBlock || - parent instanceof GrClosableBlock) { - return true; - } - if (parent instanceof GrCaseSection) { - return true; - } + if (leaf != null && leaf.getParent() instanceof GrStatementOwner) { + return true; } } @@ -73,23 +62,16 @@ public class ControlStructureFilter implements ElementFilter { if (parent instanceof GrReferenceExpression) { PsiElement superParent = parent.getParent(); + if (superParent instanceof GrExpression) { + superParent = superParent.getParent(); + } - if (superParent instanceof GrOpenBlock || - superParent instanceof GrClosableBlock || - superParent instanceof GrCaseSection || + if (superParent instanceof GrStatementOwner || superParent instanceof GrIfStatement || superParent instanceof GrForStatement || superParent instanceof GrWhileStatement) { return true; } - if (superParent instanceof GrExpression) { - PsiElement elem = superParent.getParent(); - if (elem instanceof GrCaseSection || - elem instanceof GrLoopStatement || - elem instanceof GrIfStatement) { - return true; - } - } } return false; diff --git a/plugins/groovy/test/org/jetbrains/plugins/groovy/completion/GroovyCompletionTest.groovy b/plugins/groovy/test/org/jetbrains/plugins/groovy/completion/GroovyCompletionTest.groovy index 9488cbb385f9..b46e8527715c 100644 --- a/plugins/groovy/test/org/jetbrains/plugins/groovy/completion/GroovyCompletionTest.groovy +++ b/plugins/groovy/test/org/jetbrains/plugins/groovy/completion/GroovyCompletionTest.groovy @@ -643,4 +643,8 @@ return foo()""" checkCompletion("new Abcd", '<', "new AbcdClass<>()") } + public void testDoubleSpace() { + checkCompletion "assex", ' ', 'assert x' + } + } \ No newline at end of file From 075c180102662e350f592b754332074a6ff2f972 Mon Sep 17 00:00:00 2001 From: peter Date: Mon, 4 Apr 2011 20:26:58 +0200 Subject: [PATCH 48/65] IDEA-67353 Groovy editor auto import removal puts space before javadoc class comment --- .../lang/parser/GroovyParserDefinition.java | 9 +++++---- .../optimizeImports/OptimizeImportsTest.groovy | 18 ++++++++++++++++++ 2 files changed, 23 insertions(+), 4 deletions(-) diff --git a/plugins/groovy/src/org/jetbrains/plugins/groovy/lang/parser/GroovyParserDefinition.java b/plugins/groovy/src/org/jetbrains/plugins/groovy/lang/parser/GroovyParserDefinition.java index 3fcc027cac68..1cb5d2826796 100644 --- a/plugins/groovy/src/org/jetbrains/plugins/groovy/lang/parser/GroovyParserDefinition.java +++ b/plugins/groovy/src/org/jetbrains/plugins/groovy/lang/parser/GroovyParserDefinition.java @@ -36,6 +36,7 @@ import org.jetbrains.plugins.groovy.lang.lexer.TokenSets; import org.jetbrains.plugins.groovy.lang.psi.impl.GroovyFileImpl; import org.jetbrains.plugins.groovy.lang.psi.stubs.elements.GrStubFileElementType; +import static com.intellij.lang.ParserDefinition.SpaceRequirements.MAY; import static com.intellij.lang.ParserDefinition.SpaceRequirements.MUST; import static com.intellij.lang.ParserDefinition.SpaceRequirements.MUST_LINE_BREAK; import static org.jetbrains.plugins.groovy.lang.parser.GroovyElementTypes.*; @@ -93,10 +94,10 @@ public class GroovyParserDefinition implements ParserDefinition { if (left.getElementType() == mSEMI || left.getElementType() == mSL_COMMENT) { return MUST_LINE_BREAK; } + if (left.getElementType() == mNLS || left.getElementType() == mGDOC_COMMENT_START) { + return MAY; + } - Lexer lexer=new GroovyLexer(); - final SpaceRequirements spaceRequirements = LanguageUtil.canStickTokensTogetherByLexer(left, right, lexer); - - return spaceRequirements; + return LanguageUtil.canStickTokensTogetherByLexer(left, right, new GroovyLexer()); } } diff --git a/plugins/groovy/test/org/jetbrains/plugins/groovy/refactoring/optimizeImports/OptimizeImportsTest.groovy b/plugins/groovy/test/org/jetbrains/plugins/groovy/refactoring/optimizeImports/OptimizeImportsTest.groovy index 221eb294c578..05f9195b169a 100644 --- a/plugins/groovy/test/org/jetbrains/plugins/groovy/refactoring/optimizeImports/OptimizeImportsTest.groovy +++ b/plugins/groovy/test/org/jetbrains/plugins/groovy/refactoring/optimizeImports/OptimizeImportsTest.groovy @@ -162,6 +162,24 @@ public class OptimizeImportsTest extends LightCodeInsightFixtureTestCase { myFixture.checkResult("import a.b.c.d"); } + public void testCleanBeforeJavadoc() throws Exception { + myFixture.configureByText("a.groovy", """import javax.swing.JFrame + +/** + * some javadoc + */ +class Fooxx{ +}"""); + myFixture.type ' ' + myFixture.doHighlighting() +// doOptimizeImports(); + myFixture.checkResult("""/** + * some javadoc + */ +class Fooxx { +}"""); + } + private void doTest() throws Throwable { CodeStyleSettings settings = CodeStyleSettingsManager.getSettings(getProject()).clone(); CodeStyleSettingsManager.getInstance(getProject()).setTemporarySettings(settings); From 38d2f16771704be739f6ccbff26f8e5f6c4a2368 Mon Sep 17 00:00:00 2001 From: peter Date: Mon, 4 Apr 2011 20:28:11 +0200 Subject: [PATCH 49/65] EA-26551 diagnostics --- .../com/intellij/codeInsight/lookup/TailTypeDecorator.java | 6 +++++- 1 file changed, 5 insertions(+), 1 deletion(-) diff --git a/platform/lang-impl/src/com/intellij/codeInsight/lookup/TailTypeDecorator.java b/platform/lang-impl/src/com/intellij/codeInsight/lookup/TailTypeDecorator.java index f5c649b16ee1..daec9ddc99c1 100644 --- a/platform/lang-impl/src/com/intellij/codeInsight/lookup/TailTypeDecorator.java +++ b/platform/lang-impl/src/com/intellij/codeInsight/lookup/TailTypeDecorator.java @@ -53,7 +53,11 @@ public abstract class TailTypeDecorator extends LookupE delegate.handleInsert(context); if (tailType != null && tailType.isApplicable(context)) { PostprocessReformattingAspect.getInstance(context.getProject()).doPostponedFormatting(); - tailType.processTail(context.getEditor(), context.getTailOffset()); + int tailOffset = context.getTailOffset(); + if (tailOffset < 0) { + throw new AssertionError("tailOffset < 0: delegate=" + getDelegate() + "; this=" + this + "; tail=" + tailType); + } + tailType.processTail(context.getEditor(), tailOffset); } } From 74f9e174a7609fddf851c475b195a284a3c55017 Mon Sep 17 00:00:00 2001 From: peter Date: Mon, 4 Apr 2011 20:31:40 +0200 Subject: [PATCH 50/65] EA-26533 invalid closure parameter diagnostics --- .../lang/psi/impl/synthetic/ClosureSyntheticParameter.java | 2 ++ 1 file changed, 2 insertions(+) diff --git a/plugins/groovy/src/org/jetbrains/plugins/groovy/lang/psi/impl/synthetic/ClosureSyntheticParameter.java b/plugins/groovy/src/org/jetbrains/plugins/groovy/lang/psi/impl/synthetic/ClosureSyntheticParameter.java index 128883da4fe9..8009979763f6 100644 --- a/plugins/groovy/src/org/jetbrains/plugins/groovy/lang/psi/impl/synthetic/ClosureSyntheticParameter.java +++ b/plugins/groovy/src/org/jetbrains/plugins/groovy/lang/psi/impl/synthetic/ClosureSyntheticParameter.java @@ -52,6 +52,8 @@ public class ClosureSyntheticParameter extends GrLightParameter implements Navig @Nullable public PsiType getTypeGroovy() { + assert isValid(); + PsiType typeGroovy = GrVariableEnhancer.getEnhancedType(this); if (typeGroovy instanceof PsiIntersectionType) { return ((PsiIntersectionType)typeGroovy).getRepresentative(); From c1e2b9b3d7f76fbc70493beccb44a8b84f3e3aab Mon Sep 17 00:00:00 2001 From: peter Date: Mon, 4 Apr 2011 20:31:52 +0200 Subject: [PATCH 51/65] EA-26533 invalid closure parameter diagnostics --- .../intellij/psi/impl/source/tree/LazyParseablePsiElement.java | 1 + .../groovy/lang/psi/AbstractClosureParameterEnhancer.java | 3 +++ 2 files changed, 4 insertions(+) diff --git a/platform/lang-impl/src/com/intellij/psi/impl/source/tree/LazyParseablePsiElement.java b/platform/lang-impl/src/com/intellij/psi/impl/source/tree/LazyParseablePsiElement.java index 78e8ee6e599d..e8cfbe0f5d16 100644 --- a/platform/lang-impl/src/com/intellij/psi/impl/source/tree/LazyParseablePsiElement.java +++ b/platform/lang-impl/src/com/intellij/psi/impl/source/tree/LazyParseablePsiElement.java @@ -240,6 +240,7 @@ public class LazyParseablePsiElement extends LazyParseableElement implements Psi @NotNull public GlobalSearchScope getResolveScope() { + assert isValid(); return getManager().getFileManager().getResolveScope(this); } diff --git a/plugins/groovy/src/org/jetbrains/plugins/groovy/lang/psi/AbstractClosureParameterEnhancer.java b/plugins/groovy/src/org/jetbrains/plugins/groovy/lang/psi/AbstractClosureParameterEnhancer.java index c8e52c0078e6..3da56ee22261 100644 --- a/plugins/groovy/src/org/jetbrains/plugins/groovy/lang/psi/AbstractClosureParameterEnhancer.java +++ b/plugins/groovy/src/org/jetbrains/plugins/groovy/lang/psi/AbstractClosureParameterEnhancer.java @@ -23,12 +23,15 @@ public abstract class AbstractClosureParameterEnhancer extends GrVariableEnhance return null; } + assert variable.isValid(); GrClosableBlock closure = variable instanceof ClosureSyntheticParameter ? ((ClosureSyntheticParameter)variable).getClosure() : findClosureWithArgument(variable.getParent()); if (closure == null) { return null; } + assert closure.isValid(); + @SuppressWarnings({"SuspiciousMethodCalls"}) int index = Arrays.asList(closure.getAllParameters()).indexOf(variable); assert index >= 0; From 6146b9a8f9ba2403911aa0269227d4a001ab5bcc Mon Sep 17 00:00:00 2001 From: peter Date: Mon, 4 Apr 2011 20:34:19 +0200 Subject: [PATCH 52/65] EA-26492 --- .../lang/psi/impl/statements/expressions/TypesUtil.java | 4 ++-- .../expressions/types/GrSafeCastExpressionImpl.java | 7 ++++++- 2 files changed, 8 insertions(+), 3 deletions(-) diff --git a/plugins/groovy/src/org/jetbrains/plugins/groovy/lang/psi/impl/statements/expressions/TypesUtil.java b/plugins/groovy/src/org/jetbrains/plugins/groovy/lang/psi/impl/statements/expressions/TypesUtil.java index b57f945a9ff0..6d05ab9c7e8f 100644 --- a/plugins/groovy/src/org/jetbrains/plugins/groovy/lang/psi/impl/statements/expressions/TypesUtil.java +++ b/plugins/groovy/src/org/jetbrains/plugins/groovy/lang/psi/impl/statements/expressions/TypesUtil.java @@ -85,9 +85,9 @@ public class TypesUtil { } @NotNull - public static GroovyResolveResult[] getOverloadedOperatorCandidates(PsiType thisType, + public static GroovyResolveResult[] getOverloadedOperatorCandidates(@NotNull PsiType thisType, IElementType tokenType, - GroovyPsiElement place, + @NotNull GroovyPsiElement place, PsiType[] argumentTypes) { return ResolveUtil.getMethodCandidates(thisType, ourOperationsToOperatorNames.get(tokenType), place, argumentTypes); } diff --git a/plugins/groovy/src/org/jetbrains/plugins/groovy/lang/psi/impl/statements/expressions/types/GrSafeCastExpressionImpl.java b/plugins/groovy/src/org/jetbrains/plugins/groovy/lang/psi/impl/statements/expressions/types/GrSafeCastExpressionImpl.java index 9892900f8e30..05f54442c398 100644 --- a/plugins/groovy/src/org/jetbrains/plugins/groovy/lang/psi/impl/statements/expressions/types/GrSafeCastExpressionImpl.java +++ b/plugins/groovy/src/org/jetbrains/plugins/groovy/lang/psi/impl/statements/expressions/types/GrSafeCastExpressionImpl.java @@ -41,8 +41,13 @@ public class GrSafeCastExpressionImpl extends GrExpressionImpl implements GrSafe private static final class OurResolver implements ResolveCache.PolyVariantResolver { @Override public ResolveResult[] resolve(GrSafeCastExpressionImpl cast, boolean incompleteCode) { + PsiType type = cast.getOperand().getType(); + if (type == null) { + return GroovyResolveResult.EMPTY_ARRAY; + } + return TypesUtil.getOverloadedOperatorCandidates( - cast.getOperand().getType(), + type, GroovyTokenTypes.kAS, cast, new PsiType[]{TypesUtil.createJavaLangClassType(cast.getCastTypeElement().getType(), cast.getProject(), cast.getResolveScope())} From 35a41e8295d6b58baa91e0d4ddf482df6bfcb7fd Mon Sep 17 00:00:00 2001 From: peter Date: Mon, 4 Apr 2011 20:35:59 +0200 Subject: [PATCH 53/65] EA-26490 --- java/openapi/src/com/intellij/psi/PsiType.java | 2 +- .../openapi/src/com/intellij/psi/PsiWildcardType.java | 11 ++++++----- 2 files changed, 7 insertions(+), 6 deletions(-) diff --git a/java/openapi/src/com/intellij/psi/PsiType.java b/java/openapi/src/com/intellij/psi/PsiType.java index d52949c5f6d6..581b90434d1e 100644 --- a/java/openapi/src/com/intellij/psi/PsiType.java +++ b/java/openapi/src/com/intellij/psi/PsiType.java @@ -108,7 +108,7 @@ public abstract class PsiType implements PsiAnnotationOwner { * @return the class instance. */ @NotNull - public static PsiClassType getJavaLangObject(PsiManager manager, GlobalSearchScope resolveScope) { + public static PsiClassType getJavaLangObject(@NotNull PsiManager manager, @NotNull GlobalSearchScope resolveScope) { return JavaPsiFacade.getInstance(manager.getProject()).getElementFactory().createTypeByFQClassName(CommonClassNames.JAVA_LANG_OBJECT, resolveScope); } diff --git a/java/openapi/src/com/intellij/psi/PsiWildcardType.java b/java/openapi/src/com/intellij/psi/PsiWildcardType.java index 6a1e1a13ab50..62b0003f1d88 100644 --- a/java/openapi/src/com/intellij/psi/PsiWildcardType.java +++ b/java/openapi/src/com/intellij/psi/PsiWildcardType.java @@ -102,14 +102,15 @@ public class PsiWildcardType extends PsiType { } } - + @NotNull public GlobalSearchScope getResolveScope() { if (myBound != null) { - return myBound.getResolveScope(); - } - else { - return GlobalSearchScope.allScope(myManager.getProject()); + GlobalSearchScope scope = myBound.getResolveScope(); + if (scope != null) { + return scope; + } } + return GlobalSearchScope.allScope(myManager.getProject()); } @NotNull From 8f7e7f3c228444165b9dc1eaf5055b4f6025a519 Mon Sep 17 00:00:00 2001 From: peter Date: Mon, 4 Apr 2011 20:40:49 +0200 Subject: [PATCH 54/65] EA-26452 diagnostics --- .../impl/CompletionServiceImpl.java | 21 ++++++++++++------- 1 file changed, 13 insertions(+), 8 deletions(-) diff --git a/platform/lang-impl/src/com/intellij/codeInsight/completion/impl/CompletionServiceImpl.java b/platform/lang-impl/src/com/intellij/codeInsight/completion/impl/CompletionServiceImpl.java index 7b78d815d82d..db77113140fc 100644 --- a/platform/lang-impl/src/com/intellij/codeInsight/completion/impl/CompletionServiceImpl.java +++ b/platform/lang-impl/src/com/intellij/codeInsight/completion/impl/CompletionServiceImpl.java @@ -29,11 +29,9 @@ import com.intellij.openapi.project.ProjectManagerAdapter; import com.intellij.openapi.util.Disposer; import com.intellij.openapi.util.text.StringUtil; import com.intellij.patterns.ElementPattern; -import com.intellij.psi.PsiDocumentManager; -import com.intellij.psi.PsiElement; -import com.intellij.psi.Weigher; -import com.intellij.psi.WeighingService; +import com.intellij.psi.*; import com.intellij.psi.impl.DebugUtil; +import com.intellij.psi.impl.source.tree.injected.InjectedLanguageUtil; import com.intellij.util.Consumer; import org.jetbrains.annotations.NotNull; import org.jetbrains.annotations.Nullable; @@ -82,7 +80,7 @@ public class CompletionServiceImpl extends CompletionService{ final PsiElement position = parameters.getPosition(); final String prefix = CompletionData.findPrefixStatic(position, parameters.getOffset()); final String textBeforePosition = parameters.getPosition().getContainingFile().getText().substring(0, parameters.getOffset()); - return new CompletionResultSetImpl(consumer, textBeforePosition, new CamelHumpMatcher(prefix, true, parameters.relaxMatching()), contributor, defaultSorter(parameters), null); + return new CompletionResultSetImpl(consumer, textBeforePosition, new CamelHumpMatcher(prefix, true, parameters.relaxMatching()), contributor, parameters, defaultSorter(parameters), null); } @Override @@ -108,16 +106,19 @@ public class CompletionServiceImpl extends CompletionService{ private static class CompletionResultSetImpl extends CompletionResultSet { private final String myTextBeforePosition; + private final CompletionParameters myParameters; private final CompletionSorterImpl mySorter; @Nullable private final CompletionResultSetImpl myOriginal; public CompletionResultSetImpl(final Consumer consumer, final String textBeforePosition, final PrefixMatcher prefixMatcher, CompletionContributor contributor, + CompletionParameters parameters, @NotNull CompletionSorterImpl sorter, CompletionResultSetImpl original) { super(prefixMatcher, consumer, contributor); myTextBeforePosition = textBeforePosition; + myParameters = parameters; mySorter = sorter; myOriginal = original; } @@ -133,9 +134,13 @@ public class CompletionServiceImpl extends CompletionService{ if (!myTextBeforePosition.endsWith(matcher.getPrefix())) { final int len = myTextBeforePosition.length(); final String fragment = len > 100 ? myTextBeforePosition.substring(len - 100) : myTextBeforePosition; - LOG.error("prefix should be some actual file string just before caret: " + matcher.getPrefix() + "\n text=" + fragment); + PsiFile positionFile = myParameters.getPosition().getContainingFile(); + LOG.error("prefix should be some actual file string just before caret: " + matcher.getPrefix() + + "\n text=" + fragment + + "\ninjected=" + (InjectedLanguageUtil.getTopLevelFile(positionFile) != positionFile) + + "\nlang=" + positionFile.getLanguage()); } - return new CompletionResultSetImpl(getConsumer(), myTextBeforePosition, matcher, myContributor, mySorter, this); + return new CompletionResultSetImpl(getConsumer(), myTextBeforePosition, matcher, myContributor, myParameters, mySorter, this); } @Override @@ -155,7 +160,7 @@ public class CompletionServiceImpl extends CompletionService{ @NotNull @Override public CompletionResultSet withRelevanceSorter(@NotNull CompletionSorter sorter) { - return new CompletionResultSetImpl(getConsumer(), myTextBeforePosition, getPrefixMatcher(), myContributor, (CompletionSorterImpl)sorter, this); + return new CompletionResultSetImpl(getConsumer(), myTextBeforePosition, getPrefixMatcher(), myContributor, myParameters, (CompletionSorterImpl)sorter, this); } @NotNull From 909b1213def10b1fe132c1a82ff8a21abd1d2534 Mon Sep 17 00:00:00 2001 From: peter Date: Mon, 4 Apr 2011 21:06:53 +0200 Subject: [PATCH 55/65] IDEA-67373 SuppressWarnings with more than one suppression doesn't work in Groovy --- .../GroovySuppressableInspectionTool.java | 6 +-- .../codeInspection/SuppressForMemberFix.java | 8 ++-- .../GrAnnotationArrrayInitializerImpl.java | 14 +++++++ .../groovy/lang/GroovyFixesTest.groovy | 39 +++++++++++++++++++ .../groovy/lang/GroovyHighlightingTest.java | 4 ++ .../testdata/highlighting/Suppressions.groovy | 16 ++++++++ 6 files changed, 81 insertions(+), 6 deletions(-) create mode 100644 plugins/groovy/testdata/highlighting/Suppressions.groovy diff --git a/plugins/groovy/src/org/jetbrains/plugins/groovy/codeInspection/GroovySuppressableInspectionTool.java b/plugins/groovy/src/org/jetbrains/plugins/groovy/codeInspection/GroovySuppressableInspectionTool.java index 81fb79f93326..0e15b25a45d0 100644 --- a/plugins/groovy/src/org/jetbrains/plugins/groovy/codeInspection/GroovySuppressableInspectionTool.java +++ b/plugins/groovy/src/org/jetbrains/plugins/groovy/codeInspection/GroovySuppressableInspectionTool.java @@ -27,8 +27,8 @@ import com.intellij.psi.PsiElement; import com.intellij.psi.util.PsiTreeUtil; import org.jetbrains.annotations.NotNull; import org.jetbrains.annotations.Nullable; -import org.jetbrains.plugins.groovy.lang.psi.api.auxiliary.GrListOrMap; import org.jetbrains.plugins.groovy.lang.psi.api.auxiliary.modifiers.GrModifierList; +import org.jetbrains.plugins.groovy.lang.psi.api.auxiliary.modifiers.annotation.GrAnnotationArrayInitializer; import org.jetbrains.plugins.groovy.lang.psi.api.auxiliary.modifiers.annotation.GrAnnotationMemberValue; import org.jetbrains.plugins.groovy.lang.psi.api.statements.expressions.GrExpression; import org.jetbrains.plugins.groovy.lang.psi.api.statements.expressions.literals.GrLiteral; @@ -108,8 +108,8 @@ public abstract class GroovySuppressableInspectionTool extends LocalInspectionTo } final GrAnnotationMemberValue attributeValue = (GrAnnotationMemberValue)annotation.findAttributeValue(null); Collection result = new ArrayList(); - if (attributeValue instanceof GrListOrMap) { - for (GrExpression annotationMemberValue : ((GrListOrMap)attributeValue).getInitializers()) { + if (attributeValue instanceof GrAnnotationArrayInitializer) { + for (GrExpression annotationMemberValue : ((GrAnnotationArrayInitializer)attributeValue).getInitializers()) { final String id = getInspectionIdSuppressedInAnnotationAttribute(annotationMemberValue); if (id != null) { result.add(id); diff --git a/plugins/groovy/src/org/jetbrains/plugins/groovy/codeInspection/SuppressForMemberFix.java b/plugins/groovy/src/org/jetbrains/plugins/groovy/codeInspection/SuppressForMemberFix.java index f37fcb8ad141..f48ddc92a6b9 100644 --- a/plugins/groovy/src/org/jetbrains/plugins/groovy/codeInspection/SuppressForMemberFix.java +++ b/plugins/groovy/src/org/jetbrains/plugins/groovy/codeInspection/SuppressForMemberFix.java @@ -32,8 +32,9 @@ import org.jetbrains.annotations.NotNull; import org.jetbrains.annotations.Nullable; import org.jetbrains.plugins.groovy.lang.groovydoc.psi.api.GrDocCommentOwner; import org.jetbrains.plugins.groovy.lang.psi.GroovyPsiElementFactory; -import org.jetbrains.plugins.groovy.lang.psi.api.auxiliary.GrListOrMap; import org.jetbrains.plugins.groovy.lang.psi.api.auxiliary.modifiers.GrModifierList; +import org.jetbrains.plugins.groovy.lang.psi.api.auxiliary.modifiers.annotation.GrAnnotation; +import org.jetbrains.plugins.groovy.lang.psi.api.auxiliary.modifiers.annotation.GrAnnotationArrayInitializer; import org.jetbrains.plugins.groovy.lang.psi.api.statements.expressions.GrExpression; import org.jetbrains.plugins.groovy.lang.psi.api.statements.typedef.GrAnonymousClassDefinition; import org.jetbrains.plugins.groovy.lang.psi.api.statements.typedef.GrTypeDefinition; @@ -109,10 +110,11 @@ public class SuppressForMemberFix extends SuppressIntentionAction { final GrExpression toAdd = GroovyPsiElementFactory.getInstance(project).createExpressionFromText("\"" + id + "\""); if (annotation != null) { final PsiAnnotationMemberValue value = annotation.findDeclaredAttributeValue(null); - if (value instanceof GrListOrMap) { + if (value instanceof GrAnnotationArrayInitializer) { value.add(toAdd); } else if (value != null) { - final GrExpression list = GroovyPsiElementFactory.getInstance(project).createExpressionFromText("[]"); + GrAnnotation anno = GroovyPsiElementFactory.getInstance(project).createAnnotationFromText("@A([])"); + final GrAnnotationArrayInitializer list = (GrAnnotationArrayInitializer)anno.findDeclaredAttributeValue(null); list.add(value); list.add(toAdd); annotation.setDeclaredAttributeValue(null, list); diff --git a/plugins/groovy/src/org/jetbrains/plugins/groovy/lang/psi/impl/auxiliary/annotation/GrAnnotationArrrayInitializerImpl.java b/plugins/groovy/src/org/jetbrains/plugins/groovy/lang/psi/impl/auxiliary/annotation/GrAnnotationArrrayInitializerImpl.java index a442ff1a0027..d9545ffb4153 100644 --- a/plugins/groovy/src/org/jetbrains/plugins/groovy/lang/psi/impl/auxiliary/annotation/GrAnnotationArrrayInitializerImpl.java +++ b/plugins/groovy/src/org/jetbrains/plugins/groovy/lang/psi/impl/auxiliary/annotation/GrAnnotationArrrayInitializerImpl.java @@ -23,6 +23,8 @@ import org.jetbrains.plugins.groovy.lang.psi.api.auxiliary.modifiers.annotation. import org.jetbrains.plugins.groovy.lang.psi.api.statements.expressions.GrExpression; import org.jetbrains.plugins.groovy.lang.psi.impl.GroovyPsiElementImpl; +import static org.jetbrains.plugins.groovy.lang.lexer.GroovyTokenTypes.mCOMMA; + /** * @author: Dmitry.Krasilschikov * @date: 04.04.2007 @@ -44,4 +46,16 @@ public class GrAnnotationArrrayInitializerImpl extends GroovyPsiElementImpl impl public GrExpression[] getInitializers() { return findChildrenByClass(GrExpression.class); } + + @Override + public ASTNode addInternal(ASTNode first, ASTNode last, ASTNode anchor, Boolean before) { + final GrExpression[] initializers = getInitializers(); + if (initializers.length == 0) { + return super.addInternal(first, last, getNode().getFirstChildNode(), false); + } + final ASTNode lastChild = getNode().getLastChildNode(); + getNode().addLeaf(mCOMMA, ",", lastChild); + return super.addInternal(first, last, lastChild.getTreePrev(), false); + } + } \ No newline at end of file diff --git a/plugins/groovy/test/org/jetbrains/plugins/groovy/lang/GroovyFixesTest.groovy b/plugins/groovy/test/org/jetbrains/plugins/groovy/lang/GroovyFixesTest.groovy index 427f22a1fb64..54e27ab9e111 100644 --- a/plugins/groovy/test/org/jetbrains/plugins/groovy/lang/GroovyFixesTest.groovy +++ b/plugins/groovy/test/org/jetbrains/plugins/groovy/lang/GroovyFixesTest.groovy @@ -8,6 +8,7 @@ package org.jetbrains.plugins.groovy.lang; import com.intellij.testFramework.fixtures.LightCodeInsightFixtureTestCase import org.jetbrains.plugins.groovy.codeInspection.control.GroovyConstantIfStatementInspection import org.jetbrains.plugins.groovy.codeInspection.gpath.GroovySetterCallCanBePropertyAccessInspection +import org.jetbrains.plugins.groovy.codeInspection.untypedUnresolvedAccess.GroovyUnresolvedAccessInspection /** * @author peter @@ -42,4 +43,42 @@ if (true) { assertEmpty myFixture.filterAvailableIntentions("Change to Groovy-style property reference") } + public void testSecondAnnotationSuppression() { + myFixture.enableInspections new GroovyUnresolvedAccessInspection() + myFixture.configureByText "a.groovy", """class FooBarGoo { + @SuppressWarnings(["GroovyParameterNamingConvention"]) + def test(def abc) { + abc.def() + } +} +""" + myFixture.launchAction(myFixture.findSingleIntention("Suppress for method")) + myFixture.checkResult """class FooBarGoo { + @SuppressWarnings(["GroovyParameterNamingConvention", "GroovyUnresolvedAccess"]) + def test(def abc) { + abc.def() + } +} +""" + } + + public void testSecondAnnotationSuppression2() { + myFixture.enableInspections new GroovyUnresolvedAccessInspection() + myFixture.configureByText "a.groovy", """class FooBarGoo { + @SuppressWarnings("GroovyParameterNamingConvention") + def test(def abc) { + abc.def() + } +} +""" + myFixture.launchAction(myFixture.findSingleIntention("Suppress for method")) + myFixture.checkResult """class FooBarGoo { + @SuppressWarnings(["GroovyParameterNamingConvention", "GroovyUnresolvedAccess"]) + def test(def abc) { + abc.def() + } +} +""" + } + } diff --git a/plugins/groovy/test/org/jetbrains/plugins/groovy/lang/GroovyHighlightingTest.java b/plugins/groovy/test/org/jetbrains/plugins/groovy/lang/GroovyHighlightingTest.java index 750febc26521..1fe08ab782b3 100644 --- a/plugins/groovy/test/org/jetbrains/plugins/groovy/lang/GroovyHighlightingTest.java +++ b/plugins/groovy/test/org/jetbrains/plugins/groovy/lang/GroovyHighlightingTest.java @@ -355,6 +355,10 @@ public class GroovyHighlightingTest extends LightCodeInsightFixtureTestCase { doTest(new GroovyAssignabilityCheckInspection()); } + public void testSuppressions() { + doTest(new GroovyUnresolvedAccessInspection(), new GroovyUntypedAccessInspection()); + } + public void testDuplicatedNamedArgs() {doTest();} public void testAnonymousClassArgList() { diff --git a/plugins/groovy/testdata/highlighting/Suppressions.groovy b/plugins/groovy/testdata/highlighting/Suppressions.groovy new file mode 100644 index 000000000000..8fbec0406be9 --- /dev/null +++ b/plugins/groovy/testdata/highlighting/Suppressions.groovy @@ -0,0 +1,16 @@ + +class FooBarGoo { + @SuppressWarnings(["GroovyUnresolvedAccess", "GroovyUntypedAccess"]) + def test1(def abc) { + abc.def() + } + + @SuppressWarnings("GroovyUnresolvedAccess") + def test2(def abc) { + abc.def() + } + + def test3(def abc) { + abc.def() + } +} From 554cc2d485c236888259488f4a3abf36e102cd92 Mon Sep 17 00:00:00 2001 From: peter Date: Tue, 5 Apr 2011 16:24:12 +0200 Subject: [PATCH 56/65] groovy: prefer imported classes to inherited ones (IDEA-67385) --- .../impl/types/GrCodeReferenceElementImpl.java | 13 ++++++++++++- .../groovy/lang/resolve/ResolveClassTest.groovy | 15 +++++++++++++++ 2 files changed, 27 insertions(+), 1 deletion(-) diff --git a/plugins/groovy/src/org/jetbrains/plugins/groovy/lang/psi/impl/types/GrCodeReferenceElementImpl.java b/plugins/groovy/src/org/jetbrains/plugins/groovy/lang/psi/impl/types/GrCodeReferenceElementImpl.java index e1c5ba35d75d..056bbeeabfa6 100644 --- a/plugins/groovy/src/org/jetbrains/plugins/groovy/lang/psi/impl/types/GrCodeReferenceElementImpl.java +++ b/plugins/groovy/src/org/jetbrains/plugins/groovy/lang/psi/impl/types/GrCodeReferenceElementImpl.java @@ -31,6 +31,7 @@ import org.jetbrains.plugins.groovy.lang.groovydoc.psi.api.GrDocReferenceElement import org.jetbrains.plugins.groovy.lang.parser.GroovyElementTypes; import org.jetbrains.plugins.groovy.lang.psi.GroovyElementVisitor; import org.jetbrains.plugins.groovy.lang.psi.GroovyFile; +import org.jetbrains.plugins.groovy.lang.psi.GroovyPsiElement; import org.jetbrains.plugins.groovy.lang.psi.GroovyPsiElementFactory; import org.jetbrains.plugins.groovy.lang.psi.api.GroovyResolveResult; import org.jetbrains.plugins.groovy.lang.psi.api.statements.expressions.GrExpression; @@ -307,6 +308,7 @@ public class GrCodeReferenceElementImpl extends GrReferenceElementImpl imported = new ArrayList(); final PsiType[] args = reference.getTypeArguments(); for (int i = 0; i < results.length; i++) { GroovyResolveResult result = results[i]; @@ -314,9 +316,18 @@ public class GrCodeReferenceElementImpl extends GrReferenceElementImpl {} } ") + myFixture.addClass("package java.util; public class MainMap { static interface Entry {} } ") + + myFixture.configureByText("a.groovy", """ +import java.util.MainMap.Entry; + +public class Test extends MyMap { + public void m(Entry o) {} +} +""") + def target = myFixture.getFile().findReferenceAt(myFixture.editor.caretModel.offset).resolve() + assert assertInstanceOf(target, PsiClass).qualifiedName == 'java.util.MainMap.Entry' + } + void testPreferLastImportedAlias() { myFixture.addFileToProject "a/C1.groovy", "package a; class C1{}" myFixture.addFileToProject "a/C2.groovy", "package a; class C2{}" From 385889f911603e603a1cf66326189deb46b75b0e Mon Sep 17 00:00:00 2001 From: peter Date: Tue, 5 Apr 2011 17:00:10 +0200 Subject: [PATCH 57/65] don't move selected items 1 pixel left in list popups (someone modified our border's insets) --- .../src/com/intellij/ui/DottedBorder.java | 13 ++++++++----- 1 file changed, 8 insertions(+), 5 deletions(-) diff --git a/platform/platform-api/src/com/intellij/ui/DottedBorder.java b/platform/platform-api/src/com/intellij/ui/DottedBorder.java index d93bef82348f..d1389960a429 100644 --- a/platform/platform-api/src/com/intellij/ui/DottedBorder.java +++ b/platform/platform-api/src/com/intellij/ui/DottedBorder.java @@ -25,17 +25,19 @@ import java.awt.*; * Date: 08-Nov-2005 */ public class DottedBorder implements Border { - private final Insets myInsets; + private final int myTop, myBottom, myLeft, myRight; private final Color myColor; public DottedBorder(Insets insets, Color color) { - myInsets = insets; + myTop = insets.top; + myBottom = insets.bottom; + myLeft = insets.left; + myRight = insets.right; myColor = color; } public DottedBorder(Color color) { - myInsets = new Insets(1, 1, 1, 1); - myColor = color; + this(new Insets(1, 1, 1, 1), color); } public void paintBorder(Component c, Graphics g, int x, int y, int width, int height) { @@ -44,7 +46,8 @@ public class DottedBorder implements Border { } public Insets getBorderInsets(Component c) { - return myInsets; + //return a copy, otherwise someone could change our insets from outside + return new Insets(myTop, myLeft, myBottom, myRight); } public boolean isBorderOpaque() { From a8b2a07ba24b594aaa3924d2b2622eb490643bbf Mon Sep 17 00:00:00 2001 From: peter Date: Tue, 5 Apr 2011 17:33:51 +0200 Subject: [PATCH 58/65] don't go into exponential resolve when processing @Delegate (IDEA-67426) --- .../groovy/lang/psi/util/GrClassImplUtil.java | 59 +++++++++++-------- .../groovy/lang/GroovyStressTest.groovy | 11 ++++ 2 files changed, 45 insertions(+), 25 deletions(-) diff --git a/plugins/groovy/src/org/jetbrains/plugins/groovy/lang/psi/util/GrClassImplUtil.java b/plugins/groovy/src/org/jetbrains/plugins/groovy/lang/psi/util/GrClassImplUtil.java index afbbc968ff33..c3a7f45d28f1 100644 --- a/plugins/groovy/src/org/jetbrains/plugins/groovy/lang/psi/util/GrClassImplUtil.java +++ b/plugins/groovy/src/org/jetbrains/plugins/groovy/lang/psi/util/GrClassImplUtil.java @@ -16,9 +16,7 @@ package org.jetbrains.plugins.groovy.lang.psi.util; -import com.intellij.openapi.util.Condition; -import com.intellij.openapi.util.Key; -import com.intellij.openapi.util.Pair; +import com.intellij.openapi.util.*; import com.intellij.psi.*; import com.intellij.psi.impl.PsiClassImplUtil; import com.intellij.psi.impl.light.LightMethodBuilder; @@ -114,7 +112,10 @@ public class GrClassImplUtil { if (!visited.add(grType)) return; final PsiClassType[] implementsTypes = getReferenceListTypes(grType.getImplementsClause()); - getImplementsFromDelegate(grType, result, visited); + List fromDelegates = getImplementsFromDelegate(grType, visited); + if (fromDelegates != null) { + result.addAll(fromDelegates); + } result.addAll(Arrays.asList(implementsTypes)); if (!grType.isInterface() && @@ -124,32 +125,40 @@ public class GrClassImplUtil { } } - private static List getImplementsFromDelegate(GrTypeDefinition grType, List result, Set visited) { - final GrField[] fields = grType.getFields(); - for (GrField field : fields) { - final PsiAnnotation delegate = getAnnotation(field, GroovyCommonClassNames.GROOVY_LANG_DELEGATE); - if (delegate == null) continue; + @Nullable + private static List getImplementsFromDelegate(final GrTypeDefinition grType, final Set visited) { + return RecursionManager.createGuard("groovyDelegateFields").doPreventingRecursion(grType, new Computable>() { + @Override + public List compute() { + List result = new ArrayList(); + final GrField[] fields = grType.getFields(); + for (GrField field : fields) { + final PsiAnnotation delegate = getAnnotation(field, GroovyCommonClassNames.GROOVY_LANG_DELEGATE); + if (delegate == null) continue; - final boolean shouldImplement = shouldImplementDelegatedInterfaces(delegate); - if (!shouldImplement) continue; + final boolean shouldImplement = shouldImplementDelegatedInterfaces(delegate); + if (!shouldImplement) continue; - final PsiType type = field.getDeclaredType(); - if (!(type instanceof PsiClassType)) continue; + final PsiType type = field.getDeclaredType(); + if (!(type instanceof PsiClassType)) continue; - final PsiClass psiClass = ((PsiClassType)type).resolve(); - if (psiClass == null) continue; + final PsiClass psiClass = ((PsiClassType)type).resolve(); + if (psiClass == null) continue; + + if (psiClass instanceof GrTypeDefinition) { + getImplementListsInner((GrTypeDefinition)psiClass, result, visited); + } + else { + result.addAll(Arrays.asList(psiClass.getImplementsListTypes())); + } + if (psiClass.isInterface()) { + result.add((PsiClassType)type); + } + } + return result; - if (psiClass instanceof GrTypeDefinition) { - getImplementListsInner((GrTypeDefinition)psiClass, result, visited); } - else { - result.addAll(Arrays.asList(psiClass.getImplementsListTypes())); - } - if (psiClass.isInterface()) { - result.add((PsiClassType)type); - } - } - return result; + }); } public static PsiClassType getGroovyObjectType(@NotNull PsiElement context) { diff --git a/plugins/groovy/test/org/jetbrains/plugins/groovy/lang/GroovyStressTest.groovy b/plugins/groovy/test/org/jetbrains/plugins/groovy/lang/GroovyStressTest.groovy index 763ad3db5494..a711aab9f6db 100644 --- a/plugins/groovy/test/org/jetbrains/plugins/groovy/lang/GroovyStressTest.groovy +++ b/plugins/groovy/test/org/jetbrains/plugins/groovy/lang/GroovyStressTest.groovy @@ -82,4 +82,15 @@ class GroovyStressTest extends LightCodeInsightFixtureTestCase { IdeaTestUtil.assertTiming "slow", 7000, (System.currentTimeMillis() - start) } + public void testManyAnnotatedFields() { + String text = "class Foo {\n" + for (i in 1..10) { + text += "@Deprecated String foo$i\n" + } + text += "}" + + myFixture.configureByText("a.groovy", text) + IdeaTestUtil.assertTiming "slow", 5000, { myFixture.doHighlighting() } as Runnable + } + } From 35f664710850cc1edb6cf425331da70ed4799514 Mon Sep 17 00:00:00 2001 From: peter Date: Tue, 5 Apr 2011 18:10:28 +0200 Subject: [PATCH 59/65] EA-26260 don't update structure view for invalid items --- .../groovy/lang/resolve/CollectClassMembersUtil.java | 11 +++++++++-- .../GroovyTypeDefinitionStructureViewElement.java | 7 +++++++ 2 files changed, 16 insertions(+), 2 deletions(-) diff --git a/plugins/groovy/src/org/jetbrains/plugins/groovy/lang/resolve/CollectClassMembersUtil.java b/plugins/groovy/src/org/jetbrains/plugins/groovy/lang/resolve/CollectClassMembersUtil.java index b344b283ecc8..8cec6f4db9ff 100644 --- a/plugins/groovy/src/org/jetbrains/plugins/groovy/lang/resolve/CollectClassMembersUtil.java +++ b/plugins/groovy/src/org/jetbrains/plugins/groovy/lang/resolve/CollectClassMembersUtil.java @@ -15,6 +15,7 @@ */ package org.jetbrains.plugins.groovy.lang.resolve; +import com.intellij.openapi.diagnostic.Logger; import com.intellij.openapi.util.Key; import com.intellij.openapi.util.Trinity; import com.intellij.psi.*; @@ -37,6 +38,7 @@ import java.util.Set; * @author ven */ public class CollectClassMembersUtil { + private static final Logger LOG = Logger.getInstance("#org.jetbrains.plugins.groovy.lang.resolve.CollectClassMembersUtil"); private static final Key, Map>, Map>>> CACHED_MEMBERS = Key.create("CACHED_CLASS_MEMBERS"); private static final Key, Map>, Map>>> CACHED_MEMBERS_INCLUDING_SYNTHETIC = Key.create("CACHED_MEMBERS_INCLUDING_SYNTHETIC"); @@ -85,6 +87,8 @@ public class CollectClassMembersUtil { } private static void processClass(PsiClass aClass, Map allFields, Map> allMethods, Map allInnerClasses, Set visitedClasses, PsiSubstitutor substitutor, boolean includeSynthetic, boolean shouldProcessInnerClasses) { + LOG.assertTrue(aClass.isValid()); + if (visitedClasses.contains(aClass)) return; visitedClasses.add(aClass); @@ -92,7 +96,8 @@ public class CollectClassMembersUtil { String name = field.getName(); if (!allFields.containsKey(name)) { allFields.put(name, new CandidateInfo(field, substitutor)); - } else if (hasExplicitVisibilityModifiers(field)) { + } + else if (hasExplicitVisibilityModifiers(field)) { final CandidateInfo candidateInfo = allFields.get(name); final PsiElement element = candidateInfo.getElement(); if (element instanceof GrField && (((GrField)element).getModifierList() == null || @@ -104,7 +109,9 @@ public class CollectClassMembersUtil { } } - for (PsiMethod method : includeSynthetic || !(aClass instanceof GrTypeDefinition) ? aClass.getMethods() : ((GrTypeDefinition) aClass).getGroovyMethods()) { + for (PsiMethod method : includeSynthetic || !(aClass instanceof GrTypeDefinition) + ? aClass.getMethods() + : ((GrTypeDefinition)aClass).getGroovyMethods()) { addMethod(allMethods, method, substitutor); } diff --git a/plugins/groovy/src/org/jetbrains/plugins/groovy/structure/elements/impl/GroovyTypeDefinitionStructureViewElement.java b/plugins/groovy/src/org/jetbrains/plugins/groovy/structure/elements/impl/GroovyTypeDefinitionStructureViewElement.java index 80ce58e6e41e..090dfd35ebb8 100644 --- a/plugins/groovy/src/org/jetbrains/plugins/groovy/structure/elements/impl/GroovyTypeDefinitionStructureViewElement.java +++ b/plugins/groovy/src/org/jetbrains/plugins/groovy/structure/elements/impl/GroovyTypeDefinitionStructureViewElement.java @@ -17,6 +17,7 @@ package org.jetbrains.plugins.groovy.structure.elements.impl; import com.intellij.ide.util.treeView.smartTree.TreeElement; import com.intellij.navigation.ItemPresentation; +import com.intellij.openapi.diagnostic.Logger; import com.intellij.psi.PsiClass; import com.intellij.psi.PsiField; import com.intellij.psi.PsiMethod; @@ -32,6 +33,8 @@ import java.util.List; import java.util.Set; public class GroovyTypeDefinitionStructureViewElement extends GroovyStructureViewElement { + private static final Logger LOG = + Logger.getInstance("#org.jetbrains.plugins.groovy.structure.elements.impl.GroovyTypeDefinitionStructureViewElement"); public GroovyTypeDefinitionStructureViewElement(GrTypeDefinition typeDefinition) { super(typeDefinition); } @@ -45,6 +48,10 @@ public class GroovyTypeDefinitionStructureViewElement extends GroovyStructureVie } public TreeElement[] getChildren() { + if (!myElement.isValid()) { + return EMPTY_ARRAY; + } + List children = new ArrayList(); //adding statements for type definition From 6ea42ea23be032653c6f0e9d00ae90799da748d2 Mon Sep 17 00:00:00 2001 From: peter Date: Tue, 5 Apr 2011 18:16:28 +0200 Subject: [PATCH 60/65] some diagnostics for updating lookup for a non-showing editor --- .../src/com/intellij/codeInsight/lookup/impl/LookupImpl.java | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/platform/lang-impl/src/com/intellij/codeInsight/lookup/impl/LookupImpl.java b/platform/lang-impl/src/com/intellij/codeInsight/lookup/impl/LookupImpl.java index e3e7c79f5371..3cd2178eb1ce 100644 --- a/platform/lang-impl/src/com/intellij/codeInsight/lookup/impl/LookupImpl.java +++ b/platform/lang-impl/src/com/intellij/codeInsight/lookup/impl/LookupImpl.java @@ -593,7 +593,7 @@ public class LookupImpl extends LightweightHint implements Lookup, Disposable { JComponent internalComponent = myEditor.getContentComponent(); final JRootPane rootPane = editorComponent.getRootPane(); if (rootPane == null) { - LOG.error(myEditor.isDisposed()); + LOG.error(myEditor.isDisposed() + "; shown=" + myShown + "; disposed=" + myDisposed + "; editorShowing=" + myEditor.getContentComponent().isShowing()); } JLayeredPane layeredPane = rootPane.getLayeredPane(); Point layeredPanePoint=SwingUtilities.convertPoint(internalComponent,location, layeredPane); From d558f7e57cbf6dae7b70f8bd13ca6f24832f0a10 Mon Sep 17 00:00:00 2001 From: peter Date: Tue, 5 Apr 2011 18:23:09 +0200 Subject: [PATCH 61/65] don't allow guarded actions to destroy the lookup start marker (EA-26502) --- .../src/com/intellij/codeInsight/lookup/impl/LookupImpl.java | 5 ++++- 1 file changed, 4 insertions(+), 1 deletion(-) diff --git a/platform/lang-impl/src/com/intellij/codeInsight/lookup/impl/LookupImpl.java b/platform/lang-impl/src/com/intellij/codeInsight/lookup/impl/LookupImpl.java index 3cd2178eb1ce..23113716c227 100644 --- a/platform/lang-impl/src/com/intellij/codeInsight/lookup/impl/LookupImpl.java +++ b/platform/lang-impl/src/com/intellij/codeInsight/lookup/impl/LookupImpl.java @@ -581,7 +581,7 @@ public class LookupImpl extends LightweightHint implements Lookup, Disposable { public Point calculatePosition(final JComponent component) { Dimension dim = component.getPreferredSize(); int lookupStart = getLookupStart(); - if (lookupStart < 0) { + if (lookupStart < 0 || lookupStart >= myEditor.getDocument().getTextLength()) { LOG.error(lookupStart + "; offset=" + myEditor.getCaretModel().getOffset() + "; element=" + getPsiElement()); } @@ -670,6 +670,7 @@ public class LookupImpl extends LightweightHint implements Lookup, Disposable { } public int getLookupStart() { + LOG.assertTrue(myLookupStartMarker.isValid()); return myLookupStartMarker.getStartOffset(); } @@ -683,6 +684,8 @@ public class LookupImpl extends LightweightHint implements Lookup, Disposable { finally { myChangeGuard = false; } + LOG.assertTrue(!myDisposed, disposeTrace); + LOG.assertTrue(myLookupStartMarker.isValid()); if (isVisible()) { updateLookupBounds(); } From fcbf6ee55a94a591137b9e61b51dc3e3ff4668b0 Mon Sep 17 00:00:00 2001 From: peter Date: Tue, 5 Apr 2011 19:00:29 +0200 Subject: [PATCH 62/65] RecursionManager javadoc --- .../intellij/openapi/util/RecursionGuard.java | 44 ++++++++++++++++++- .../openapi/util/RecursionManager.java | 20 +++++++++ 2 files changed, 63 insertions(+), 1 deletion(-) diff --git a/platform/platform-api/src/com/intellij/openapi/util/RecursionGuard.java b/platform/platform-api/src/com/intellij/openapi/util/RecursionGuard.java index bcfa3415ced4..8910afb0323f 100644 --- a/platform/platform-api/src/com/intellij/openapi/util/RecursionGuard.java +++ b/platform/platform-api/src/com/intellij/openapi/util/RecursionGuard.java @@ -20,19 +20,61 @@ import org.jetbrains.annotations.Nullable; import java.util.List; /** -* @author peter + * A helper object for {@link RecursionManager}. Is obtained from {@link RecursionManager#createGuard(String)}. + * + * @author peter */ public interface RecursionGuard { + + /** + * @param key an id of the computation. Is stored internally to ensure that a recursive calls with the same key won't lead to endless recursion. + * @param computation a piece of code to compute. + * @return the result of the computation or null if we're entering a computation with this key on this thread recursively, + */ @Nullable T doPreventingRecursion(Object key, Computable computation); + /** + * Used in pair with {@link com.intellij.openapi.util.RecursionGuard.StackStamp#mayCacheNow()} to ensure that cached are only the reliable values, + * not depending on anything incomplete due to recursive prevention policies. + * A typical usage is this: + * + * RecursionGuard.StackStamp stamp = RecursionManager.createGuard("id").markStack(); + * + * Result result = doComputation(); + * + * if (stamp.mayCacheNow()) { + * cache(result); + * } + * return result; + * + + * @return an object representing the current stack state, managed by {@link RecursionManager} + */ StackStamp markStack(); + /** + * @return the current thread-local stack of keys passed to {@link #doPreventingRecursion(Object, Computable)} + */ List currentStack(); + /** + * Makes {@link com.intellij.openapi.util.RecursionGuard.StackStamp#mayCacheNow()} return false for all stamps created since a computation with + * key since began. + * + * Used to prevent caching of results that are non-reliable NOT due to recursion prevention: for example, too deep recursion + * ({@link #currentStack()} may help in determining the recursion depth) + * + * @param since the id of a computation whose result is safe to cache whilst for more nested ones it's not. + */ void prohibitResultCaching(Object since); interface StackStamp { + + /** + * @return whether a computation that started at the moment of this {@link StackStamp} instance creation does not depend on any re-entrant recursive + * results. When such non-reliable results exist in the thread's call stack, returns false, otherwise true + */ boolean mayCacheNow(); } } diff --git a/platform/platform-api/src/com/intellij/openapi/util/RecursionManager.java b/platform/platform-api/src/com/intellij/openapi/util/RecursionManager.java index ce4d7ce92d24..25a035c9144f 100644 --- a/platform/platform-api/src/com/intellij/openapi/util/RecursionManager.java +++ b/platform/platform-api/src/com/intellij/openapi/util/RecursionManager.java @@ -21,6 +21,22 @@ import java.util.List; import java.util.Map; /** + * There are moments when a computation A requires the result of computation B, which in turn requires C, which (unexpectedly) requires A. + * If there are no other ways to solve it, it helps to track all the computations in the thread stack and return some default value when + * asked to compute A for the second time. {@link RecursionGuard#doPreventingRecursion(Object, Computable)} does precisely this. + * + * It's quite useful to cache some computation results to avoid performance problems. But not everyone realises that in the above situation it's + * incorrect to cache the results of B and C, because they all are based on the default incomplete result of the A calculation. If the actual + * computation sequence were C->A->B->C, the result of the outer C most probably wouldn't be the same as in A->B->C->A, where it depends on + * the null A result directly. The natural wish is that the program with cache enabled has the same results as the one without cache. In the above + * situation the result of C would depend on the order of invocations of C and A, which can be hardly predictable in multithreaded environments. + * + * Therefore if you use any kind of cache, it probably would make your program safer to cache only when it's safe to do this. See + * {@link com.intellij.openapi.util.RecursionGuard#markStack()} and {@link com.intellij.openapi.util.RecursionGuard.StackStamp#mayCacheNow()} + * for the advice. + * + * @see RecursionGuard + * @see RecursionGuard.StackStamp * @author peter */ @SuppressWarnings({"UtilityClassWithoutPrivateConstructor"}) @@ -38,6 +54,10 @@ public class RecursionManager { } }; + /** + * @param id just some string to separate different recursion prevention policies from each other + * @return a helper object which allow you to perform reentrancy-safe computations and check whether caching will be safe. + */ public static RecursionGuard createGuard(final String id) { return new RecursionGuard() { @Override From fc0fcbc1166a2c2a67a371bf5e13a76d2d6a9a0d Mon Sep 17 00:00:00 2001 From: peter Date: Tue, 5 Apr 2011 20:42:18 +0200 Subject: [PATCH 63/65] suggest class names when typing a new groovy field type in lowercase --- .../completion/GroovyCompletionContributor.java | 13 +++++++------ .../lang/completion/GroovyCompletionUtil.java | 10 +++++++++- .../filters/modifiers/ModifiersFilter.java | 2 +- .../groovy/completion/GroovyAutoPopupTest.groovy | 6 ++++++ 4 files changed, 23 insertions(+), 8 deletions(-) diff --git a/plugins/groovy/src/org/jetbrains/plugins/groovy/lang/completion/GroovyCompletionContributor.java b/plugins/groovy/src/org/jetbrains/plugins/groovy/lang/completion/GroovyCompletionContributor.java index ae429f5cb945..a6146234abc5 100644 --- a/plugins/groovy/src/org/jetbrains/plugins/groovy/lang/completion/GroovyCompletionContributor.java +++ b/plugins/groovy/src/org/jetbrains/plugins/groovy/lang/completion/GroovyCompletionContributor.java @@ -47,6 +47,7 @@ import org.jetbrains.plugins.groovy.lang.lexer.TokenSets; import org.jetbrains.plugins.groovy.lang.parser.GroovyElementTypes; import org.jetbrains.plugins.groovy.lang.psi.GrReferenceElement; import org.jetbrains.plugins.groovy.lang.psi.GroovyFile; +import org.jetbrains.plugins.groovy.lang.psi.GroovyPsiElement; import org.jetbrains.plugins.groovy.lang.psi.api.GroovyResolveResult; import org.jetbrains.plugins.groovy.lang.psi.api.statements.*; import org.jetbrains.plugins.groovy.lang.psi.api.statements.blocks.GrClosableBlock; @@ -271,18 +272,18 @@ public class GroovyCompletionContributor extends CompletionContributor { ProcessingContext context, @NotNull final CompletionResultSet result) { PsiElement position = parameters.getPosition(); - final PsiElement reference = position.getParent(); - if (reference instanceof GrReferenceElement) { - if (reference.getParent() instanceof GrImportStatement && ((GrReferenceElement)reference).getQualifier() != null) { + final PsiElement parent = position.getParent(); + if (parent instanceof GrReferenceElement) { + if (parent.getParent() instanceof GrImportStatement && ((GrReferenceElement)parent).getQualifier() != null) { result.addElement(LookupElementBuilder.create("*")); } addKeywords(parameters, result); - completeReference(parameters, result, (GrReferenceElement)reference); + completeReference(parameters, result, (GrReferenceElement)parent); } else if (IN_CATCH_TYPE.accepts(position) || AFTER_AT.accepts(position)) { addAllClasses(parameters, result, new InheritorsHolder(position, result)); - } else if (GroovyCompletionUtil.isFirstElementAfterModifiersInVariableDeclaration(position, true)) { + } else if (GroovyCompletionUtil.isFirstElementAfterPossibleModifiersInVariableDeclaration(position, true)) { addDeclarationTypes(result, position); } } @@ -292,7 +293,7 @@ public class GroovyCompletionContributor extends CompletionContributor { private static void addDeclarationTypes(CompletionResultSet result, PsiElement position) { ResolverProcessor processor = CompletionProcessor.createClassCompletionProcessor(position); - ResolveUtil.treeWalkUp((GrVariable)position.getParent(), processor, false); + ResolveUtil.treeWalkUp((GroovyPsiElement)position.getParent(), processor, false); for (Object variant : GroovyCompletionUtil.getCompletionVariants(processor.getCandidates())) { if (variant instanceof LookupElement) { diff --git a/plugins/groovy/src/org/jetbrains/plugins/groovy/lang/completion/GroovyCompletionUtil.java b/plugins/groovy/src/org/jetbrains/plugins/groovy/lang/completion/GroovyCompletionUtil.java index 097b78d6b8ca..bb1dfb092112 100644 --- a/plugins/groovy/src/org/jetbrains/plugins/groovy/lang/completion/GroovyCompletionUtil.java +++ b/plugins/groovy/src/org/jetbrains/plugins/groovy/lang/completion/GroovyCompletionUtil.java @@ -42,6 +42,7 @@ import com.intellij.psi.util.TypeConversionUtil; import com.intellij.util.Function; import com.intellij.util.IncorrectOperationException; import com.intellij.util.containers.CollectionFactory; +import com.intellij.util.text.CharArrayUtil; import org.jetbrains.annotations.NonNls; import org.jetbrains.annotations.Nullable; import org.jetbrains.plugins.groovy.GroovyFileType; @@ -140,7 +141,14 @@ public class GroovyCompletionUtil { /** * return true, if the element is first element after modifiers and there is no type element */ - public static boolean isFirstElementAfterModifiersInVariableDeclaration(PsiElement element, boolean acceptParameter) { + public static boolean isFirstElementAfterPossibleModifiersInVariableDeclaration(PsiElement element, boolean acceptParameter) { + if (element.getParent() instanceof GrTypeDefinitionBody) { + //is first on the line? + String text = element.getContainingFile().getText(); + int i = CharArrayUtil.shiftBackward(text, element.getTextRange().getStartOffset() - 1, " \t"); + return i >= 0 && (text.charAt(i) == '\n' || text.charAt(i) == '{'); + } + final PsiElement parent = element.getParent(); if (!(parent instanceof GrVariable)) return false; diff --git a/plugins/groovy/src/org/jetbrains/plugins/groovy/lang/completion/filters/modifiers/ModifiersFilter.java b/plugins/groovy/src/org/jetbrains/plugins/groovy/lang/completion/filters/modifiers/ModifiersFilter.java index 9b4b059c3b2d..f6e0e44963e1 100644 --- a/plugins/groovy/src/org/jetbrains/plugins/groovy/lang/completion/filters/modifiers/ModifiersFilter.java +++ b/plugins/groovy/src/org/jetbrains/plugins/groovy/lang/completion/filters/modifiers/ModifiersFilter.java @@ -40,7 +40,7 @@ public class ModifiersFilter implements ElementFilter { if (GroovyCompletionUtil.asSimpleVariable(context) || GroovyCompletionUtil.asTypedMethod(context)) { return true; } - if (GroovyCompletionUtil.isFirstElementAfterModifiersInVariableDeclaration(context, false)) { + if (GroovyCompletionUtil.isFirstElementAfterPossibleModifiersInVariableDeclaration(context, false)) { return true; } final PsiElement contextParent = context.getParent(); diff --git a/plugins/groovy/test/org/jetbrains/plugins/groovy/completion/GroovyAutoPopupTest.groovy b/plugins/groovy/test/org/jetbrains/plugins/groovy/completion/GroovyAutoPopupTest.groovy index 5dcc6ce5136d..b533e24f6cda 100644 --- a/plugins/groovy/test/org/jetbrains/plugins/groovy/completion/GroovyAutoPopupTest.groovy +++ b/plugins/groovy/test/org/jetbrains/plugins/groovy/completion/GroovyAutoPopupTest.groovy @@ -89,4 +89,10 @@ class GroovyAutoPopupTest extends CompletionAutoPopupTestCase { assert lookup.focused } + public void testFieldTypeLowercase() { + myFixture.configureByText "a.groovy", "class Foo { }" + type 'aioobe' + assert myFixture.lookupElementStrings == [ArrayIndexOutOfBoundsException.simpleName] + } + } From 6ae83662cfc068a98afae519c9da5694e69679de Mon Sep 17 00:00:00 2001 From: peter Date: Tue, 5 Apr 2011 21:38:06 +0200 Subject: [PATCH 64/65] the non-green completion items were sorted by proximity in the wrong direction (IDEA-67349) --- .../SortSameNamedVariantsByProximity.java | 9 ++++ .../NormalCompletionOrderingTest.java | 16 +++++++ .../LookupElementProximityWeigher.java | 13 ++++-- .../impl/CompletionServiceImpl.java | 24 ----------- .../completion/impl/NegatingComparable.java | 43 +++++++++++++++++++ .../src/META-INF/LangExtensions.xml | 2 +- 6 files changed, 78 insertions(+), 29 deletions(-) create mode 100644 java/java-tests/testData/codeInsight/completion/normalSorting/SortSameNamedVariantsByProximity.java create mode 100644 platform/lang-impl/src/com/intellij/codeInsight/completion/impl/NegatingComparable.java diff --git a/java/java-tests/testData/codeInsight/completion/normalSorting/SortSameNamedVariantsByProximity.java b/java/java-tests/testData/codeInsight/completion/normalSorting/SortSameNamedVariantsByProximity.java new file mode 100644 index 000000000000..6b1078a9d0b8 --- /dev/null +++ b/java/java-tests/testData/codeInsight/completion/normalSorting/SortSameNamedVariantsByProximity.java @@ -0,0 +1,9 @@ +import sun.swing.BakedArrayList; + +class Foo { + { + Object element; + if (element instanceof bar) + } + +} \ No newline at end of file diff --git a/java/java-tests/testSrc/com/intellij/codeInsight/completion/NormalCompletionOrderingTest.java b/java/java-tests/testSrc/com/intellij/codeInsight/completion/NormalCompletionOrderingTest.java index 08265d07ef4e..01d60d2af9c2 100644 --- a/java/java-tests/testSrc/com/intellij/codeInsight/completion/NormalCompletionOrderingTest.java +++ b/java/java-tests/testSrc/com/intellij/codeInsight/completion/NormalCompletionOrderingTest.java @@ -217,4 +217,20 @@ public class NormalCompletionOrderingTest extends CompletionSortingTestCase { checkPreferredItems(0, "Bar9", "Bar1", "Bar2", "Bar3", "Bar4"); } + public void testSortSameNamedVariantsByProximity() { + myFixture.addClass("public class Bar {}"); + for (int i = 0; i < 10; i++) { + myFixture.addClass("public class Bar" + i + " {}"); + myFixture.addClass("public class Bar" + i + "Colleague {}"); + } + myFixture.addClass("package bar; public class Bar {}"); + final String path = getTestName(false) + ".java"; + myFixture.configureByFile(getTestName(false) + ".java"); + myFixture.complete(CompletionType.BASIC, 2); + assertPreferredItems(0); + List items = getLookup().getItems(); + assertEquals(((JavaPsiClassReferenceElement)items.get(0)).getQualifiedName(), "Bar"); + assertEquals(((JavaPsiClassReferenceElement)items.get(1)).getQualifiedName(), "bar.Bar"); + } + } diff --git a/platform/lang-impl/src/com/intellij/codeInsight/completion/LookupElementProximityWeigher.java b/platform/lang-impl/src/com/intellij/codeInsight/completion/LookupElementProximityWeigher.java index 7632bebc0f42..0423d04e9bd3 100644 --- a/platform/lang-impl/src/com/intellij/codeInsight/completion/LookupElementProximityWeigher.java +++ b/platform/lang-impl/src/com/intellij/codeInsight/completion/LookupElementProximityWeigher.java @@ -15,11 +15,11 @@ */ package com.intellij.codeInsight.completion; +import com.intellij.codeInsight.completion.impl.NegatingComparable; import com.intellij.codeInsight.lookup.LookupElement; import com.intellij.psi.PsiElement; import com.intellij.psi.util.proximity.PsiProximityComparator; import org.jetbrains.annotations.NotNull; -import org.jetbrains.annotations.Nullable; /** * @author peter @@ -27,13 +27,18 @@ import org.jetbrains.annotations.Nullable; public class LookupElementProximityWeigher extends CompletionWeigher { public Comparable weigh(@NotNull final LookupElement item, @NotNull final CompletionLocation location) { - if (location == null) { - return null; - } final Object o = item.getObject(); if (o instanceof PsiElement) { return PsiProximityComparator.getProximity((PsiElement)o, location.getCompletionParameters().getPosition(), location.getProcessingContext()); } return null; } + + public static class Negative extends LookupElementProximityWeigher { + @Override + public Comparable weigh(@NotNull LookupElement element, @NotNull CompletionLocation location) { + return new NegatingComparable(super.weigh(element, location)); + } + } + } diff --git a/platform/lang-impl/src/com/intellij/codeInsight/completion/impl/CompletionServiceImpl.java b/platform/lang-impl/src/com/intellij/codeInsight/completion/impl/CompletionServiceImpl.java index db77113140fc..41f28dcbb42f 100644 --- a/platform/lang-impl/src/com/intellij/codeInsight/completion/impl/CompletionServiceImpl.java +++ b/platform/lang-impl/src/com/intellij/codeInsight/completion/impl/CompletionServiceImpl.java @@ -292,28 +292,4 @@ public class CompletionServiceImpl extends CompletionService{ public CompletionSorterImpl emptySorter() { return new CompletionSorterImpl(new ArrayList>()); } - - private static class NegatingComparable> implements Comparable { - private final Comparable myWeigh; - - public NegatingComparable(Comparable weigh) { - myWeigh = weigh; - } - - @Override - public int compareTo(T o) { - final Comparable w1 = myWeigh; - final Comparable w2 = o.myWeigh; - if (w1 == null && w2 == null) return 0; - if (w1 == null) return 1; - if (w2 == null) return -1; - - return -w1.compareTo(w2); - } - - @Override - public String toString() { - return String.valueOf(myWeigh); - } - } } diff --git a/platform/lang-impl/src/com/intellij/codeInsight/completion/impl/NegatingComparable.java b/platform/lang-impl/src/com/intellij/codeInsight/completion/impl/NegatingComparable.java new file mode 100644 index 000000000000..36f02aa13dd8 --- /dev/null +++ b/platform/lang-impl/src/com/intellij/codeInsight/completion/impl/NegatingComparable.java @@ -0,0 +1,43 @@ +/* + * Copyright 2000-2011 JetBrains s.r.o. + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ +package com.intellij.codeInsight.completion.impl; + +/** +* @author peter +*/ +public class NegatingComparable> implements Comparable { + private final Comparable myWeigh; + + public NegatingComparable(Comparable weigh) { + myWeigh = weigh; + } + + @Override + public int compareTo(T o) { + final Comparable w1 = myWeigh; + final Comparable w2 = o.myWeigh; + if (w1 == null && w2 == null) return 0; + if (w1 == null) return 1; + if (w2 == null) return -1; + + return -w1.compareTo(w2); + } + + @Override + public String toString() { + return String.valueOf(myWeigh); + } +} diff --git a/platform/platform-resources/src/META-INF/LangExtensions.xml b/platform/platform-resources/src/META-INF/LangExtensions.xml index a5c953e1988c..b74d5e3e7830 100644 --- a/platform/platform-resources/src/META-INF/LangExtensions.xml +++ b/platform/platform-resources/src/META-INF/LangExtensions.xml @@ -381,7 +381,7 @@ - + From 8d12f07a6aea3d0efb279aa621ab6722f70a28a3 Mon Sep 17 00:00:00 2001 From: peter Date: Wed, 6 Apr 2011 12:57:22 +0200 Subject: [PATCH 65/65] fix some empty stack exceptions during dfa analysis --- .../dataFlow/ControlFlowAnalyzer.java | 3 ++- .../codeInspection/dataFlow/DataFlowRunner.java | 3 ++- .../instructions/MethodCallInstruction.java | 2 +- .../completion/normal/OrAssignmentDfa.java | 17 +++++++++++++++++ .../normal/OrAssignmentDfa_after.java | 17 +++++++++++++++++ .../completion/NormalCompletionTest.groovy | 2 ++ 6 files changed, 41 insertions(+), 3 deletions(-) create mode 100644 java/java-tests/testData/codeInsight/completion/normal/OrAssignmentDfa.java create mode 100644 java/java-tests/testData/codeInsight/completion/normal/OrAssignmentDfa_after.java diff --git a/java/java-impl/src/com/intellij/codeInspection/dataFlow/ControlFlowAnalyzer.java b/java/java-impl/src/com/intellij/codeInspection/dataFlow/ControlFlowAnalyzer.java index cf03fa2c32f9..6bca3124730d 100644 --- a/java/java-impl/src/com/intellij/codeInspection/dataFlow/ControlFlowAnalyzer.java +++ b/java/java-impl/src/com/intellij/codeInspection/dataFlow/ControlFlowAnalyzer.java @@ -532,9 +532,10 @@ class ControlFlowAnalyzer extends JavaElementVisitor { generateBoxingUnboxingInstructionFor(caseExpression, PsiType.INT); if (TypeConversionUtil.isEnumType(caseExpression.getType())) { addInstruction(new FieldReferenceInstruction(caseExpression, "switch statement expression")); + } else { + addInstruction(new PopInstruction()); } - addInstruction(new PopInstruction()); } PsiCodeBlock body = switchStmt.getBody(); diff --git a/java/java-impl/src/com/intellij/codeInspection/dataFlow/DataFlowRunner.java b/java/java-impl/src/com/intellij/codeInspection/dataFlow/DataFlowRunner.java index 0a50f444b59b..3e27932031b3 100644 --- a/java/java-impl/src/com/intellij/codeInspection/dataFlow/DataFlowRunner.java +++ b/java/java-impl/src/com/intellij/codeInspection/dataFlow/DataFlowRunner.java @@ -161,7 +161,8 @@ public class DataFlowRunner { LOG.error(psiBlock.getText(), e); /* TODO[max] !!! hack (of 18186). Please fix in better times. */ return RunnerResult.ABORTED; } - catch (EmptyStackException e) /* TODO[max] !!! hack (of 18186). Please fix in better times. */ { + catch (EmptyStackException e) { + //LOG.error(psiBlock.getText(), e); /* TODO[max] !!! hack (of 18186). Please fix in better times. */ return RunnerResult.ABORTED; } } diff --git a/java/java-impl/src/com/intellij/codeInspection/dataFlow/instructions/MethodCallInstruction.java b/java/java-impl/src/com/intellij/codeInspection/dataFlow/instructions/MethodCallInstruction.java index 51c6dee10de0..079e0f0ba4e9 100644 --- a/java/java-impl/src/com/intellij/codeInspection/dataFlow/instructions/MethodCallInstruction.java +++ b/java/java-impl/src/com/intellij/codeInspection/dataFlow/instructions/MethodCallInstruction.java @@ -57,7 +57,7 @@ public class MethodCallInstruction extends Instruction { public MethodCallInstruction(@NotNull PsiExpression context, MethodType methodType) { myContext = context; myMethodType = methodType; - myCall = context instanceof PsiCallExpression ? (PsiCallExpression)context : null; + myCall = methodType == MethodType.REGULAR_METHOD_CALL && context instanceof PsiCallExpression ? (PsiCallExpression)context : null; final PsiExpressionList argList = myCall == null ? null : myCall.getArgumentList(); myArgs = argList != null ? argList.getExpressions() : PsiExpression.EMPTY_ARRAY; diff --git a/java/java-tests/testData/codeInsight/completion/normal/OrAssignmentDfa.java b/java/java-tests/testData/codeInsight/completion/normal/OrAssignmentDfa.java new file mode 100644 index 000000000000..48fab97edaa3 --- /dev/null +++ b/java/java-tests/testData/codeInsight/completion/normal/OrAssignmentDfa.java @@ -0,0 +1,17 @@ +class Foo { + + boolean foo(Object o, final PairFunction fun){ + boolean result = true; + result |= fun.fun(path); + if (o instanceof String) { + o.subst + } + } + + void foo(String s) {} +} + +interface PairFunction { + U fun(T t, V v); + +} diff --git a/java/java-tests/testData/codeInsight/completion/normal/OrAssignmentDfa_after.java b/java/java-tests/testData/codeInsight/completion/normal/OrAssignmentDfa_after.java new file mode 100644 index 000000000000..cecc36797b06 --- /dev/null +++ b/java/java-tests/testData/codeInsight/completion/normal/OrAssignmentDfa_after.java @@ -0,0 +1,17 @@ +class Foo { + + boolean foo(Object o, final PairFunction fun){ + boolean result = true; + result |= fun.fun(path); + if (o instanceof String) { + ((String) o).substring() + } + } + + void foo(String s) {} +} + +interface PairFunction { + U fun(T t, V v); + +} diff --git a/java/java-tests/testSrc/com/intellij/codeInsight/completion/NormalCompletionTest.groovy b/java/java-tests/testSrc/com/intellij/codeInsight/completion/NormalCompletionTest.groovy index 4677a94efca2..ce92618fb7dc 100644 --- a/java/java-tests/testSrc/com/intellij/codeInsight/completion/NormalCompletionTest.groovy +++ b/java/java-tests/testSrc/com/intellij/codeInsight/completion/NormalCompletionTest.groovy @@ -809,6 +809,8 @@ public class NormalCompletionTest extends LightFixtureCompletionTestCase { public void testQualifierCastingWithUnknownAssignments() throws Throwable { doTest(); } public void testQualifierCastingBeforeLt() throws Throwable { doTest(); } + public void testOrAssignmentDfa() throws Throwable { doTest(); } + public void testWildcardsInLookup() throws Exception { configure() assertNotNull(getLookup());