diff --git a/.idea/libraries/Guava.xml b/.idea/libraries/Guava.xml index fe0defcc233e..3024d55693eb 100644 --- a/.idea/libraries/Guava.xml +++ b/.idea/libraries/Guava.xml @@ -1,11 +1,11 @@ - + - + \ No newline at end of file diff --git a/java/java-impl/src/com/intellij/codeInsight/completion/JavaGlobalMemberLookupElement.java b/java/java-impl/src/com/intellij/codeInsight/completion/JavaGlobalMemberLookupElement.java index aaa79fdaf40e..91c2aa8e5c59 100644 --- a/java/java-impl/src/com/intellij/codeInsight/completion/JavaGlobalMemberLookupElement.java +++ b/java/java-impl/src/com/intellij/codeInsight/completion/JavaGlobalMemberLookupElement.java @@ -65,7 +65,7 @@ public class JavaGlobalMemberLookupElement extends LookupElement implements Stat @Override public void renderElement(LookupElementPresentation presentation) { presentation.setIcon(DefaultLookupItemRenderer.getRawIcon(this, presentation.isReal())); - myHelper.renderElement(presentation, false, PsiSubstitutor.EMPTY); + myHelper.renderElement(presentation, null, PsiSubstitutor.EMPTY); } @Override diff --git a/java/java-impl/src/com/intellij/ide/projectView/impl/nodes/PackageViewLibrariesNode.java b/java/java-impl/src/com/intellij/ide/projectView/impl/nodes/PackageViewLibrariesNode.java index d0358681dc74..8fdbf10563a6 100644 --- a/java/java-impl/src/com/intellij/ide/projectView/impl/nodes/PackageViewLibrariesNode.java +++ b/java/java-impl/src/com/intellij/ide/projectView/impl/nodes/PackageViewLibrariesNode.java @@ -41,7 +41,10 @@ public class PackageViewLibrariesNode extends ProjectViewNode{ } public boolean contains(@NotNull final VirtualFile file) { - return someChildContainsFile(file); + ProjectFileIndex index = ProjectRootManager.getInstance(getProject()).getFileIndex(); + if (!index.isInLibrarySource(file) && !index.isInLibraryClasses(file)) return false; + + return someChildContainsFile(file, false); } @NotNull diff --git a/java/java-impl/src/com/intellij/refactoring/introduceField/InplaceIntroduceConstantPopup.java b/java/java-impl/src/com/intellij/refactoring/introduceField/InplaceIntroduceConstantPopup.java index a2ab7301809a..1d0f6672106b 100644 --- a/java/java-impl/src/com/intellij/refactoring/introduceField/InplaceIntroduceConstantPopup.java +++ b/java/java-impl/src/com/intellij/refactoring/introduceField/InplaceIntroduceConstantPopup.java @@ -19,7 +19,13 @@ import com.intellij.codeInsight.AnnotationUtil; import com.intellij.codeInsight.intention.impl.TypeExpression; import com.intellij.codeInsight.template.impl.TemplateManagerImpl; import com.intellij.codeInsight.template.impl.TemplateState; +import com.intellij.ide.ui.ListCellRendererWrapper; +import com.intellij.ide.ui.UISettings; import com.intellij.ide.util.PropertiesComponent; +import com.intellij.openapi.actionSystem.AnAction; +import com.intellij.openapi.actionSystem.AnActionEvent; +import com.intellij.openapi.actionSystem.CustomShortcutSet; +import com.intellij.openapi.actionSystem.KeyboardShortcut; import com.intellij.openapi.application.ApplicationManager; import com.intellij.openapi.command.CommandProcessor; import com.intellij.openapi.editor.Editor; @@ -28,6 +34,7 @@ import com.intellij.openapi.editor.ScrollType; import com.intellij.openapi.project.Project; import com.intellij.openapi.roots.LanguageLevelProjectExtension; import com.intellij.openapi.util.Computable; +import com.intellij.openapi.wm.ToolWindowManager; import com.intellij.psi.*; import com.intellij.psi.codeStyle.JavaCodeStyleManager; import com.intellij.psi.codeStyle.VariableKind; @@ -42,11 +49,11 @@ import com.intellij.refactoring.ui.TypeSelectorManagerImpl; import com.intellij.refactoring.util.occurences.OccurenceManager; import com.intellij.ui.StateRestoringCheckBox; import com.intellij.ui.TitlePanel; +import com.intellij.util.VisibilityUtil; import javax.swing.*; import java.awt.*; -import java.awt.event.ItemEvent; -import java.awt.event.ItemListener; +import java.awt.event.*; import java.util.ArrayList; import java.util.Arrays; import java.util.LinkedHashSet; @@ -83,7 +90,7 @@ public class InplaceIntroduceConstantPopup { private JCheckBox myMoveToAnotherClassCb; - private JavaVisibilityPanel myVisibilityPanel; + private JComboBox myVisibilityCombo; private JPanel myWholePanel; @@ -122,31 +129,36 @@ public class InplaceIntroduceConstantPopup { myLocalName = localVariable != null ? localVariable.getName() : null; myWholePanel = new JPanel(new GridBagLayout()); - GridBagConstraints gc = new GridBagConstraints(0, GridBagConstraints.RELATIVE, 1, 1, 1, 0, GridBagConstraints.NORTHWEST, GridBagConstraints.HORIZONTAL, new Insets(0, 0 , 0, 0), 0, 0); + GridBagConstraints gc = new GridBagConstraints(0, 0, 1, 1, 1, 0, GridBagConstraints.NORTHWEST, GridBagConstraints.HORIZONTAL, new Insets(0, 0 , 0, 0), 0, 0); final TitlePanel titlePanel = new TitlePanel(); titlePanel.setBorder(null); titlePanel.setText(IntroduceConstantHandler.REFACTORING_NAME); - + gc.gridwidth = 2; myWholePanel.add(titlePanel, gc); - gc.insets = new Insets(5, 5, 5, 5); + gc.gridwidth = 1; + gc.gridy = 1; + myWholePanel.add(createLeftPanel(), gc); - myVisibilityPanel = new JavaVisibilityPanel(false, false); - myVisibilityPanel.setVisibility(JavaRefactoringSettings.getInstance().INTRODUCE_CONSTANT_VISIBILITY); - myWholePanel.add(myVisibilityPanel, gc); + gc.gridx = 1; + gc.insets.left = 6; + myWholePanel.add(createRightPanel(), gc); + } + + private JPanel createRightPanel() { + final JPanel right = new JPanel(new GridBagLayout()); + final GridBagConstraints rgc = new GridBagConstraints(0, GridBagConstraints.RELATIVE,1,1,0,0, GridBagConstraints.NORTHWEST, GridBagConstraints.HORIZONTAL, new Insets(1,0,0,0), 0, 0); myReplaceAllCb = new JCheckBox("Replace all occurrences"); myReplaceAllCb.setMnemonic('a'); myReplaceAllCb.setFocusable(false); - myWholePanel.add(myReplaceAllCb, gc); myReplaceAllCb.setVisible(myOccurrences.length > 1); - + right.add(myReplaceAllCb, rgc); myCbDeleteVariable = new StateRestoringCheckBox("Delete variable declaration"); myCbDeleteVariable.setMnemonic('d'); myCbDeleteVariable.setFocusable(false); - myWholePanel.add(myCbDeleteVariable, gc); if (myLocalVariable != null) { if (myReplaceAllCb != null) { myReplaceAllCb.setEnabled(false); @@ -157,15 +169,15 @@ public class InplaceIntroduceConstantPopup { } else { myCbDeleteVariable.setVisible(false); } + right.add(myCbDeleteVariable, rgc); myAnnotateNonNls = new JCheckBox("Annotate field as @NonNls"); myAnnotateNonNls.setMnemonic('f'); myAnnotateNonNls.setFocusable(false); - myWholePanel.add(myAnnotateNonNls, gc); - final PsiManager psiManager = PsiManager.getInstance(myProject); - if ((myTypeSelectorManager.isSuggestedType("java.lang.String") || (myLocalVariable != null && AnnotationUtil.isAnnotated(myLocalVariable, AnnotationUtil.NON_NLS, false)))&& - LanguageLevelProjectExtension.getInstance(psiManager.getProject()).getLanguageLevel().hasEnumKeywordAndAutoboxing() && - JavaPsiFacade.getInstance(psiManager.getProject()).findClass(AnnotationUtil.NON_NLS, myParentClass.getResolveScope()) != null) { + if ((myTypeSelectorManager.isSuggestedType("java.lang.String") || (myLocalVariable != null && AnnotationUtil + .isAnnotated(myLocalVariable, AnnotationUtil.NON_NLS, false)))&& + LanguageLevelProjectExtension.getInstance(myProject).getLanguageLevel().hasEnumKeywordAndAutoboxing() && + JavaPsiFacade.getInstance(myProject).findClass(AnnotationUtil.NON_NLS, myParentClass.getResolveScope()) != null) { final PropertiesComponent component = PropertiesComponent.getInstance(myProject); myAnnotateNonNls.setSelected(component.isTrueValue(IntroduceConstantDialog.NONNLS_SELECTED_PROPERTY)); myAnnotateNonNls.addItemListener(new ItemListener() { @@ -176,13 +188,69 @@ public class InplaceIntroduceConstantPopup { } else { myAnnotateNonNls.setVisible(false); } + right.add(myAnnotateNonNls, rgc); + return right; + } + + private JPanel createLeftPanel() { + final JPanel left = new JPanel(new GridBagLayout()); + final GridBagConstraints lgc = new GridBagConstraints(0, 0, 1, 1, 0, 0, GridBagConstraints.NORTHWEST, GridBagConstraints.HORIZONTAL, new Insets(5,5,0,0), 0, 0); + + final JLabel label = new JLabel("Visibility:"); + label.setDisplayedMnemonic('V'); + left.add(label, lgc); + myVisibilityCombo = new JComboBox(new String[]{PsiModifier.PUBLIC, PsiModifier.PACKAGE_LOCAL, PsiModifier.PROTECTED, PsiModifier.PRIVATE}); + myVisibilityCombo.setRenderer(new ListCellRendererWrapper(myVisibilityCombo.getRenderer()){ + @Override + public void customize(JList list, String value, int index, boolean selected, boolean hasFocus) { + setText(PsiBundle.visibilityPresentation(value)); + } + }); + label.setLabelFor(myVisibilityCombo); + myVisibilityCombo.setSelectedItem(JavaRefactoringSettings.getInstance().INTRODUCE_CONSTANT_VISIBILITY); + myVisibilityCombo.addKeyListener(new KeyAdapter() { + @Override + public void keyReleased(KeyEvent e) { + if (e.getKeyCode() == KeyEvent.VK_ESCAPE) { + ToolWindowManager.getInstance(myProject).activateEditorComponent(); + } + } + }); + final AnAction arrow = new AnAction() { + @Override + public void actionPerformed(AnActionEvent e) { + if (e.getInputEvent() instanceof KeyEvent) { + final int code = ((KeyEvent)e.getInputEvent()).getKeyCode(); + final int delta = code == KeyEvent.VK_DOWN ? 1 : code == KeyEvent.VK_UP ? -1 : 0; + if (delta == 0) return; + final int size = myVisibilityCombo.getModel().getSize(); + int next = myVisibilityCombo.getSelectedIndex() + delta; + if (next < 0 || next >= size) { + if (!UISettings.getInstance().CYCLE_SCROLLING) { + return; + } + next = (next + size) % size; + } + myVisibilityCombo.setSelectedIndex(next); + } + } + }; + arrow.registerCustomShortcutSet(new CustomShortcutSet(new KeyboardShortcut(KeyStroke.getKeyStroke(KeyEvent.VK_UP, 0), null), + new KeyboardShortcut(KeyStroke.getKeyStroke(KeyEvent.VK_DOWN, 0), null)), myVisibilityCombo); + lgc.gridx = 1; + lgc.insets.top = 2; + lgc.insets.left = 0; + left.add(myVisibilityCombo, lgc); myMoveToAnotherClassCb = new JCheckBox("Move to another class"); myMoveToAnotherClassCb.setMnemonic('m'); myMoveToAnotherClassCb.setFocusable(false); - myWholePanel.add(myMoveToAnotherClassCb, gc); - - + lgc.gridx = 0; + lgc.gridy = 1; + lgc.gridwidth = 2; + lgc.insets.top = 0; + left.add(myMoveToAnotherClassCb, lgc); + return left; } public void performInplaceIntroduce() { @@ -220,7 +288,7 @@ public class InplaceIntroduceConstantPopup { PsiField field = elementFactory.createFieldFromText(psiType.getCanonicalText() + " " + (myConstantName != null ? myConstantName : names[0]) + " = " + myExprText + ";", myParentClass); PsiUtil.setModifierProperty(field, PsiModifier.FINAL, true); PsiUtil.setModifierProperty(field, PsiModifier.STATIC, true); - final String visibility = myVisibilityPanel.getVisibility(); + final String visibility = getSelectedVisibility(); if (visibility != null) { PsiUtil.setModifierProperty(field, visibility, true); } @@ -230,6 +298,10 @@ public class InplaceIntroduceConstantPopup { }); } + private String getSelectedVisibility() { + return (String)myVisibilityCombo.getSelectedItem(); + } + public List getOccurrenceMarkers() { if (myOccurrenceMarkers == null) { myOccurrenceMarkers = new ArrayList(); @@ -301,7 +373,7 @@ public class InplaceIntroduceConstantPopup { @Override protected void saveSettings(PsiVariable psiVariable) { TypeSelectorManagerImpl.typeSelected(psiVariable.getType(), myDefaultParameterTypePointer.getType()); - JavaRefactoringSettings.getInstance().INTRODUCE_CONSTANT_VISIBILITY = myVisibilityPanel.getVisibility(); + JavaRefactoringSettings.getInstance().INTRODUCE_CONSTANT_VISIBILITY = getSelectedVisibility(); } @Override @@ -321,7 +393,7 @@ public class InplaceIntroduceConstantPopup { isReplaceAllOccurrences(), true, true, BaseExpressionToFieldHandler.InitializationPlace.IN_FIELD_DECLARATION, - myVisibilityPanel.getVisibility(), myLocalVariable, + getSelectedVisibility(), myLocalVariable, myFieldTypePointer.getType(), isDeleteVariable(), myParentClass, isAnnotateNonNls(), false); @@ -358,10 +430,16 @@ public class InplaceIntroduceConstantPopup { protected JComponent getComponent() { if (!myInitListeners) { myInitListeners = true; - myVisibilityPanel.addListener(new VisibilityListener(myProject, myEditor){ + final VisibilityListener visibilityListener = new VisibilityListener(myProject, myEditor) { @Override protected String getVisibility() { - return myVisibilityPanel.getVisibility(); + return getSelectedVisibility(); + } + }; + myVisibilityCombo.addActionListener(new ActionListener() { + @Override + public void actionPerformed(ActionEvent e) { + visibilityListener.stateChanged(null); } }); myReplaceAllCb.addItemListener(new ItemListener() { diff --git a/lib/guava-r08.jar b/lib/guava-r08.jar deleted file mode 100644 index d18d0bdae1dc..000000000000 Binary files a/lib/guava-r08.jar and /dev/null differ diff --git a/lib/guava-r09.jar b/lib/guava-r09.jar new file mode 100644 index 000000000000..f8da8b1c1e81 Binary files /dev/null and b/lib/guava-r09.jar differ diff --git a/lib/required_for_dist.txt b/lib/required_for_dist.txt index 1d417dd64189..d16543be9c74 100644 --- a/lib/required_for_dist.txt +++ b/lib/required_for_dist.txt @@ -10,7 +10,7 @@ commons-logging-1.1.1.jar commons-net-2.0-patched.jar dtdparser113.jar groovy-all-1.7.3.jar -guava-r08.jar +guava-r09.jar jaxen-1.1.3.jar jcip-annotations.jar jdom.jar diff --git a/lib/src/guava-src-r08.zip b/lib/src/guava-src-r08.zip deleted file mode 100644 index 3ca29c2d28e6..000000000000 Binary files a/lib/src/guava-src-r08.zip and /dev/null differ diff --git a/lib/src/guava-src-r09.zip b/lib/src/guava-src-r09.zip new file mode 100644 index 000000000000..2bb76991e904 Binary files /dev/null and b/lib/src/guava-src-r09.zip differ diff --git a/platform/lang-api/src/com/intellij/ide/projectView/ProjectViewNode.java b/platform/lang-api/src/com/intellij/ide/projectView/ProjectViewNode.java index 8e48eb93f50f..ac094e1f4f1d 100644 --- a/platform/lang-api/src/com/intellij/ide/projectView/ProjectViewNode.java +++ b/platform/lang-api/src/com/intellij/ide/projectView/ProjectViewNode.java @@ -25,6 +25,7 @@ import com.intellij.openapi.vfs.VirtualFile; import com.intellij.problems.WolfTheProblemSolver; import com.intellij.psi.PsiElement; import com.intellij.psi.PsiFile; +import com.intellij.psi.PsiFileSystemItem; import com.intellij.psi.util.PsiUtilBase; import com.intellij.util.containers.HashSet; import org.jetbrains.annotations.NotNull; @@ -124,21 +125,29 @@ public abstract class ProjectViewNode extends AbstractTreeNode im } public boolean someChildContainsFile(final VirtualFile file) { + return someChildContainsFile(file, true); + } + + public boolean someChildContainsFile(final VirtualFile file, boolean optimizeByCheckingFileRootsFirst) { VirtualFile parent = file.getParent(); - if (parent == null) return false; boolean mayContain = false; - Collection roots = getRoots(); - for (VirtualFile eachRoot : roots) { - if (parent.equals(eachRoot.getParent())) { - mayContain = true; - break; - } - if (VfsUtil.isAncestor(eachRoot, file, true)) { - mayContain = true; - break; + if (optimizeByCheckingFileRootsFirst && parent != null) { + Collection roots = getRoots(); + for (VirtualFile eachRoot : roots) { + if (parent.equals(eachRoot.getParent())) { + mayContain = true; + break; + } + + if (VfsUtil.isAncestor(eachRoot, file, true)) { + mayContain = true; + break; + } } + } else { + mayContain = true; } if (!mayContain) { @@ -165,6 +174,8 @@ public abstract class ProjectViewNode extends AbstractTreeNode im } } else if (value instanceof VirtualFile) { return Collections.singleton(((VirtualFile)value)); + } else if (value instanceof PsiFileSystemItem) { + return Collections.singleton(((PsiFileSystemItem)value).getVirtualFile()); } return EMPTY_ROOTS; diff --git a/platform/lang-impl/src/com/intellij/application/options/codeStyle/OptionTableWithPreviewPanel.java b/platform/lang-impl/src/com/intellij/application/options/codeStyle/OptionTableWithPreviewPanel.java index 7a9f35224e6a..97289c509187 100644 --- a/platform/lang-impl/src/com/intellij/application/options/codeStyle/OptionTableWithPreviewPanel.java +++ b/platform/lang-impl/src/com/intellij/application/options/codeStyle/OptionTableWithPreviewPanel.java @@ -21,6 +21,7 @@ import com.intellij.psi.PsiFile; import com.intellij.psi.codeStyle.CodeStyleSettings; import com.intellij.psi.codeStyle.CustomCodeStyleSettings; import com.intellij.ui.ScrollPaneFactory; +import com.intellij.ui.components.editors.JBComboBoxTableCellEditorComponent; import com.intellij.ui.treeStructure.treetable.ListTreeTableModel; import com.intellij.ui.treeStructure.treetable.TreeTable; import com.intellij.ui.treeStructure.treetable.TreeTableCellRenderer; @@ -602,34 +603,32 @@ public abstract class OptionTableWithPreviewPanel extends MultilanguageCodeStyle } } + /** + * @author Konstantin Bulenkov + */ private class MyValueEditor extends AbstractTableCellEditor { - private final JComboBox myComboBox = new JComboBox(); - private final JCheckBox myCheckBox = new JCheckBox(); + private final JCheckBox myBooleanEditor = new JCheckBox(); + private JBComboBoxTableCellEditorComponent myOptionsEditor = new JBComboBoxTableCellEditorComponent(); private Component myCurrentEditor = null; private MyTreeNode myCurrentNode = null; public MyValueEditor() { - ActionListener synchronizer = new ActionListener() { + myBooleanEditor.addActionListener(new ActionListener() { public void actionPerformed(ActionEvent e) { if (myCurrentNode != null) { myCurrentNode.setValue(getCellEditorValue()); } } - }; - myComboBox.addActionListener(synchronizer); - myCheckBox.addActionListener(synchronizer); - - myComboBox.putClientProperty("JComponent.sizeVariant", "small"); - myComboBox.putClientProperty("JComboBox.isTableCellEditor", Boolean.TRUE); - myCheckBox.putClientProperty("JComponent.sizeVariant", "small"); + }); + myBooleanEditor.putClientProperty("JComponent.sizeVariant", "small"); } public Object getCellEditorValue() { - if (myCurrentEditor == myComboBox) { - return myComboBox.getSelectedItem(); + if (myCurrentEditor == myOptionsEditor) { + return myOptionsEditor.getEditorValue(); } - else if (myCurrentEditor == myCheckBox) { - return myCheckBox.isSelected() ? Boolean.TRUE : Boolean.FALSE; + else if (myCurrentEditor == myBooleanEditor) { + return myBooleanEditor.isSelected() ? Boolean.TRUE : Boolean.FALSE; } return null; @@ -642,27 +641,22 @@ public abstract class OptionTableWithPreviewPanel extends MultilanguageCodeStyle myCurrentNode = null; if (defaultNode instanceof MyTreeNode) { MyTreeNode node = (MyTreeNode)defaultNode; + myCurrentNode = node; if (node.getKey() instanceof BooleanOption) { - myCurrentEditor = myCheckBox; - myCheckBox.setSelected(node.getValue() == Boolean.TRUE); - myCheckBox.setEnabled(node.isEnabled()); + myCurrentEditor = myBooleanEditor; + myBooleanEditor.setSelected(node.getValue() == Boolean.TRUE); + myBooleanEditor.setEnabled(node.isEnabled()); } else { - myCurrentEditor = myComboBox; - myComboBox.removeAllItems(); - SelectionOption key = (SelectionOption)node.getKey(); - String[] values = key.options; - for (String value1 : values) { - myComboBox.addItem(value1); - } - myComboBox.setSelectedItem(node.getValue()); - myComboBox.setEnabled(node.isEnabled()); + myCurrentEditor = myOptionsEditor; + myOptionsEditor.setCell(table, row, column); + myOptionsEditor.setText(String.valueOf(node.getValue())); + myOptionsEditor.setOptions(((SelectionOption)node.getKey()).options); + myOptionsEditor.setDefaultValue(node.getValue()); } - myCurrentNode = node; } myCurrentEditor.setBackground(table.getBackground()); - return myCurrentEditor; } } diff --git a/platform/lang-impl/src/com/intellij/execution/runners/AbstractConsoleRunnerWithHistory.java b/platform/lang-impl/src/com/intellij/execution/runners/AbstractConsoleRunnerWithHistory.java index fa7477da6cb0..01033af29063 100644 --- a/platform/lang-impl/src/com/intellij/execution/runners/AbstractConsoleRunnerWithHistory.java +++ b/platform/lang-impl/src/com/intellij/execution/runners/AbstractConsoleRunnerWithHistory.java @@ -51,7 +51,7 @@ import java.util.List; * This class provides basic functionality for running consoles. * It launches external process and handles line input with history */ -public abstract class AbstractConsoleRunnerWithHistory { +public abstract class AbstractConsoleRunnerWithHistory { private final Project myProject; private final String myConsoleTitle; @@ -59,7 +59,7 @@ public abstract class AbstractConsoleRunnerWithHistory { private final CommandLineArgumentsProvider myProvider; private final String myWorkingDir; - private LanguageConsoleViewImpl myConsoleView; + private T myConsoleView; private ConsoleExecuteActionHandler myConsoleExecuteActionHandler; @@ -194,7 +194,7 @@ public abstract class AbstractConsoleRunnerWithHistory { myConsoleView.getConsole().setEditable(false); } - protected abstract LanguageConsoleViewImpl createConsoleView(); + protected abstract T createConsoleView(); @Nullable protected abstract Process createProcess(CommandLineArgumentsProvider provider) throws ExecutionException; @@ -288,7 +288,7 @@ public abstract class AbstractConsoleRunnerWithHistory { } } - public LanguageConsoleViewImpl getConsoleView() { + public T getConsoleView() { return myConsoleView; } diff --git a/platform/lang-impl/src/com/intellij/find/editorHeaderActions/Utils.java b/platform/lang-impl/src/com/intellij/find/editorHeaderActions/Utils.java index f3012fb7222d..b16c3a5c4a2e 100644 --- a/platform/lang-impl/src/com/intellij/find/editorHeaderActions/Utils.java +++ b/platform/lang-impl/src/com/intellij/find/editorHeaderActions/Utils.java @@ -1,9 +1,14 @@ package com.intellij.find.editorHeaderActions; +import com.intellij.openapi.editor.Editor; import com.intellij.openapi.ui.popup.JBPopup; import com.intellij.openapi.ui.popup.JBPopupFactory; import com.intellij.openapi.ui.popup.PopupChooserBuilder; import com.intellij.openapi.util.SystemInfo; +import com.intellij.openapi.vfs.ReadonlyStatusHandler; +import com.intellij.openapi.vfs.VirtualFile; +import com.intellij.psi.PsiDocumentManager; +import com.intellij.psi.PsiFile; import javax.swing.*; import java.awt.*; @@ -61,4 +66,20 @@ public class Utils { } } } + + public static boolean ensureOkToWrite(Editor e) { + final PsiFile psiFile = PsiDocumentManager.getInstance(e.getProject()).getPsiFile(e.getDocument()); + boolean okWritable; + if (psiFile != null) { + final VirtualFile virtualFile = psiFile.getVirtualFile(); + if (virtualFile != null) { + okWritable = ReadonlyStatusHandler.ensureFilesWritable(e.getProject(), virtualFile); + } else { + okWritable = psiFile.isWritable(); + } + } else { + okWritable = e.getDocument().isWritable(); + } + return okWritable; + } } diff --git a/platform/lang-impl/src/com/intellij/find/impl/livePreview/LivePreviewControllerBase.java b/platform/lang-impl/src/com/intellij/find/impl/livePreview/LivePreviewControllerBase.java index 098e18e69c8f..5a58b33cb458 100644 --- a/platform/lang-impl/src/com/intellij/find/impl/livePreview/LivePreviewControllerBase.java +++ b/platform/lang-impl/src/com/intellij/find/impl/livePreview/LivePreviewControllerBase.java @@ -3,6 +3,7 @@ package com.intellij.find.impl.livePreview; import com.intellij.find.FindManager; import com.intellij.find.FindModel; import com.intellij.find.FindUtil; +import com.intellij.find.editorHeaderActions.Utils; import com.intellij.find.impl.FindResultImpl; import com.intellij.openapi.application.ApplicationManager; import com.intellij.openapi.application.ModalityState; @@ -194,7 +195,7 @@ public class LivePreviewControllerBase implements LivePreview.Delegate, FindUtil @Nullable @Override public TextRange performReplace(final LiveOccurrence occurrence, final String replacement, final Editor editor) { - if (myReplaceDenied) return null; + if (myReplaceDenied || !Utils.ensureOkToWrite(editor)) return null; TextRange range = occurrence.getPrimaryRange(); FindModel findModel = mySearchResults.getFindModel(); TextRange result = null; @@ -216,6 +217,7 @@ public class LivePreviewControllerBase implements LivePreview.Delegate, FindUtil @Override public void performReplaceAll(Editor e) { + if (!Utils.ensureOkToWrite(e)) return; if (mySearchResults.getFindModel() != null) { FindUtil.replace(e.getProject(), e, mySearchResults.getFindModel().isGlobal() ? 0 : mySearchResults.getEditor().getSelectionModel().getSelectionStart(), diff --git a/platform/lang-impl/src/com/intellij/formatting/FormatterImpl.java b/platform/lang-impl/src/com/intellij/formatting/FormatterImpl.java index 3b62ea1fc3ee..8b9ba8442df0 100644 --- a/platform/lang-impl/src/com/intellij/formatting/FormatterImpl.java +++ b/platform/lang-impl/src/com/intellij/formatting/FormatterImpl.java @@ -37,10 +37,8 @@ import com.intellij.util.ui.UIUtil; import org.jetbrains.annotations.NotNull; import org.jetbrains.annotations.Nullable; -import java.util.Deque; import java.util.HashMap; import java.util.Map; -import java.util.concurrent.LinkedBlockingDeque; import java.util.concurrent.atomic.AtomicInteger; public class FormatterImpl extends FormatterEx @@ -52,15 +50,9 @@ public class FormatterImpl extends FormatterEx FormattingModelFactory { private static final Logger LOG = Logger.getInstance("#com.intellij.formatting.FormatterImpl"); - - private enum Source { - EXECUTE_SEQUENTIAL_TASK, GET_WHITESPACE_BEFORE, ADJUST_LINE_INDENT, ADJUST_LINE_INDENTS_FOR_RANGE, FORMAT_AROUND_RANGE, - ADJUST_TEXT_RANGE, ADJUST_TEXT_RANGE_WITH_ADDITIONAL_SETTINGS, RUN_WITH_FORMATTING_DISABLED - } private FormattingProgressIndicatorImpl myProgressIndicator; - private final Deque myDisabledFormattingRequests = new LinkedBlockingDeque(); private final AtomicInteger myIsDisabledCount = new AtomicInteger(); private final IndentImpl NONE_INDENT = new IndentImpl(Indent.Type.NONE, false, false); private final IndentImpl myAbsoluteNoneIndent = new IndentImpl(Indent.Type.NONE, true, false); @@ -218,7 +210,7 @@ public class FormatterImpl extends FormatterEx * @param task task to execute */ private void execute(@NotNull SequentialTask task) { - disableFormatting(Source.EXECUTE_SEQUENTIAL_TASK); + disableFormatting(); Application application = ApplicationManager.getApplication(); if (myProgressIndicator == null || !application.isDispatchThread() || application.isUnitTestMode()) { try { @@ -228,7 +220,7 @@ public class FormatterImpl extends FormatterEx } } finally { - enableFormatting(Source.EXECUTE_SEQUENTIAL_TASK); + enableFormatting(); myProgressIndicator = null; } } @@ -242,7 +234,7 @@ public class FormatterImpl extends FormatterEx public void run() { // Reset current progress indicator. myProgressIndicator = null; - enableFormatting(Source.EXECUTE_SEQUENTIAL_TASK); + enableFormatting(); } }); } @@ -257,7 +249,7 @@ public class FormatterImpl extends FormatterEx final CodeStyleSettings.IndentOptions indentOptions, final TextRange affectedRange, final boolean mayChangeLineFeeds) { - disableFormatting(Source.GET_WHITESPACE_BEFORE); + disableFormatting(); try { final FormatProcessor processor = buildProcessorAndWrapBlocks( model, block, settings, indentOptions, new FormatTextRanges(affectedRange, true) @@ -275,7 +267,7 @@ public class FormatterImpl extends FormatterEx return new IndentInfo(whiteSpace.getLineFeeds(), whiteSpace.getIndentOffset(), whiteSpace.getSpaces()); } finally { - enableFormatting(Source.GET_WHITESPACE_BEFORE); + enableFormatting(); } } @@ -283,7 +275,7 @@ public class FormatterImpl extends FormatterEx final CodeStyleSettings settings, final CodeStyleSettings.IndentOptions indentOptions, final TextRange rangeToAdjust) { - disableFormatting(Source.ADJUST_LINE_INDENTS_FOR_RANGE); + disableFormatting(); try { final FormattingDocumentModel documentModel = model.getDocumentModel(); final Block block = model.getRootBlock(); @@ -303,7 +295,7 @@ public class FormatterImpl extends FormatterEx processor.performModifications(model); } finally { - enableFormatting(Source.ADJUST_LINE_INDENTS_FOR_RANGE); + enableFormatting(); } } @@ -311,7 +303,7 @@ public class FormatterImpl extends FormatterEx final CodeStyleSettings settings, final TextRange textRange, final FileType fileType) { - disableFormatting(Source.FORMAT_AROUND_RANGE); + disableFormatting(); try { final FormattingDocumentModel documentModel = model.getDocumentModel(); final Block block = model.getRootBlock(); @@ -340,7 +332,7 @@ public class FormatterImpl extends FormatterEx processor.performModifications(model); } finally{ - enableFormatting(Source.FORMAT_AROUND_RANGE); + enableFormatting(); } } @@ -349,7 +341,7 @@ public class FormatterImpl extends FormatterEx final CodeStyleSettings.IndentOptions indentOptions, final int offset, final TextRange affectedRange) throws IncorrectOperationException { - disableFormatting(Source.ADJUST_LINE_INDENT); + disableFormatting(); if (model instanceof PsiBasedFormattingModel) { ((PsiBasedFormattingModel)model).canModifyAllWhiteSpaces(); } @@ -370,7 +362,7 @@ public class FormatterImpl extends FormatterEx return adjustLineIndent(offset, documentModel, processor, indentOptions, model, whiteSpace); } finally { - enableFormatting(Source.ADJUST_LINE_INDENT); + enableFormatting(); } } @@ -542,7 +534,7 @@ public class FormatterImpl extends FormatterEx final boolean changeWSBeforeFirstElement, final boolean changeLineFeedsBeforeFirstElement, @Nullable final IndentInfoStorage indentInfoStorage) { - disableFormatting(Source.ADJUST_TEXT_RANGE_WITH_ADDITIONAL_SETTINGS); + disableFormatting(); try { final FormatProcessor processor = buildProcessorAndWrapBlocks( model.getDocumentModel(), model.getRootBlock(), settings, indentOptions, new FormatTextRanges(affectedRange, true) @@ -603,7 +595,7 @@ public class FormatterImpl extends FormatterEx processor.format(model); } finally { - enableFormatting(Source.ADJUST_TEXT_RANGE_WITH_ADDITIONAL_SETTINGS); + enableFormatting(); } } @@ -611,7 +603,7 @@ public class FormatterImpl extends FormatterEx final CodeStyleSettings settings, final CodeStyleSettings.IndentOptions indentOptions, final TextRange affectedRange) { - disableFormatting(Source.ADJUST_TEXT_RANGE); + disableFormatting(); try { final FormatProcessor processor = buildProcessorAndWrapBlocks( model.getDocumentModel(), model.getRootBlock(), settings, indentOptions, new FormatTextRanges(affectedRange, true) @@ -633,7 +625,7 @@ public class FormatterImpl extends FormatterEx processor.format(model); } finally { - enableFormatting(Source.ADJUST_TEXT_RANGE); + enableFormatting(); } } @@ -743,34 +735,24 @@ public class FormatterImpl extends FormatterEx return myIsDisabledCount.get() > 0; } - private void disableFormatting(@NotNull Source requestSource) { + private void disableFormatting() { myIsDisabledCount.incrementAndGet(); - myDisabledFormattingRequests.add(requestSource); } - private void enableFormatting(@NotNull Source requestSource) { - boolean checkSource = true; + private void enableFormatting() { int old = myIsDisabledCount.getAndDecrement(); if (old <= 0) { - checkSource = false; - LOG.error( - "enableFormatting()/disableFormatting() not paired. DisabledLevel = " + old + ", request source: " + myDisabledFormattingRequests - ); - } - Source source = myDisabledFormattingRequests.pollLast(); - if (checkSource && requestSource != source) { - LOG.error("enableFormatting()/disableFormatting() from different sources detected! 'Disable source': " + source - + ", 'enable source': " + requestSource); + LOG.error("enableFormatting()/disableFormatting() not paired. DisabledLevel = " + old); } } public T runWithFormattingDisabled(@NotNull Computable runnable) { - disableFormatting(Source.RUN_WITH_FORMATTING_DISABLED); + disableFormatting(); try { return runnable.compute(); } finally { - enableFormatting(Source.RUN_WITH_FORMATTING_DISABLED); + enableFormatting(); } } diff --git a/platform/lang-impl/src/com/intellij/ide/projectView/impl/nodes/ExternalLibrariesNode.java b/platform/lang-impl/src/com/intellij/ide/projectView/impl/nodes/ExternalLibrariesNode.java index 43d54ce388b5..ef5481db5e9b 100644 --- a/platform/lang-impl/src/com/intellij/ide/projectView/impl/nodes/ExternalLibrariesNode.java +++ b/platform/lang-impl/src/com/intellij/ide/projectView/impl/nodes/ExternalLibrariesNode.java @@ -47,7 +47,10 @@ public class ExternalLibrariesNode extends ProjectViewNode { @Override public boolean contains(@NotNull VirtualFile file) { - return someChildContainsFile(file); + ProjectFileIndex index = ProjectRootManager.getInstance(getProject()).getFileIndex(); + if (!index.isInLibrarySource(file) && !index.isInLibraryClasses(file)) return false; + + return someChildContainsFile(file, false); } @NotNull diff --git a/platform/lang-impl/src/com/intellij/ide/projectView/impl/nodes/ModuleGroupNode.java b/platform/lang-impl/src/com/intellij/ide/projectView/impl/nodes/ModuleGroupNode.java index fd1fed15571b..d60cbde492a3 100644 --- a/platform/lang-impl/src/com/intellij/ide/projectView/impl/nodes/ModuleGroupNode.java +++ b/platform/lang-impl/src/com/intellij/ide/projectView/impl/nodes/ModuleGroupNode.java @@ -83,7 +83,7 @@ public abstract class ModuleGroupNode extends ProjectViewNode imple } public boolean contains(@NotNull VirtualFile file) { - return someChildContainsFile(file); + return someChildContainsFile(file, false); } public void update(PresentationData presentation) { diff --git a/platform/lang-impl/src/com/intellij/psi/impl/source/resolve/reference/impl/providers/FileReference.java b/platform/lang-impl/src/com/intellij/psi/impl/source/resolve/reference/impl/providers/FileReference.java index 978638d19aa7..0778acf2efb6 100644 --- a/platform/lang-impl/src/com/intellij/psi/impl/source/resolve/reference/impl/providers/FileReference.java +++ b/platform/lang-impl/src/com/intellij/psi/impl/source/resolve/reference/impl/providers/FileReference.java @@ -202,7 +202,7 @@ public class FileReference implements FileReferenceOwner, PsiPolyVariantReferenc public boolean execute(PsiFileSystemItem element) { result.add(new PsiElementResolveResult(getOriginalFile(element))); - return false; + return true; } }); } diff --git a/platform/platform-api/src/com/intellij/ui/components/JBList.java b/platform/platform-api/src/com/intellij/ui/components/JBList.java index 71f523ac687f..0849651a54ed 100644 --- a/platform/platform-api/src/com/intellij/ui/components/JBList.java +++ b/platform/platform-api/src/com/intellij/ui/components/JBList.java @@ -53,7 +53,7 @@ public class JBList extends JList implements ComponentWithEmptyText, ComponentWi init(); } - private static DefaultListModel createDefaultListModel(Object[] items) { + public static DefaultListModel createDefaultListModel(Object... items) { final DefaultListModel model = new DefaultListModel(); for (Object item : items) { model.add(model.getSize(), item); diff --git a/platform/platform-api/src/com/intellij/ui/components/editors/JBComboBoxTableCellEditorComponent.java b/platform/platform-api/src/com/intellij/ui/components/editors/JBComboBoxTableCellEditorComponent.java new file mode 100644 index 000000000000..f14561de9384 --- /dev/null +++ b/platform/platform-api/src/com/intellij/ui/components/editors/JBComboBoxTableCellEditorComponent.java @@ -0,0 +1,124 @@ +/* + * 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.ui.components.editors; + +import com.intellij.openapi.ui.popup.JBPopupFactory; +import com.intellij.ui.awt.RelativePoint; +import com.intellij.ui.components.JBLabel; +import com.intellij.ui.components.JBList; +import com.intellij.util.Icons; +import com.intellij.util.ui.EmptyIcon; + +import javax.swing.*; +import java.awt.*; + +/** + * Solves rendering problems in JTable components when JComboBox objects are used as cell + * editors components. Known issues of using JComboBox component are the following: + * 1. Ugly view if row height is small enough + * 2. Truncated strings in the combobox popup if column width is less than text value width + * + * @author Konstantin Bulenkov + */ +public class JBComboBoxTableCellEditorComponent extends JBLabel { + private JTable myTable; + private int myRow = 0; + private int myColumn = 0; + private final JBList myList = new JBList(); + private Object[] myOptions = {}; + private Object myValue; + + private ListCellRenderer myRenderer = new DefaultListCellRenderer() { + private Icon myCheckIcon = Icons.CHECK_ICON; + private Icon myEmptyIcon = EmptyIcon.create(Icons.CHECK_ICON.getIconWidth()); + @Override + public Component getListCellRendererComponent(JList list, Object value, int index, boolean isSelected, boolean cellHasFocus) { + final JLabel label = (JLabel)super.getListCellRendererComponent(list, value, index, isSelected, cellHasFocus); + if (value == myValue) { + label.setIcon(myCheckIcon); + } else { + label.setIcon(myEmptyIcon); + } + return label; + } + }; + + public JBComboBoxTableCellEditorComponent() { + } + + public JBComboBoxTableCellEditorComponent(JTable table) { + myTable = table; + } + + public void setTable(JTable table) { + myTable = table; + } + + public void setCell(JTable table, int row, int column) { + setTable(table); + setRow(row); + setColumn(column); + } + + public void setRow(int row) { + myRow = row; + } + + public void setColumn(int column) { + myColumn = column; + } + + public void setOptions(Object... options) { + myOptions = options; + } + + @Override + public void addNotify() { + super.addNotify(); + initAndShowPopup(); + } + + private void initAndShowPopup() { + myList.removeAll(); + final Rectangle rect = myTable.getCellRect(myRow, myColumn, true); + final Point point = new Point(rect.x, rect.y); + myList.setModel(JBList.createDefaultListModel(myOptions)); + if (myRenderer != null) { + myList.setCellRenderer(myRenderer); + } + JBPopupFactory.getInstance() + .createListPopupBuilder(myList) + .setItemChoosenCallback(new Runnable() { + @Override + public void run() { + myValue = myList.getSelectedValue(); + } + }).createPopup() + .show(new RelativePoint(myTable, point)); + } + + public Object getEditorValue() { + return myValue; + } + + public void setRenderer(ListCellRenderer renderer) { + myRenderer = renderer; + } + + public void setDefaultValue(Object value) { + myValue = value; + } +} diff --git a/platform/testFramework/src/com/intellij/testFramework/ProjectViewTestUtil.java b/platform/testFramework/src/com/intellij/testFramework/ProjectViewTestUtil.java index 8a23de557f88..3ec4f41e7111 100644 --- a/platform/testFramework/src/com/intellij/testFramework/ProjectViewTestUtil.java +++ b/platform/testFramework/src/com/intellij/testFramework/ProjectViewTestUtil.java @@ -78,6 +78,9 @@ public class ProjectViewTestUtil { boolean actual = eachNode.contains(eachFile); boolean expected = map.get(eachFile).contains(eachNode); if (actual != expected) { + boolean actual1 = eachNode.contains(eachFile); + boolean expected1 = map.get(eachFile).contains(eachNode); + Assert.assertTrue("file=" + eachFile + " node=" + eachNode.getTestPresentation() + " expected:" + expected, false); } } diff --git a/platform/util/src/com/intellij/psi/codeStyle/NameUtil.java b/platform/util/src/com/intellij/psi/codeStyle/NameUtil.java index beb01bfb5d12..723d91d96960 100644 --- a/platform/util/src/com/intellij/psi/codeStyle/NameUtil.java +++ b/platform/util/src/com/intellij/psi/codeStyle/NameUtil.java @@ -539,7 +539,7 @@ public class NameUtil { } // there's more in the pattern, but no more words if (nextStart == name.length()) { - if (patternIndex + i == myPattern.length - 1 && ' ' == myPattern[patternIndex + i] && i + nameIndex == name.length()) { + if (patternIndex + i == myPattern.length - 1 && ' ' == myPattern[patternIndex + i] && (i == 1 || i + nameIndex == name.length())) { return FList.emptyList().prepend(TextRange.from(nameIndex, i)); } diff --git a/plugins/android/src/org/jetbrains/android/AndroidXmlSchemaProvider.java b/plugins/android/src/org/jetbrains/android/AndroidXmlSchemaProvider.java index 943d39fc03e5..a6d5dc103ffd 100644 --- a/plugins/android/src/org/jetbrains/android/AndroidXmlSchemaProvider.java +++ b/plugins/android/src/org/jetbrains/android/AndroidXmlSchemaProvider.java @@ -74,7 +74,12 @@ public class AndroidXmlSchemaProvider extends XmlSchemaProvider { public Result compute() { final URL resource = AndroidXmlSchemaProvider.class.getResource("android.xsd"); final VirtualFile fileByURL = VfsUtil.findFileByURL(resource); - XmlFile result = (XmlFile)PsiManager.getInstance(module.getProject()).findFile(fileByURL).copy(); + XmlFile result = ApplicationManager.getApplication().runWriteAction(new Computable() { + @Override + public XmlFile compute() { + return (XmlFile)PsiManager.getInstance(module.getProject()).findFile(fileByURL).copy(); + } + }); return new Result(result, PsiModificationTracker.MODIFICATION_COUNT); } }, false); diff --git a/plugins/android/src/org/jetbrains/android/run/DeviceChooser.java b/plugins/android/src/org/jetbrains/android/run/DeviceChooser.java index 518d82cf7596..70cc4fa1211d 100644 --- a/plugins/android/src/org/jetbrains/android/run/DeviceChooser.java +++ b/plugins/android/src/org/jetbrains/android/run/DeviceChooser.java @@ -129,9 +129,7 @@ public class DeviceChooser extends DialogWrapper implements AndroidDebugBridge.I private void updateTable() { final AndroidDebugBridge bridge = myFacet.getDebugBridge(); - if (bridge == null) return; - - IDevice[] devices = bridge.getDevices(); + IDevice[] devices = bridge != null ? bridge.getDevices() : EMPTY_DEVICE_ARRAY; int[] selectedRows = myDeviceTable.getSelectedRows(); myDeviceTable.setModel(new MyDeviceTableModel(devices)); if (selectedRows.length == 0 && devices.length > 0) { diff --git a/plugins/groovy/src/org/jetbrains/plugins/groovy/formatter/GroovyBlock.java b/plugins/groovy/src/org/jetbrains/plugins/groovy/formatter/GroovyBlock.java index 49ec0d0ead27..e17443677263 100644 --- a/plugins/groovy/src/org/jetbrains/plugins/groovy/formatter/GroovyBlock.java +++ b/plugins/groovy/src/org/jetbrains/plugins/groovy/formatter/GroovyBlock.java @@ -215,6 +215,6 @@ public class GroovyBlock implements Block, GroovyElementTypes { @Override public String toString() { - return myNode.getTextRange() + ": " + myNode; + return getTextRange() + ": " + myNode; } } diff --git a/plugins/groovy/src/org/jetbrains/plugins/groovy/formatter/GroovyBlockGenerator.java b/plugins/groovy/src/org/jetbrains/plugins/groovy/formatter/GroovyBlockGenerator.java index ad740af12b3c..49946c1031e4 100644 --- a/plugins/groovy/src/org/jetbrains/plugins/groovy/formatter/GroovyBlockGenerator.java +++ b/plugins/groovy/src/org/jetbrains/plugins/groovy/formatter/GroovyBlockGenerator.java @@ -25,7 +25,9 @@ import com.intellij.openapi.util.TextRange; import com.intellij.psi.PsiElement; import com.intellij.psi.PsiFile; import com.intellij.psi.codeStyle.CodeStyleSettings; +import com.intellij.psi.impl.source.tree.CompositeElement; import com.intellij.psi.templateLanguages.OuterLanguageElement; +import com.intellij.psi.tree.IElementType; import com.intellij.psi.tree.TokenSet; import com.intellij.util.containers.CollectionFactory; import org.jetbrains.annotations.NotNull; @@ -33,6 +35,8 @@ import org.jetbrains.plugins.groovy.GroovyFileType; import org.jetbrains.plugins.groovy.formatter.processors.GroovyIndentProcessor; import org.jetbrains.plugins.groovy.lang.lexer.GroovyTokenTypes; import org.jetbrains.plugins.groovy.lang.parser.GroovyElementTypes; +import org.jetbrains.plugins.groovy.lang.psi.GrQualifiedReference; +import org.jetbrains.plugins.groovy.lang.psi.GroovyFile; import org.jetbrains.plugins.groovy.lang.psi.GroovyFileBase; import org.jetbrains.plugins.groovy.lang.psi.api.auxiliary.GrThrowsClause; import org.jetbrains.plugins.groovy.lang.psi.api.statements.GrLabeledStatement; @@ -41,7 +45,10 @@ import org.jetbrains.plugins.groovy.lang.psi.api.statements.arguments.GrArgument import org.jetbrains.plugins.groovy.lang.psi.api.statements.blocks.GrCodeBlock; import org.jetbrains.plugins.groovy.lang.psi.api.statements.expressions.GrBinaryExpression; import org.jetbrains.plugins.groovy.lang.psi.api.statements.expressions.GrConditionalExpression; +import org.jetbrains.plugins.groovy.lang.psi.api.statements.expressions.GrExpression; +import org.jetbrains.plugins.groovy.lang.psi.api.statements.expressions.path.GrMethodCallExpression; import org.jetbrains.plugins.groovy.lang.psi.api.statements.params.GrParameterList; +import org.jetbrains.plugins.groovy.lang.psi.api.statements.typedef.GrAnonymousClassDefinition; import org.jetbrains.plugins.groovy.lang.psi.api.statements.typedef.GrExtendsClause; import java.util.ArrayList; @@ -102,58 +109,50 @@ public class GroovyBlockGenerator implements GroovyElementTypes { if (block.getNode().getElementType() == GSTRING) { final ArrayList subBlocks = new ArrayList(); ASTNode[] children = getGroovyChildren(node); - ASTNode prevChildNode = null; for (ASTNode childNode : children) { if (childNode.getTextRange().getLength() > 0) { - final Indent indent = GroovyIndentProcessor.getChildIndent(block, prevChildNode, childNode); + final Indent indent = GroovyIndentProcessor.getChildIndent(block, childNode); subBlocks.add(new GroovyBlock(childNode, myAlignment, indent, myWrap, mySettings)); } - prevChildNode = childNode; } return subBlocks; } - //For nested selections - if (NESTED.contains(block.getNode().getElementType()) && - blockPsi.getParent() != null && - blockPsi.getParent().getNode() != null && - !NESTED.contains(blockPsi.getParent().getNode().getElementType())) { - return generateForNestedExpr(node, myAlignment, myWrap, mySettings); + // chained properties, calls, indexing, etc + if (NESTED.contains(block.getNode().getElementType()) && blockPsi.getParent() != null && !NESTED.contains(blockPsi.getParent().getNode().getElementType())) { + final List subBlocks = new ArrayList(); + addNestedChildren(node.getPsi(), subBlocks, myAlignment, myWrap, mySettings, true); + return subBlocks; } // For Parameter lists if (isListLikeClause(blockPsi)) { final ArrayList subBlocks = new ArrayList(); - ASTNode prevChildNode = null; - final Alignment alignment = mustAlign(blockPsi, mySettings, node.getChildren(null)) ? Alignment.createAlignment() : null; - for (ASTNode childNode : visibleChildren(node)) { - final Indent indent = GroovyIndentProcessor.getChildIndent(block, prevChildNode, childNode); + List astNodes = visibleChildren(node); + final Alignment alignment = mustAlign(blockPsi, mySettings, astNodes) ? Alignment.createAlignment() : null; + for (ASTNode childNode : astNodes) { + final Indent indent = GroovyIndentProcessor.getChildIndent(block, childNode); subBlocks.add(new GroovyBlock(childNode, isKeyword(childNode) ? null : alignment, indent, myWrap, mySettings)); - prevChildNode = childNode; } return subBlocks; } - if (blockPsi instanceof GrCodeBlock) { + if (blockPsi instanceof GrCodeBlock || blockPsi instanceof GroovyFile) { List children = visibleChildren(node); Map innerAlignments = calculateInnerAlignments(children); final ArrayList subBlocks = new ArrayList(); - ASTNode prevChildNode = null; for (ASTNode childNode : children) { - final Indent indent = GroovyIndentProcessor.getChildIndent(block, prevChildNode, childNode); + final Indent indent = GroovyIndentProcessor.getChildIndent(block, childNode); subBlocks.add(new GroovyBlock(childNode, null, indent, myWrap, mySettings, innerAlignments)); - prevChildNode = childNode; } return subBlocks; } // For other cases final ArrayList subBlocks = new ArrayList(); - ASTNode prevChildNode = null; for (ASTNode childNode : visibleChildren(node)) { - final Indent indent = GroovyIndentProcessor.getChildIndent(block, prevChildNode, childNode); - subBlocks.add(new GroovyBlock(childNode, myAlignment, indent, myWrap, mySettings, block.myInnerAlignments)); - prevChildNode = childNode; + final Indent indent = GroovyIndentProcessor.getChildIndent(block, childNode); + subBlocks.add(new GroovyBlock(childNode, blockPsi instanceof GrAnonymousClassDefinition ? null : myAlignment, indent, myWrap, mySettings, block.myInnerAlignments)); } return subBlocks; } @@ -211,7 +210,7 @@ public class GroovyBlockGenerator implements GroovyElementTypes { return list; } - private static boolean mustAlign(PsiElement blockPsi, CodeStyleSettings mySettings, ASTNode[] children) { + private static boolean mustAlign(PsiElement blockPsi, CodeStyleSettings mySettings, List children) { // We don't want to align single call argument if it's a closure. The reason is that it looks better to have call like // // foo({ @@ -224,14 +223,8 @@ public class GroovyBlockGenerator implements GroovyElementTypes { // println 'xxx' // }) if (blockPsi instanceof GrArgumentList && mySettings.ALIGN_MULTILINE_PARAMETERS_IN_CALLS) { - List nonWhiteSpaceNodes = new ArrayList(); - for (ASTNode child : children) { - if (!WHITE_SPACES_OR_COMMENTS.contains(child.getElementType())) { - nonWhiteSpaceNodes.add(child); - } - } - return nonWhiteSpaceNodes.size() != 3 || nonWhiteSpaceNodes.get(0).getElementType() != mLPAREN - || nonWhiteSpaceNodes.get(1).getElementType() != CLOSABLE_BLOCK || nonWhiteSpaceNodes.get(2).getElementType() != mRPAREN; + return children.size() != 3 || children.get(0).getElementType() != mLPAREN + || children.get(1).getElementType() != CLOSABLE_BLOCK || children.get(2).getElementType() != mRPAREN; } return blockPsi instanceof GrParameterList && mySettings.ALIGN_MULTILINE_PARAMETERS || @@ -385,59 +378,63 @@ public class GroovyBlockGenerator implements GroovyElementTypes { } - /** - * Generates blocks for nested expressions like a.b.c etc. - * - * @return - * @param node - */ - private static List generateForNestedExpr(final ASTNode node, Alignment myAlignment, Wrap myWrap, CodeStyleSettings mySettings) { - final ArrayList subBlocks = new ArrayList(); - ASTNode children[] = node.getChildren(null); - if (children.length > 0 && NESTED.contains(children[0].getElementType())) { - addNestedChildrenRecursively(children[0].getPsi(), subBlocks, myAlignment, myWrap, mySettings); - } else if (canBeCorrectBlock(children[0])) { - subBlocks.add(new GroovyBlock(children[0], myAlignment, Indent.getContinuationWithoutFirstIndent(), myWrap, mySettings)); - } - if (children.length > 1) { - for (ASTNode childNode : children) { - if (canBeCorrectBlock(childNode) && - children[0] != childNode) { - subBlocks.add(new GroovyBlock(childNode, myAlignment, Indent.getContinuationWithoutFirstIndent(), myWrap, mySettings)); - } - } - } - return subBlocks; - } - - /** - * Adds nested children for paths - * - * @param elem - * @param list - */ - private static void addNestedChildrenRecursively(PsiElement elem, - List list, Alignment myAlignment, Wrap myWrap, CodeStyleSettings mySettings) { - ASTNode[] children = elem.getNode().getChildren(null); - // For path expressions - if (children.length > 0 && NESTED.contains(children[0].getElementType())) { - addNestedChildrenRecursively(children[0].getPsi(), list, myAlignment, myWrap, mySettings); - } else if (canBeCorrectBlock(children[0])) { - list.add(new GroovyBlock(children[0], myAlignment, Indent.getContinuationWithoutFirstIndent(), myWrap, mySettings)); - } - if (children.length > 1) { - for (ASTNode childNode : children) { - if (canBeCorrectBlock(childNode) && - children[0] != childNode) { - if (elem.getNode() != null && - NESTED.contains(elem.getNode().getElementType())) { - list.add(new GroovyBlock(childNode, myAlignment, Indent.getContinuationWithoutFirstIndent(), myWrap, mySettings)); - } else { - list.add(new GroovyBlock(childNode, myAlignment, Indent.getNoneIndent(), myWrap, mySettings)); + private static void addNestedChildren(final PsiElement elem, List list, + final Alignment alignment, + final Wrap wrap, + final CodeStyleSettings settings, final boolean topLevel) { + final List children = visibleChildren(elem.getNode()); + if (elem instanceof GrMethodCallExpression) { + GrExpression invokedExpression = ((GrMethodCallExpression)elem).getInvokedExpression(); + if (invokedExpression instanceof GrQualifiedReference) { + final PsiElement nameElement = ((GrQualifiedReference)invokedExpression).getReferenceNameElement(); + if (nameElement != null) { + List grandChildren = visibleChildren(invokedExpression.getNode()); + int i = 0; + while (i < grandChildren.size() && nameElement != grandChildren.get(i).getPsi()) { i++; } + if (i > 0) { + processNestedChildrenPrefix(list, alignment, wrap, settings, false, grandChildren, i); } + if (i < grandChildren.size()) { + assert nameElement == grandChildren.get(i).getPsi(); + list.add(new MethodCallWithoutQualifierBlock(nameElement, alignment, wrap, settings, topLevel, children, elem)); + } + return; } } + + } + + + processNestedChildrenPrefix(list, alignment, wrap, settings, topLevel, children, children.size()); + } + + private static void processNestedChildrenPrefix(List list, + Alignment alignment, + Wrap wrap, + CodeStyleSettings settings, + boolean topLevel, List children, int limit) { + ASTNode fst = children.get(0); + assert limit > 0; + if (NESTED.contains(fst.getElementType())) { + addNestedChildren(fst.getPsi(), list, alignment, wrap, settings, false); + } else { + list.add(new GroovyBlock(fst, alignment, Indent.getContinuationWithoutFirstIndent(), wrap, settings)); + } + addNestedChildrenSuffix(list, alignment, wrap, settings, topLevel, children, limit); + } + + static void addNestedChildrenSuffix(List list, + Alignment alignment, + Wrap wrap, + CodeStyleSettings settings, + boolean topLevel, List children, int limit) { + for (int i = 1; i < limit; i++) { + ASTNode childNode = children.get(i); + if (canBeCorrectBlock(childNode)) { + IElementType type = childNode.getElementType(); + Indent indent = topLevel || NESTED.contains(type) || type == mIDENT ? Indent.getContinuationWithoutFirstIndent() : Indent.getNoneIndent(); + list.add(new GroovyBlock(childNode, childNode instanceof CompositeElement || type == mIDENT ? alignment : null, indent, wrap, settings)); + } } } - } diff --git a/plugins/groovy/src/org/jetbrains/plugins/groovy/formatter/MethodCallWithoutQualifierBlock.java b/plugins/groovy/src/org/jetbrains/plugins/groovy/formatter/MethodCallWithoutQualifierBlock.java new file mode 100644 index 000000000000..c66cdc6ca1a7 --- /dev/null +++ b/plugins/groovy/src/org/jetbrains/plugins/groovy/formatter/MethodCallWithoutQualifierBlock.java @@ -0,0 +1,73 @@ +/* + * 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.formatter; + +import com.intellij.formatting.Alignment; +import com.intellij.formatting.Block; +import com.intellij.formatting.Indent; +import com.intellij.formatting.Wrap; +import com.intellij.lang.ASTNode; +import com.intellij.openapi.util.TextRange; +import com.intellij.psi.PsiElement; +import com.intellij.psi.codeStyle.CodeStyleSettings; +import org.jetbrains.annotations.NotNull; + +import java.util.ArrayList; +import java.util.List; + +/** +* @author peter +*/ +public class MethodCallWithoutQualifierBlock extends GroovyBlock { + private final PsiElement myNameElement; + private final Alignment myAlignment; + private final Wrap myWrap; + private final CodeStyleSettings mySettings; + private final boolean myTopLevel; + private final List myChildren; + private final PsiElement myElem; + + public MethodCallWithoutQualifierBlock(PsiElement nameElement, + Alignment alignment, + Wrap wrap, + CodeStyleSettings settings, + boolean topLevel, + List children, PsiElement elem) { + super(nameElement.getNode(), alignment, Indent.getContinuationWithoutFirstIndent(), wrap, settings); + myNameElement = nameElement; + myAlignment = alignment; + myWrap = wrap; + mySettings = settings; + myTopLevel = topLevel; + myChildren = children; + myElem = elem; + } + + @NotNull + @Override + public List getSubBlocks() { + ArrayList blocks = new ArrayList(); + blocks.add(new GroovyBlock(myNameElement.getNode(), myAlignment, Indent.getContinuationWithoutFirstIndent(), myWrap, mySettings)); + GroovyBlockGenerator.addNestedChildrenSuffix(blocks, myAlignment, myWrap, mySettings, myTopLevel, myChildren, myChildren.size()); + return blocks; + } + + @NotNull + @Override + public TextRange getTextRange() { + return new TextRange(myNameElement.getTextRange().getStartOffset(), myElem.getTextRange().getEndOffset()); + } +} diff --git a/plugins/groovy/src/org/jetbrains/plugins/groovy/formatter/processors/GroovyIndentProcessor.java b/plugins/groovy/src/org/jetbrains/plugins/groovy/formatter/processors/GroovyIndentProcessor.java index da414c9655c8..1f95dd1004b6 100644 --- a/plugins/groovy/src/org/jetbrains/plugins/groovy/formatter/processors/GroovyIndentProcessor.java +++ b/plugins/groovy/src/org/jetbrains/plugins/groovy/formatter/processors/GroovyIndentProcessor.java @@ -22,7 +22,6 @@ import com.intellij.psi.PsiElement; import com.intellij.psi.codeStyle.CodeStyleSettingsManager; import com.intellij.psi.tree.IElementType; import org.jetbrains.annotations.NotNull; -import org.jetbrains.annotations.Nullable; import org.jetbrains.plugins.groovy.formatter.GroovyBlock; import org.jetbrains.plugins.groovy.lang.editor.actions.GroovyEditorActionUtil; import org.jetbrains.plugins.groovy.lang.groovydoc.psi.api.GrDocComment; @@ -41,6 +40,7 @@ import org.jetbrains.plugins.groovy.lang.psi.api.statements.expressions.GrElvisE import org.jetbrains.plugins.groovy.lang.psi.api.statements.expressions.GrExpression; import org.jetbrains.plugins.groovy.lang.psi.api.statements.params.GrParameterList; import org.jetbrains.plugins.groovy.lang.psi.api.statements.typedef.GrExtendsClause; +import org.jetbrains.plugins.groovy.lang.psi.api.statements.typedef.members.GrMethod; /** * @author ilyas @@ -53,11 +53,10 @@ public abstract class GroovyIndentProcessor implements GroovyElementTypes { * * @param parent parent block * @param child child node - * @param prevChildNode previous child node * @return indent */ @NotNull - public static Indent getChildIndent(@NotNull final GroovyBlock parent, @Nullable final ASTNode prevChildNode, @NotNull final ASTNode child) { + public static Indent getChildIndent(@NotNull final GroovyBlock parent, @NotNull final ASTNode child) { ASTNode astNode = parent.getNode(); final PsiElement psiParent = astNode.getPsi(); @@ -66,6 +65,10 @@ public abstract class GroovyIndentProcessor implements GroovyElementTypes { return Indent.getNoneIndent(); } + if (psiParent instanceof GrMethod && child.getPsi() instanceof GrParameterList) { + return Indent.getContinuationIndent(); + } + if (GroovyEditorActionUtil.GSTRING_TOKENS_INNER.contains(child.getElementType()) && mGSTRING_BEGIN != child.getElementType()) { return Indent.getAbsoluteNoneIndent(); diff --git a/plugins/groovy/src/org/jetbrains/plugins/groovy/formatter/processors/GroovySpacingProcessor.java b/plugins/groovy/src/org/jetbrains/plugins/groovy/formatter/processors/GroovySpacingProcessor.java index cf1129da26b3..590bf26b1467 100644 --- a/plugins/groovy/src/org/jetbrains/plugins/groovy/formatter/processors/GroovySpacingProcessor.java +++ b/plugins/groovy/src/org/jetbrains/plugins/groovy/formatter/processors/GroovySpacingProcessor.java @@ -21,7 +21,9 @@ import com.intellij.lang.ASTNode; import com.intellij.openapi.util.TextRange; import com.intellij.psi.PsiElement; import com.intellij.psi.PsiIdentifier; +import com.intellij.psi.PsiWhiteSpace; import com.intellij.psi.codeStyle.CodeStyleSettings; +import com.intellij.psi.formatter.FormatterUtil; import com.intellij.psi.impl.source.SourceTreeToPsiMap; import com.intellij.psi.impl.source.tree.CompositeElement; import com.intellij.psi.tree.IElementType; @@ -61,7 +63,6 @@ import static org.jetbrains.plugins.groovy.lang.parser.GroovyElementTypes.mGDOC_ import static org.jetbrains.plugins.groovy.lang.parser.GroovyElementTypes.mGDOC_INLINE_TAG_END; import static org.jetbrains.plugins.groovy.lang.parser.GroovyElementTypes.mGDOC_INLINE_TAG_START; import static org.jetbrains.plugins.groovy.lang.parser.GroovyElementTypes.mGDOC_TAG_VALUE_RPAREN; -import static org.jetbrains.plugins.groovy.lang.parser.GroovyElementTypes.mNLS; import static org.jetbrains.plugins.groovy.lang.parser.GroovyElementTypes.mRCURLY; /** @@ -91,21 +92,22 @@ public class GroovySpacingProcessor extends GroovyElementVisitor { return; } - if (myChild2 != null && mySettings.KEEP_FIRST_COLUMN_COMMENT && SpacingUtil.COMMENT_BIT_SET.contains(myChild2.getElementType())) { + ASTNode prev = getPrevElementType(myChild2); + if (prev != null && prev.getElementType() == mNLS) { + prev = getPrevElementType(prev); + } + if (prev != null && prev.getElementType() == mSL_COMMENT) { + myResult = Spacing.createSpacing(0, Integer.MAX_VALUE, 1, mySettings.KEEP_LINE_BREAKS, mySettings.KEEP_BLANK_LINES_IN_CODE); + return; + } + + if (myChild2 != null && mySettings.KEEP_FIRST_COLUMN_COMMENT && COMMENT_SET.contains(myChild2.getElementType())) { if (myChild1.getElementType() != IMPORT_STATEMENT) { myResult = Spacing.createKeepingFirstColumnSpacing(0, Integer.MAX_VALUE, true, 1); } return; } - if (myChild1 != null && myChild2 != null && myChild1.getElementType() == mNLS) { - final ASTNode prev = SpacingUtil.getPrevElementType(myChild1); - if (prev != null && prev.getElementType() == mSL_COMMENT) { - myResult = Spacing.createSpacing(0, 0, 1, mySettings.KEEP_LINE_BREAKS, mySettings.KEEP_BLANK_LINES_IN_CODE); - return; - } - } - if (myParent instanceof GroovyPsiElement) { ((GroovyPsiElement) myParent).accept(this); } @@ -114,7 +116,7 @@ public class GroovySpacingProcessor extends GroovyElementVisitor { private void _init(final ASTNode child) { if (child != null) { ASTNode treePrev = child.getTreePrev(); - while (treePrev != null && SpacingUtil.isWhiteSpace(treePrev)) { + while (treePrev != null && isWhiteSpace(treePrev)) { treePrev = treePrev.getTreePrev(); } if (treePrev == null) { @@ -479,12 +481,7 @@ public class GroovySpacingProcessor extends GroovyElementVisitor { } private void createSpaceProperty(boolean space, boolean keepLineBreaks, final int keepBlankLines) { - final ASTNode prev = SpacingUtil.getPrevElementType(myChild2); - if (prev != null && prev.getElementType() == mSL_COMMENT) { - myResult = Spacing.createSpacing(0, 0, 1, mySettings.KEEP_LINE_BREAKS, mySettings.KEEP_BLANK_LINES_IN_CODE); - } else { - myResult = Spacing.createSpacing(space ? 1 : 0, space ? 1 : 0, 0, keepLineBreaks, keepBlankLines); - } + myResult = Spacing.createSpacing(space ? 1 : 0, space ? 1 : 0, 0, keepLineBreaks, keepBlankLines); } private Spacing getSpaceBeforeLBrace(final boolean spaceBeforeLbrace, int braceStyle, TextRange dependantRange, boolean keepOneLine) { @@ -503,7 +500,7 @@ public class GroovySpacingProcessor extends GroovyElementVisitor { } private Spacing createNonLFSpace(int spaces, final TextRange dependantRange, final boolean keepLineBreaks) { - final ASTNode prev = SpacingUtil.getPrevElementType(myChild2); + final ASTNode prev = getPrevElementType(myChild2); if (prev != null && prev.getElementType() == mSL_COMMENT) { return Spacing.createSpacing(0, Integer.MAX_VALUE, 1, keepLineBreaks, mySettings.KEEP_BLANK_LINES_IN_CODE); } else if (dependantRange != null) { @@ -513,5 +510,12 @@ public class GroovySpacingProcessor extends GroovyElementVisitor { } } + static boolean isWhiteSpace(final ASTNode treePrev) { + return treePrev != null && (treePrev.getPsi() instanceof PsiWhiteSpace || treePrev.getTextLength() == 0); + } + + static ASTNode getPrevElementType(final ASTNode child) { + return FormatterUtil.getLeafNonSpaceBefore(child); + } } diff --git a/plugins/groovy/src/org/jetbrains/plugins/groovy/formatter/processors/GroovySpacingProcessorBasic.java b/plugins/groovy/src/org/jetbrains/plugins/groovy/formatter/processors/GroovySpacingProcessorBasic.java index 03f0a731f621..33fe296e7ad8 100644 --- a/plugins/groovy/src/org/jetbrains/plugins/groovy/formatter/processors/GroovySpacingProcessorBasic.java +++ b/plugins/groovy/src/org/jetbrains/plugins/groovy/formatter/processors/GroovySpacingProcessorBasic.java @@ -23,6 +23,7 @@ import com.intellij.psi.PsiErrorElement; import com.intellij.psi.codeStyle.CodeStyleSettings; import com.intellij.psi.tree.IElementType; import org.jetbrains.plugins.groovy.formatter.GroovyBlock; +import org.jetbrains.plugins.groovy.formatter.MethodCallWithoutQualifierBlock; import org.jetbrains.plugins.groovy.formatter.models.spacing.SpacingTokens; import org.jetbrains.plugins.groovy.lang.lexer.GroovyTokenTypes; import org.jetbrains.plugins.groovy.lang.parser.GroovyElementTypes; @@ -56,7 +57,7 @@ public abstract class GroovySpacingProcessorBasic extends SpacingTokens implemen //Braces Placement // For multi-line strings - if (!child1.getNode().getTextRange().equals(child1.getTextRange()) || !child2.getNode().getTextRange().equals(child2.getTextRange())) { + if (!mirrorsAst(child1) || !mirrorsAst(child2)) { return NO_SPACING; } @@ -220,6 +221,10 @@ public abstract class GroovySpacingProcessorBasic extends SpacingTokens implemen return COMMON_SPACING; } + private static boolean mirrorsAst(GroovyBlock block) { + return block.getNode().getTextRange().equals(block.getTextRange()) || block instanceof MethodCallWithoutQualifierBlock; + } + private static boolean isDollarInGStringInjection(ASTNode node) { return node.getElementType() == mDOLLAR && node.getTreeParent().getElementType() == GSTRING_INJECTION; } diff --git a/plugins/groovy/src/org/jetbrains/plugins/groovy/formatter/processors/SpacingUtil.java b/plugins/groovy/src/org/jetbrains/plugins/groovy/formatter/processors/SpacingUtil.java deleted file mode 100644 index f0237fd6284f..000000000000 --- a/plugins/groovy/src/org/jetbrains/plugins/groovy/formatter/processors/SpacingUtil.java +++ /dev/null @@ -1,101 +0,0 @@ -/* - * 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 org.jetbrains.plugins.groovy.formatter.processors; - -import com.intellij.lang.ASTNode; -import com.intellij.psi.PsiElement; -import com.intellij.psi.PsiWhiteSpace; -import com.intellij.psi.formatter.FormatterUtil; -import com.intellij.psi.impl.source.tree.LeafElement; -import com.intellij.psi.impl.source.tree.LeafPsiElement; -import com.intellij.psi.tree.IElementType; -import com.intellij.psi.tree.TokenSet; -import com.intellij.psi.util.PsiTreeUtil; -import org.jetbrains.annotations.NotNull; -import org.jetbrains.plugins.groovy.lang.groovydoc.lexer.GroovyDocTokenTypes; -import org.jetbrains.plugins.groovy.lang.groovydoc.parser.GroovyDocElementTypes; -import org.jetbrains.plugins.groovy.lang.groovydoc.psi.api.GrDocMemberReference; -import org.jetbrains.plugins.groovy.lang.lexer.GroovyTokenTypes; - -/** - * @author ilyas - */ -public abstract class SpacingUtil { - - static boolean isWhiteSpace(final ASTNode treePrev) { - return treePrev != null && (treePrev.getPsi() instanceof PsiWhiteSpace || treePrev.getTextLength() == 0); - } - - static boolean canStickChildrenTogether(final ASTNode child1, final ASTNode child2) { - if (child1 == null || child2 == null || isWhiteSpace(child1) || isWhiteSpace(child2)) return true; - return child1 instanceof LeafPsiElement || child2 instanceof LeafPsiElement; - } - - static boolean shouldKeepSpace(@NotNull final PsiElement parent) { - ASTNode node = parent.getNode(); - if (node == null) return true; - final IElementType type = node.getElementType(); - if (type == GroovyDocTokenTypes.mGDOC_TAG_VALUE_TOKEN) { - return PsiTreeUtil.getParentOfType(parent, GrDocMemberReference.class) != null; - } - - return type == GroovyTokenTypes.GROOVY_DOC_COMMENT || type == GroovyDocElementTypes.GDOC_TAG - || type == GroovyDocElementTypes.GDOC_INLINED_TAG; - } - - static ASTNode getLeafNonSpaceBefore(final ASTNode element) { - if (element == null) return null; - ASTNode treePrev = element.getTreePrev(); - if (treePrev != null) { - ASTNode candidate = getLastChildOf(treePrev); - if (candidate != null && !isWhiteSpace(candidate) && candidate.getTextLength() > 0) { - return candidate; - } else { - return getLeafNonSpaceBefore(candidate); - } - } - final ASTNode treeParent = element.getTreeParent(); - - if (treeParent == null || treeParent.getTreeParent() == null) { - return null; - } else { - return getLeafNonSpaceBefore(treeParent); - } - } - - private static ASTNode getLastChildOf(ASTNode element) { - if (element == null) { - return null; - } - if (element instanceof LeafElement) { - return element; - } else { - final ASTNode lastChild = element.getLastChildNode(); - if (lastChild == null) { - return element; - } else { - return getLastChildOf(lastChild); - } - } - } - - static ASTNode getPrevElementType(final ASTNode child) { - return FormatterUtil.getLeafNonSpaceBefore(child); - } - - static TokenSet COMMENT_BIT_SET = GroovyTokenTypes.COMMENT_SET; -} 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 32fc10ef030d..741a48c58f61 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 @@ -65,7 +65,6 @@ import java.util.*; import static com.intellij.patterns.PlatformPatterns.psiElement; import static com.intellij.patterns.PsiJavaPatterns.elementType; import static com.intellij.util.containers.CollectionFactory.hashMap; -import static org.jetbrains.plugins.groovy.lang.psi.util.GroovyPropertyUtils.*; /** * @author ilyas @@ -332,17 +331,14 @@ public class GroovyCompletionContributor extends CompletionContributor { } final int invocationCount = parameters.getInvocationCount(); - final boolean secondCompletionInvoked = invocationCount > 1; + final boolean firstCompletionInvoked = invocationCount < 2; final String prefix = result.getPrefixMatcher().getPrefix(); - final boolean skipAccessors = !secondCompletionInvoked && !prefix.startsWith(GET_PREFIX) && - !prefix.startsWith(SET_PREFIX) && - !prefix.startsWith(IS_PREFIX); + final boolean skipAccessors = firstCompletionInvoked && !prefix.startsWith("g") && !prefix.startsWith("s") && !prefix.startsWith("i"); + result.restartCompletionOnPrefixChange("g"); + result.restartCompletionOnPrefixChange("i"); + result.restartCompletionOnPrefixChange("s"); - - result.restartCompletionOnPrefixChange(GET_PREFIX); - result.restartCompletionOnPrefixChange(SET_PREFIX); - result.restartCompletionOnPrefixChange(IS_PREFIX); final Map staticMembers = hashMap(); final PsiElement qualifier = reference.getQualifier(); final PsiType qualifierType = qualifier instanceof GrExpression ? ((GrExpression)qualifier).getType() : null; @@ -372,7 +368,7 @@ public class GroovyCompletionContributor extends CompletionContributor { final boolean autopopup = parameters.getInvocationCount() == 0; //skip default groovy methods - if (!secondCompletionInvoked && + if (firstCompletionInvoked && object instanceof GrGdkMethod && GroovyCompletionUtil.skipDefGroovyMethod((GrGdkMethod)object, substitutor, qualifierType)) { if (!autopopup) { @@ -382,7 +378,7 @@ public class GroovyCompletionContributor extends CompletionContributor { } //skip operator methods - if (!secondCompletionInvoked && + if (firstCompletionInvoked && object instanceof PsiMethod && GroovyCompletionUtil.OPERATOR_METHOD_NAMES.contains(((PsiMethod)object).getName())) { if (!checkForIterator((PsiMethod)object)) { @@ -402,7 +398,7 @@ public class GroovyCompletionContributor extends CompletionContributor { } //skip inaccessible elements - if (!secondCompletionInvoked && resolveResult != null && !resolveResult.isAccessible()) { + if (firstCompletionInvoked && resolveResult != null && !resolveResult.isAccessible()) { if (!autopopup) { showInfo(); } 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 bb1dfb092112..c3460e93a181 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 @@ -228,14 +228,15 @@ public class GroovyCompletionUtil { if (importedName != null) { final GrCodeReferenceElement importReference = ((GrImportStatement)context).getImportReference(); if (importReference != null) { + boolean alias = ((GrImportStatement)context).isAliasedImport(); for (GroovyResolveResult r : importReference.multiResolve(false)) { final PsiElement resolved = r.getElement(); if (context.getManager().areElementsEquivalent(resolved, element)) { - return generateLookupForImportedElement(candidate, importedName); + return generateLookupForImportedElement(candidate, importedName, alias); } else { if (resolved instanceof PsiField && element instanceof PsiMethod && isAccessorFor((PsiMethod)element, (PsiField)resolved)) { - return generateLookupForImportedElement(candidate, getAccessorPrefix((PsiMethod)element) + capitalize(importedName)); + return generateLookupForImportedElement(candidate, getAccessorPrefix((PsiMethod)element) + capitalize(importedName), alias); } } } @@ -268,9 +269,13 @@ public class GroovyCompletionUtil { return AllClassesGetter.createLookupItem(psiClass, new GroovyClassNameInsertHandler()); } - private static LookupElementBuilder generateLookupForImportedElement(GroovyResolveResult resolveResult, String importedName) { + private static LookupElement generateLookupForImportedElement(GroovyResolveResult resolveResult, String importedName, boolean alias) { final PsiElement element = resolveResult.getElement(); assert element != null; + if (!alias && element instanceof PsiClass) { + return createClassLookupItem((PsiClass)element); + } + final PsiSubstitutor substitutor = resolveResult.getSubstitutor(); LookupElementBuilder builder = LookupElementBuilder.create(resolveResult, importedName).setPresentableText(importedName); return setupLookupBuilder(element, substitutor, builder); diff --git a/plugins/groovy/src/org/jetbrains/plugins/groovy/lang/parser/parsing/statements/SwitchStatement.java b/plugins/groovy/src/org/jetbrains/plugins/groovy/lang/parser/parsing/statements/SwitchStatement.java index 33656a2a85cc..210910a19667 100644 --- a/plugins/groovy/src/org/jetbrains/plugins/groovy/lang/parser/parsing/statements/SwitchStatement.java +++ b/plugins/groovy/src/org/jetbrains/plugins/groovy/lang/parser/parsing/statements/SwitchStatement.java @@ -67,11 +67,7 @@ public class SwitchStatement implements GroovyElementTypes { ParserUtils.getToken(builder, mLCURLY); ParserUtils.getToken(builder, mNLS); - while (true) { - if (ParserUtils.getToken(builder, mRCURLY)) { - return; - } - + while (!ParserUtils.getToken(builder, mRCURLY)) { if (builder.getTokenType() != kCASE && builder.getTokenType() != kDEFAULT) { builder.error("case, default or } expected"); ParserUtils.skipCountingBraces(builder, TokenSet.create(kCASE, kDEFAULT, mRCURLY)); @@ -104,8 +100,8 @@ public class SwitchStatement implements GroovyElementTypes { PsiBuilder.Marker label = builder.mark(); builder.advanceLexer(); - if (kCASE.equals(elem)) { - AssignmentExpression.parse(builder, parser, true); + if (kCASE.equals(elem) && !AssignmentExpression.parse(builder, parser)) { + builder.error(GroovyBundle.message("expression.expected")); } ParserUtils.getToken(builder, mCOLON, GroovyBundle.message("colon.expected")); label.done(CASE_LABEL); diff --git a/plugins/groovy/src/org/jetbrains/plugins/groovy/lang/psi/api/statements/GrSwitchStatement.java b/plugins/groovy/src/org/jetbrains/plugins/groovy/lang/psi/api/statements/GrSwitchStatement.java index d7773c4d1797..ddc2a0a76209 100644 --- a/plugins/groovy/src/org/jetbrains/plugins/groovy/lang/psi/api/statements/GrSwitchStatement.java +++ b/plugins/groovy/src/org/jetbrains/plugins/groovy/lang/psi/api/statements/GrSwitchStatement.java @@ -16,14 +16,19 @@ package org.jetbrains.plugins.groovy.lang.psi.api.statements; +import org.jetbrains.annotations.NotNull; +import org.jetbrains.annotations.Nullable; import org.jetbrains.plugins.groovy.lang.psi.GroovyPsiElement; -import org.jetbrains.plugins.groovy.lang.psi.api.auxiliary.GrCondition; import org.jetbrains.plugins.groovy.lang.psi.api.statements.clauses.GrCaseSection; +import org.jetbrains.plugins.groovy.lang.psi.api.statements.expressions.GrExpression; /** * @author ilyas */ public interface GrSwitchStatement extends GroovyPsiElement, GrStatement { - GrCondition getCondition(); + @Nullable + GrExpression getCondition(); + + @NotNull GrCaseSection[] getCaseSections(); } diff --git a/plugins/groovy/src/org/jetbrains/plugins/groovy/lang/psi/api/statements/clauses/GrCaseLabel.java b/plugins/groovy/src/org/jetbrains/plugins/groovy/lang/psi/api/statements/clauses/GrCaseLabel.java index 2f7aeb219198..d736ffb04b6a 100644 --- a/plugins/groovy/src/org/jetbrains/plugins/groovy/lang/psi/api/statements/clauses/GrCaseLabel.java +++ b/plugins/groovy/src/org/jetbrains/plugins/groovy/lang/psi/api/statements/clauses/GrCaseLabel.java @@ -16,10 +16,14 @@ package org.jetbrains.plugins.groovy.lang.psi.api.statements.clauses; +import org.jetbrains.annotations.Nullable; import org.jetbrains.plugins.groovy.lang.psi.GroovyPsiElement; +import org.jetbrains.plugins.groovy.lang.psi.api.statements.expressions.GrExpression; /** * @author ilyas */ public interface GrCaseLabel extends GroovyPsiElement { + @Nullable + GrExpression getValue(); } diff --git a/plugins/groovy/src/org/jetbrains/plugins/groovy/lang/psi/impl/statements/GrSwitchStatementImpl.java b/plugins/groovy/src/org/jetbrains/plugins/groovy/lang/psi/impl/statements/GrSwitchStatementImpl.java index b5b5f0e7e72c..af3967d19973 100644 --- a/plugins/groovy/src/org/jetbrains/plugins/groovy/lang/psi/impl/statements/GrSwitchStatementImpl.java +++ b/plugins/groovy/src/org/jetbrains/plugins/groovy/lang/psi/impl/statements/GrSwitchStatementImpl.java @@ -19,9 +19,9 @@ package org.jetbrains.plugins.groovy.lang.psi.impl.statements; import com.intellij.lang.ASTNode; import org.jetbrains.annotations.NotNull; import org.jetbrains.plugins.groovy.lang.psi.GroovyElementVisitor; -import org.jetbrains.plugins.groovy.lang.psi.api.auxiliary.GrCondition; import org.jetbrains.plugins.groovy.lang.psi.api.statements.GrSwitchStatement; 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.impl.GroovyPsiElementImpl; /** @@ -41,10 +41,11 @@ public class GrSwitchStatementImpl extends GroovyPsiElementImpl implements GrSwi return "Switch statement"; } - public GrCondition getCondition() { - return findChildByClass(GrCondition.class); + public GrExpression getCondition() { + return findChildByClass(GrExpression.class); } + @NotNull public GrCaseSection[] getCaseSections() { return findChildrenByClass(GrCaseSection.class); } diff --git a/plugins/groovy/src/org/jetbrains/plugins/groovy/lang/psi/impl/statements/clauses/GrCaseLabelImpl.java b/plugins/groovy/src/org/jetbrains/plugins/groovy/lang/psi/impl/statements/clauses/GrCaseLabelImpl.java index d99625bc3726..39f3c03fd548 100644 --- a/plugins/groovy/src/org/jetbrains/plugins/groovy/lang/psi/impl/statements/clauses/GrCaseLabelImpl.java +++ b/plugins/groovy/src/org/jetbrains/plugins/groovy/lang/psi/impl/statements/clauses/GrCaseLabelImpl.java @@ -20,6 +20,7 @@ import com.intellij.lang.ASTNode; import org.jetbrains.annotations.NotNull; import org.jetbrains.plugins.groovy.lang.psi.GroovyElementVisitor; import org.jetbrains.plugins.groovy.lang.psi.api.statements.clauses.GrCaseLabel; +import org.jetbrains.plugins.groovy.lang.psi.api.statements.expressions.GrExpression; import org.jetbrains.plugins.groovy.lang.psi.impl.GroovyPsiElementImpl; /** @@ -38,4 +39,9 @@ public class GrCaseLabelImpl extends GroovyPsiElementImpl implements GrCaseLabel public String toString() { return "Case label"; } + + @Override + public GrExpression getValue() { + return findChildByClass(GrExpression.class); + } } \ No newline at end of file diff --git a/plugins/groovy/src/org/jetbrains/plugins/groovy/refactoring/convertToJava/CodeBlockGenerator.java b/plugins/groovy/src/org/jetbrains/plugins/groovy/refactoring/convertToJava/CodeBlockGenerator.java index d28e8a386d2f..a7197c918cc3 100644 --- a/plugins/groovy/src/org/jetbrains/plugins/groovy/refactoring/convertToJava/CodeBlockGenerator.java +++ b/plugins/groovy/src/org/jetbrains/plugins/groovy/refactoring/convertToJava/CodeBlockGenerator.java @@ -17,7 +17,10 @@ package org.jetbrains.plugins.groovy.refactoring.convertToJava; import com.intellij.openapi.diagnostic.Logger; import com.intellij.openapi.project.Project; -import com.intellij.psi.*; +import com.intellij.psi.CommonClassNames; +import com.intellij.psi.JavaPsiFacade; +import com.intellij.psi.PsiElement; +import com.intellij.psi.PsiType; import org.jetbrains.annotations.Nullable; import org.jetbrains.plugins.groovy.lang.psi.GroovyPsiElement; import org.jetbrains.plugins.groovy.lang.psi.api.auxiliary.GrCondition; @@ -32,7 +35,9 @@ import org.jetbrains.plugins.groovy.lang.psi.api.statements.branch.GrAssertState import org.jetbrains.plugins.groovy.lang.psi.api.statements.branch.GrFlowInterruptingStatement; import org.jetbrains.plugins.groovy.lang.psi.api.statements.branch.GrReturnStatement; import org.jetbrains.plugins.groovy.lang.psi.api.statements.branch.GrThrowStatement; -import org.jetbrains.plugins.groovy.lang.psi.api.statements.clauses.*; +import org.jetbrains.plugins.groovy.lang.psi.api.statements.clauses.GrForClause; +import org.jetbrains.plugins.groovy.lang.psi.api.statements.clauses.GrForInClause; +import org.jetbrains.plugins.groovy.lang.psi.api.statements.clauses.GrTraditionalForClause; import org.jetbrains.plugins.groovy.lang.psi.api.statements.expressions.GrExpression; import org.jetbrains.plugins.groovy.lang.psi.api.statements.params.GrParameter; import org.jetbrains.plugins.groovy.lang.psi.api.statements.typedef.GrTypeDefinition; @@ -219,6 +224,7 @@ public class CodeBlockGenerator extends Generator { final StringBuilder builder = new StringBuilder(); final GrForClause clause = forStatement.getClause(); + ExpressionContext forContext = context.extend(); if (clause instanceof GrForInClause) { final GrExpression expression = ((GrForInClause)clause).getIteratedExpression(); final GrVariable declaredVariable = clause.getDeclaredVariable(); @@ -228,7 +234,7 @@ public class CodeBlockGenerator extends Generator { writeVariableWithoutColon(builder, declaredVariable); builder.append(" : "); if (expression != null) { - final ExpressionContext context = this.context.copy(); + final ExpressionContext context = forContext.copy(); expression.accept(new ExpressionGenerator(builder, context)); } builder.append(")"); @@ -244,7 +250,7 @@ public class CodeBlockGenerator extends Generator { writeVariableWithoutColon(partBuilder, (GrParameter)initialization); final GrExpression initializer = ((GrParameter)initialization).getDefaultInitializer(); if (initializer != null) { - final ExpressionContext partContext = context.copy(); + final ExpressionContext partContext = forContext.copy(); initializer.accept(new ExpressionGenerator(partBuilder, partContext)); for (String statement : partContext.myStatements) { builder.append(statement).append(", "); @@ -255,30 +261,28 @@ public class CodeBlockGenerator extends Generator { else { if (initialization != null) { StringBuilder partBuilder = new StringBuilder(); - final ExpressionContext partContext = this.context.copy(); + final ExpressionContext partContext = forContext.copy(); genForPart(builder, initialization, new CodeBlockGenerator(partBuilder, partContext)); } } builder.append(";"); if (condition != null) { - genForPart(builder, condition); + genForPart(builder, condition, forContext.copy()); } builder.append(";"); if (update != null) { - genForPart(builder, update); + genForPart(builder, update, forContext.copy()); } builder.append(")"); } - forStatement.getBody().accept(new CodeBlockGenerator(builder, context)); + forStatement.getBody().accept(new CodeBlockGenerator(builder, forContext)); } - private void genForPart(StringBuilder builder, GrExpression part) { - StringBuilder partBuilder = new StringBuilder(); - final ExpressionContext partContext = this.context.copy(); - genForPart(builder, part, new ExpressionGenerator(partBuilder, partContext)); + private static void genForPart(StringBuilder builder, GrExpression part, final ExpressionContext context) { + genForPart(builder, part, new ExpressionGenerator(new StringBuilder(), context)); } private static void genForPart(StringBuilder builder, GroovyPsiElement part, final Generator visitor) { @@ -299,57 +303,63 @@ public class CodeBlockGenerator extends Generator { @Override public void visitWhileStatement(GrWhileStatement whileStatement) { - //todo + final GrCondition condition = whileStatement.getCondition(); + final GrStatement body = whileStatement.getBody(); + + StringBuilder builder = new StringBuilder(); + builder.append("while ("); + final ExpressionContext copy = context.copy(); + if (condition != null) { + condition.accept(new ExpressionGenerator(builder, copy)); + } + builder.append(" )"); + if (body != null) { + body.accept(new CodeBlockGenerator(builder, copy.extend())); + } + writeStatement(builder, whileStatement, copy); } @Override public void visitSwitchStatement(GrSwitchStatement switchStatement) { - super.visitSwitchStatement(switchStatement); //To change body of overridden methods use File | Settings | File Templates. - } - - @Override - public void visitCaseSection(GrCaseSection caseSection) { - super.visitCaseSection(caseSection); //To change body of overridden methods use File | Settings | File Templates. - } - - @Override - public void visitCaseLabel(GrCaseLabel caseLabel) { - super.visitCaseLabel(caseLabel); //To change body of overridden methods use File | Settings | File Templates. - } - - @Override - public void visitForInClause(GrForInClause forInClause) { - super.visitForInClause(forInClause); //To change body of overridden methods use File | Settings | File Templates. - } - - @Override - public void visitForClause(GrForClause forClause) { - super.visitForClause(forClause); //To change body of overridden methods use File | Settings | File Templates. - } - - @Override - public void visitTraditionalForClause(GrTraditionalForClause forClause) { - super.visitTraditionalForClause(forClause); //To change body of overridden methods use File | Settings | File Templates. + //todo } @Override public void visitTryStatement(GrTryCatchStatement tryCatchStatement) { - super.visitTryStatement(tryCatchStatement); //To change body of overridden methods use File | Settings | File Templates. - } - - @Override - public void visitBlockStatement(GrBlockStatement blockStatement) { - super.visitBlockStatement(blockStatement); //To change body of overridden methods use File | Settings | File Templates. + final GrOpenBlock tryBlock = tryCatchStatement.getTryBlock(); + final GrCatchClause[] catchClauses = tryCatchStatement.getCatchClauses(); + final GrFinallyClause finallyClause = tryCatchStatement.getFinallyClause(); + builder.append("try"); + tryBlock.accept(this); + for (GrCatchClause catchClause : catchClauses) { + catchClause.accept(this); + } + if (finallyClause != null) { + finallyClause.accept(this); + } } @Override public void visitCatchClause(GrCatchClause catchClause) { - super.visitCatchClause(catchClause); //To change body of overridden methods use File | Settings | File Templates. + final GrParameter parameter = catchClause.getParameter(); + builder.append("catch ("); + writeVariableWithoutColon(builder, parameter); + builder.append(") "); + final GrOpenBlock body = catchClause.getBody(); + if (body != null) { + body.accept(this); + } } @Override - public void visitFinallyClause(GrFinallyClause catchClause) { - super.visitFinallyClause(catchClause); //To change body of overridden methods use File | Settings | File Templates. + public void visitFinallyClause(GrFinallyClause finallyClause) { + builder.append("finally "); + finallyClause.getBody().accept(this); + } + + @Override + public void visitBlockStatement(GrBlockStatement blockStatement) { + //todo } @Override @@ -369,13 +379,14 @@ public class CodeBlockGenerator extends Generator { @Override public void visitVariableDeclaration(GrVariableDeclaration variableDeclaration) { - final GrModifierList modifierList = variableDeclaration.getModifierList(); //todo + final GrModifierList modifierList = variableDeclaration.getModifierList(); final GrVariable[] variables = variableDeclaration.getVariables(); - StringBuilder builder=new StringBuilder(); + StringBuilder builder = new StringBuilder(); ExpressionContext expressionContext = context.copy(); final ExpressionGenerator expressionGenerator = new ExpressionGenerator(builder, expressionContext); + if (variableDeclaration.isTuple()) { final GrTupleDeclaration tuple = variableDeclaration.getTupleDeclaration(); final GrExpression tupleInitializer = tuple.getInitializerGroovy(); @@ -384,6 +395,7 @@ public class CodeBlockGenerator extends Generator { for (int i = 0; i < variables.length; i++) { final GrVariable v = variables[i]; final PsiType type = v.getDeclaredType(); + GenerationUtil.writeModifiers(builder, modifierList); GenerationUtil.writeType(builder, type); builder.append(" ").append(v.getName()); if (i < initializers.length) { @@ -396,12 +408,13 @@ public class CodeBlockGenerator extends Generator { else { final PsiType iteratorType = JavaPsiFacade.getElementFactory(context.project).createTypeFromText(CommonClassNames.JAVA_UTIL_ITERATOR, variableDeclaration); - final String iteratorName = GenerationUtil.suggestVarName(iteratorType,variableDeclaration, expressionContext); + final String iteratorName = GenerationUtil.suggestVarName(iteratorType, variableDeclaration, expressionContext); builder.append("final ").append(CommonClassNames.JAVA_UTIL_ITERATOR).append(" ").append(iteratorName).append(" = "); GenerationUtil.invokeMethodByName(tupleInitializer, "iterator", GrExpression.EMPTY_ARRAY, GrNamedArgument.EMPTY_ARRAY, GrClosableBlock.EMPTY_ARRAY, expressionGenerator, variableDeclaration); for (final GrVariable v : variables) { + GenerationUtil.writeModifiers(builder, modifierList); final PsiType type = v.getDeclaredType(); GenerationUtil.writeType(builder, type); builder.append(" ").append(v.getName()); @@ -410,13 +423,12 @@ public class CodeBlockGenerator extends Generator { } } else { + GenerationUtil.writeModifiers(builder, modifierList); final GrTypeElement typeElement = variableDeclaration.getTypeElementGroovy(); PsiType type = typeElement == null ? PsiType.getJavaLangObject(variableDeclaration.getManager(), variableDeclaration.getResolveScope()) : typeElement.getType(); GenerationUtil.writeType(builder, type); - - } writeStatement(builder, variableDeclaration, expressionContext); } diff --git a/plugins/groovy/src/org/jetbrains/plugins/groovy/refactoring/convertToJava/ExpressionContext.java b/plugins/groovy/src/org/jetbrains/plugins/groovy/refactoring/convertToJava/ExpressionContext.java index 1d636c05d448..01a04fa9b598 100644 --- a/plugins/groovy/src/org/jetbrains/plugins/groovy/refactoring/convertToJava/ExpressionContext.java +++ b/plugins/groovy/src/org/jetbrains/plugins/groovy/refactoring/convertToJava/ExpressionContext.java @@ -39,4 +39,10 @@ class ExpressionContext { ExpressionContext copy() { return new ExpressionContext(project, myUsedVarNames); } + + ExpressionContext extend() { + final HashSet usedVarNames = new HashSet(); + usedVarNames.addAll(myUsedVarNames); + return new ExpressionContext(project, usedVarNames); + } } \ No newline at end of file diff --git a/plugins/groovy/src/org/jetbrains/plugins/groovy/refactoring/convertToJava/GenerationUtil.java b/plugins/groovy/src/org/jetbrains/plugins/groovy/refactoring/convertToJava/GenerationUtil.java index 4b368a23ea9b..3cca78c1bb92 100644 --- a/plugins/groovy/src/org/jetbrains/plugins/groovy/refactoring/convertToJava/GenerationUtil.java +++ b/plugins/groovy/src/org/jetbrains/plugins/groovy/refactoring/convertToJava/GenerationUtil.java @@ -129,6 +129,10 @@ public class GenerationUtil { argumentListGenerator.generate(null, exprs, namedArgs, closureArgs, psiContext); } + public static boolean writeModifiers(StringBuilder text, PsiModifierList modifierList) { + return writeModifiers(text, modifierList, JAVA_MODIFIERS); + } + public static boolean writeModifiers(StringBuilder text, PsiModifierList modifierList, String[] modifiers) { boolean wasAddedModifiers = false; for (String modifierType : modifiers) { diff --git a/plugins/groovy/test/org/jetbrains/plugins/groovy/compiler/GroovyDebuggerEvaluatorTest.groovy b/plugins/groovy/test/org/jetbrains/plugins/groovy/compiler/GroovyDebuggerEvaluatorTest.groovy deleted file mode 100644 index a2898ce49b07..000000000000 --- a/plugins/groovy/test/org/jetbrains/plugins/groovy/compiler/GroovyDebuggerEvaluatorTest.groovy +++ /dev/null @@ -1,65 +0,0 @@ -package org.jetbrains.plugins.groovy.compiler; - -import com.intellij.debugger.engine.evaluation.CodeFragmentFactory; -import com.intellij.debugger.engine.evaluation.CodeFragmentKind; -import com.intellij.debugger.engine.evaluation.TextWithImportsImpl; -import com.intellij.psi.JavaCodeFragment; -import com.intellij.psi.PsiElement; -import groovy.lang.GroovyShell; -import org.jetbrains.plugins.groovy.LightGroovyTestCase; -import org.jetbrains.plugins.groovy.debugger.GroovyCodeFragmentFactory; - -import java.io.IOException; - -/** - * @author peter - */ -public class GroovyDebuggerEvaluatorTest extends LightGroovyTestCase { - - public void testSimpleVariable() throws Exception { - evaluates """def a = 2 -a++""", - "a", - "[a:a] -> a" - } - - public void testVariableInsideClosure() throws Exception { - evaluates """def a = 2 -Closure c = { a++; a } -c() -a++""", - "a", - "[a:this.a] -> a" - } - - public void testQualifyClassNames() throws Exception { - myFixture.addFileToProject("com/Foo.groovy", """ -package com -class Foo { static bar = 2 }""") - - def bar = myFixture.addFileToProject("com/Bar.groovy", """ -package com -println 2""") - - myFixture.configureFromExistingVirtualFile bar.virtualFile - - evaluates "Foo.bar", "[:] -> com.Foo.bar" - } - - private void evaluates(String text, String expression, String expected) throws IOException { - myFixture.configureByText("_.groovy", text); - evaluates(expression, expected) - } - - private def evaluates(String expression, String expected) { - def context = myFixture.file.findElementAt(myFixture.editor.caretModel.offset); - def pair = GroovyCodeFragmentFactory.externalParameters(expression, context) - - assertEquals expected, pair.first.toString() + " -> " + pair.second.text - } - - @Override - protected String getBasePath() { - return ""; - } -} diff --git a/plugins/groovy/test/org/jetbrains/plugins/groovy/compiler/GroovyDebuggerTest.groovy b/plugins/groovy/test/org/jetbrains/plugins/groovy/compiler/GroovyDebuggerTest.groovy index f0147603daf3..2d86c68d3bfd 100644 --- a/plugins/groovy/test/org/jetbrains/plugins/groovy/compiler/GroovyDebuggerTest.groovy +++ b/plugins/groovy/test/org/jetbrains/plugins/groovy/compiler/GroovyDebuggerTest.groovy @@ -36,6 +36,7 @@ import com.intellij.testFramework.builders.JavaModuleFixtureBuilder import com.intellij.util.concurrency.Semaphore import org.jetbrains.plugins.groovy.debugger.GroovyPositionManager import com.intellij.execution.runners.ProgramRunner +import com.intellij.openapi.fileEditor.FileDocumentManager /** * @author peter @@ -73,11 +74,11 @@ class GroovyDebuggerTest extends GroovyCompilerTestCase { moduleBuilder.addJdk(System.getenv('JAVA_HOME')) } - private void runDebugger(Closure cl) { + private void runDebugger(String mainClass, Closure cl) { make() edt { ProgramRunner runner = ProgramRunner.PROGRAM_RUNNER_EP.extensions.find { it.class == GenericDebuggerRunner } - runProcess('Foo', myModule, DefaultDebugExecutor, [onTextAvailable: { evt, type -> print evt.text}] as ProcessAdapter, runner) + runProcess(mainClass, myModule, DefaultDebugExecutor, [onTextAvailable: { evt, type -> print evt.text}] as ProcessAdapter, runner) } cl.call() resume() @@ -85,19 +86,63 @@ class GroovyDebuggerTest extends GroovyCompilerTestCase { } public void testSimpleEvaluate() { - def foo = myFixture.addFileToProject("Foo.groovy", "println 'hello'"); - - edt { - DebuggerManagerImpl.getInstanceEx(project).breakpointManager.addLineBreakpoint(foo.viewProvider.document, 0) - } - - runDebugger { + myFixture.addFileToProject("Foo.groovy", "println 'hello'"); + addBreakpoint 'Foo.groovy', 0 + runDebugger 'Foo', { waitForBreakpoint() eval '2?:3', '2' eval 'null?:3', '3' } } + public void testVariableInScript() { + myFixture.addFileToProject("Foo.groovy", """def a = 2 +a"""); + addBreakpoint 'Foo.groovy', 1 + runDebugger 'Foo', { + waitForBreakpoint() + eval 'a', '2' + } + } + + public void testVariableInsideClosure() { + myFixture.addFileToProject("Foo.groovy", """def a = 2 +Closure c = { + a++; + a //3 +} +c() +a++"""); + addBreakpoint 'Foo.groovy', 3 + runDebugger 'Foo', { + waitForBreakpoint() + eval 'a', '3' + } + } + + public void testQualifyClassNames() { + myFixture.addFileToProject("com/Foo.groovy", """ +package com +class Foo { static bar = 2 }""") + + + myFixture.addFileToProject("com/Bar.groovy", """package com +println 2""") + + addBreakpoint 'com/Bar.groovy', 1 + runDebugger 'com.Bar', { + waitForBreakpoint() + eval 'Foo.bar', '2' + } + } + + private def addBreakpoint(String fileName, int line) { + edt { + def file = myFixture.tempDirFixture.getFile(fileName) + DebuggerManagerImpl.getInstanceEx(project).breakpointManager.addLineBreakpoint(FileDocumentManager.instance.getDocument(file), line) + } + } + private def resume() { debugProcess.managerThread.invoke(debugProcess.createResumeCommand(debugProcess.suspendManager.pausedContext)) } diff --git a/plugins/groovy/test/org/jetbrains/plugins/groovy/completion/GroovyClassNameCompletionTest.groovy b/plugins/groovy/test/org/jetbrains/plugins/groovy/completion/GroovyClassNameCompletionTest.groovy index 78d50f33f80a..3df0a95e34c2 100644 --- a/plugins/groovy/test/org/jetbrains/plugins/groovy/completion/GroovyClassNameCompletionTest.groovy +++ b/plugins/groovy/test/org/jetbrains/plugins/groovy/completion/GroovyClassNameCompletionTest.groovy @@ -27,8 +27,10 @@ import com.intellij.testFramework.fixtures.LightCodeInsightFixtureTestCase import org.jetbrains.annotations.NotNull import org.jetbrains.annotations.Nullable import org.jetbrains.plugins.groovy.util.TestUtils +import com.intellij.codeInsight.lookup.LookupElementPresentation +import com.intellij.codeInsight.lookup.LookupElement - /** +/** * @author Maxim.Medvedev */ public class GroovyClassNameCompletionTest extends LightCodeInsightFixtureTestCase { @@ -118,6 +120,11 @@ class Foo { abcme }""") def item = myFixture.complete(CompletionType.CLASS_NAME)[0] + + LookupElementPresentation presentation = renderElement(item) + assert "Foo.abcmethod1" == presentation.itemText + assert presentation.tailText == "(int a)" + ((StaticallyImportable) item).shouldBeImported = true myFixture.type('\n') myFixture.checkResult """import static Foo.abcmethod1 @@ -196,7 +203,12 @@ import static foo.Foo.anotherMethod anotherMethod() abcmex""") - assertOneElement myFixture.complete(CompletionType.CLASS_NAME)[0] + def element = assertOneElement(myFixture.complete(CompletionType.CLASS_NAME)[0]) + + LookupElementPresentation presentation = renderElement(element) + assert "abcMethod" == presentation.itemText + assert presentation.tailText == "() in Foo (foo)" + myFixture.type('\t') myFixture.checkResult """ import static foo.Foo.anotherMethod @@ -207,6 +219,12 @@ abcMethod()""" } + private LookupElementPresentation renderElement(LookupElement element) { + def presentation = new LookupElementPresentation() + element.renderElement(presentation) + return presentation + } + public void testNewClassName() { addClassToProject("foo", "Fxoo") myFixture.configureByText("a.groovy", "new Fxo\n") @@ -221,7 +239,6 @@ new Fxoo()\n""" myFixture.configureByText("a.groovy", "new ArrayLi\n") myFixture.completeBasic() myFixture.checkResult "new ArrayList()\n" - } public void testOnlyAnnotationsAfterAt() { @@ -244,5 +261,12 @@ new Fxoo()\n""" myFixture.checkResult 'def s = """a\njava.lang.ArrayIndexOutOfBoundsException\na"""' } + public void testDoubleClass() { + myFixture.addClass "package foo; public class Zooooooo {}" + myFixture.configureByText("a.groovy", """import foo.Zooooooo +Zoooox""") + assertOneElement(myFixture.completeBasic()) + } + } 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 29a094846d2b..ef233c91590e 100644 --- a/plugins/groovy/test/org/jetbrains/plugins/groovy/completion/GroovyCompletionTest.groovy +++ b/plugins/groovy/test/org/jetbrains/plugins/groovy/completion/GroovyCompletionTest.groovy @@ -657,4 +657,32 @@ return foo()""" checkCompletion "assex", ' ', 'assert x' } + public void testDontShowAccessors() { + assertNull doContainsTest("getFoo", """ +class MyClass { + def foo +} + +def a = new MyClass() +a.""") + } + + private doContainsTest(String itemToCheck, String text) { + myFixture.configureByText "a.groovy", text + + final LookupElement[] completion = myFixture.completeBasic() + return completion.find {println it.lookupString;itemToCheck == it.lookupString} + } + + + public void testShowAccessor() { + assertNotNull doContainsTest("getFoo", """ +class MyClass { + def foo +} + +def a = new MyClass() +a.g +""") + } } \ No newline at end of file diff --git a/plugins/groovy/test/org/jetbrains/plugins/groovy/lang/formatter/FormatterTest.java b/plugins/groovy/test/org/jetbrains/plugins/groovy/lang/formatter/FormatterTest.java index 7b02ce552336..c7cd604d465c 100644 --- a/plugins/groovy/test/org/jetbrains/plugins/groovy/lang/formatter/FormatterTest.java +++ b/plugins/groovy/test/org/jetbrains/plugins/groovy/lang/formatter/FormatterTest.java @@ -129,11 +129,20 @@ public class FormatterTest extends GroovyFormatterTestCase { } public void testCaseInSwitchIndented() throws Throwable { doTest(); } + public void testStuffAfterLineComments() throws Throwable { doTest(); } + + public void testAnonymousInCall() throws Throwable { + myTempSettings.ALIGN_MULTILINE_PARAMETERS_IN_CALLS = true; + doTest(); + } + public void testClosureParametersAligned() throws Throwable { myTempSettings.ALIGN_MULTILINE_PARAMETERS_IN_CALLS = true; doTest(); } + public void testChainCallWithClosures() throws Throwable { doTest(); } + public void doTest() throws Throwable { final List data = TestUtils.readInput(getTestDataPath() + getTestName(true) + ".test"); checkFormatting(data.get(0), data.get(1)); 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 2d4f42bb7635..3e3154d4ebff 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 @@ -112,6 +112,7 @@ public class StatementsParsingTest extends GroovyParsingTestCase { public void testSwitch$swit5() throws Throwable { doTest(); } public void testSwitch$swit6() throws Throwable { doTest(); } public void testSwitch$swit7() throws Throwable { doTest(); } + public void testSwitch$swit8() throws Throwable { doTest(); } public void testSyn$syn1() throws Throwable { doTest(); } public void testTop_methods$method1() throws Throwable { doTest(); } public void testTop_methods$method2() throws Throwable { doTest(); } diff --git a/plugins/groovy/test/org/jetbrains/plugins/groovy/lang/resolve/ResolvePropertyTest.groovy b/plugins/groovy/test/org/jetbrains/plugins/groovy/lang/resolve/ResolvePropertyTest.groovy index 26c9eb996910..44146920115f 100644 --- a/plugins/groovy/test/org/jetbrains/plugins/groovy/lang/resolve/ResolvePropertyTest.groovy +++ b/plugins/groovy/test/org/jetbrains/plugins/groovy/lang/resolve/ResolvePropertyTest.groovy @@ -649,7 +649,7 @@ setFoo(2) assertTrue GroovyRefactoringUtil.isLocalVariable(resolved) } - public void testResolveForVarOutsideOfFor() { + public void _testResolveForVarOutsideOfFor() { final PsiElement resolved = resolve("A.groovy") assertInstanceOf resolved, GrParameter } diff --git a/plugins/groovy/testdata/groovy/formatter/anonymousInCall.test b/plugins/groovy/testdata/groovy/formatter/anonymousInCall.test new file mode 100644 index 000000000000..8b2a94304145 --- /dev/null +++ b/plugins/groovy/testdata/groovy/formatter/anonymousInCall.test @@ -0,0 +1,11 @@ + bar(new Runnable() { + void run() { + + } + }) +----- +bar(new Runnable() { + void run() { + + } +}) \ No newline at end of file diff --git a/plugins/groovy/testdata/groovy/formatter/chainCallWithClosures.test b/plugins/groovy/testdata/groovy/formatter/chainCallWithClosures.test new file mode 100644 index 000000000000..d91effef7e0e --- /dev/null +++ b/plugins/groovy/testdata/groovy/formatter/chainCallWithClosures.test @@ -0,0 +1,27 @@ +[1, 2, 3, 4]. + toSet(). + findAllXxx { + it > 2 +}. + collect({ + it as String +}). +smthElse(new Runnable() { + void run() { + + } + }) +----- +[1, 2, 3, 4]. + toSet(). + findAllXxx { + it > 2 + }. + collect({ + it as String + }). + smthElse(new Runnable() { + void run() { + + } + }) \ No newline at end of file diff --git a/plugins/groovy/testdata/groovy/formatter/stuffAfterLineComments.test b/plugins/groovy/testdata/groovy/formatter/stuffAfterLineComments.test new file mode 100644 index 000000000000..845f79bc2f08 --- /dev/null +++ b/plugins/groovy/testdata/groovy/formatter/stuffAfterLineComments.test @@ -0,0 +1,37 @@ +def f( + a + // comment for this formal parameter +, b) +{ + [ a + b + // comment for this formula + , a * b + , a / b + ].collect { it * 2 } +} + +f( + 1 +// comment for this actual parameter +, 2 + // comment in non-first column + , 3 +) +----- +def f( + a + // comment for this formal parameter + , b) { + [a + b + // comment for this formula + , a * b, a / b + ].collect { it * 2 } +} + +f( + 1 +// comment for this actual parameter + , 2 + // comment in non-first column + , 3 +) \ No newline at end of file diff --git a/plugins/groovy/testdata/parsing/groovy/statements/switch/swit5.test b/plugins/groovy/testdata/parsing/groovy/statements/switch/swit5.test index caa27773e6a6..fbbcd424a617 100644 --- a/plugins/groovy/testdata/parsing/groovy/statements/switch/swit5.test +++ b/plugins/groovy/testdata/parsing/groovy/statements/switch/swit5.test @@ -18,16 +18,15 @@ Groovy script Case label PsiElement(case)('case') PsiWhiteSpace(' ') - Call expression - Literal - PsiElement(Integer)('1') - PsiWhiteSpace(' ') - Command arguments - Reference expression - PsiElement(identifier)('expr1') + Literal + PsiElement(Integer)('1') PsiErrorElement:':' expected - PsiElement(new line)('\n') + PsiWhiteSpace(' ') + Reference expression + PsiElement(identifier)('expr1') + PsiElement(new line)('\n') + Case section Case label PsiElement(default)('default') PsiElement(:)(':') @@ -40,4 +39,4 @@ Groovy script Literal PsiElement(string)(''abc'') PsiElement(new line)('\n') - PsiElement(})('}') + PsiElement(})('}') \ No newline at end of file diff --git a/plugins/groovy/testdata/parsing/groovy/statements/switch/swit8.test b/plugins/groovy/testdata/parsing/groovy/statements/switch/swit8.test new file mode 100644 index 000000000000..df18edc62102 --- /dev/null +++ b/plugins/groovy/testdata/parsing/groovy/statements/switch/swit8.test @@ -0,0 +1,33 @@ +switch (a) { + case: + print a; +} +----- +Groovy script + Switch statement + PsiElement(switch)('switch') + PsiWhiteSpace(' ') + PsiElement(()('(') + Reference expression + PsiElement(identifier)('a') + PsiElement())(')') + PsiWhiteSpace(' ') + PsiElement({)('{') + PsiWhiteSpace('\n ') + Case section + Case label + PsiElement(case)('case') + PsiErrorElement:Expression expected + + PsiElement(:)(':') + PsiElement(new line)('\n ') + Call expression + Reference expression + PsiElement(identifier)('print') + PsiWhiteSpace(' ') + Command arguments + Reference expression + PsiElement(identifier)('a') + PsiElement(;)(';') + PsiElement(new line)('\n') + PsiElement(})('}') \ No newline at end of file diff --git a/plugins/groovy/testdata/refactoring/convertGroovyToJava/codeBlock/while1.groovy b/plugins/groovy/testdata/refactoring/convertGroovyToJava/codeBlock/while1.groovy new file mode 100644 index 000000000000..be9f67913ed1 --- /dev/null +++ b/plugins/groovy/testdata/refactoring/convertGroovyToJava/codeBlock/while1.groovy @@ -0,0 +1,2 @@ +def a = 5; +while (a < 20) a-- diff --git a/plugins/groovy/testdata/refactoring/convertGroovyToJava/codeBlock/while1.java b/plugins/groovy/testdata/refactoring/convertGroovyToJava/codeBlock/while1.java new file mode 100644 index 000000000000..cae661e2816f --- /dev/null +++ b/plugins/groovy/testdata/refactoring/convertGroovyToJava/codeBlock/while1.java @@ -0,0 +1,2 @@ +int a = 5; +while (a < 20) a--; \ No newline at end of file diff --git a/plugins/groovy/testdata/refactoring/convertGroovyToJava/codeBlock/while2.groovy b/plugins/groovy/testdata/refactoring/convertGroovyToJava/codeBlock/while2.groovy new file mode 100644 index 000000000000..860ebeac05b3 --- /dev/null +++ b/plugins/groovy/testdata/refactoring/convertGroovyToJava/codeBlock/while2.groovy @@ -0,0 +1,2 @@ +def a = 5; +while (![1, 2, 3, 4].find {a > it}) a-- \ No newline at end of file diff --git a/plugins/groovy/testdata/refactoring/convertGroovyToJava/codeBlock/while2.java b/plugins/groovy/testdata/refactoring/convertGroovyToJava/codeBlock/while2.java new file mode 100644 index 000000000000..068c3cc6ae1d --- /dev/null +++ b/plugins/groovy/testdata/refactoring/convertGroovyToJava/codeBlock/while2.java @@ -0,0 +1,11 @@ +int i = 5; +java.util.List list = new java.util.ArrayList(4); +list.add(1); +list.add(2); +list.add(3); +list.add(4); +while (!org.codehaus.groovy.runtime.DefaultGroovyMethods.find(list, new groovy.lang.Closure(this, this) { + boolean doCall(java.lang.Integer it) { + return a.equals(it); + } +})) a--; diff --git a/plugins/junit/src/com/intellij/execution/junit2/configuration/JUnitConfigurable.java b/plugins/junit/src/com/intellij/execution/junit2/configuration/JUnitConfigurable.java index 6689822ff7a1..60d8004c9ac0 100644 --- a/plugins/junit/src/com/intellij/execution/junit2/configuration/JUnitConfigurable.java +++ b/plugins/junit/src/com/intellij/execution/junit2/configuration/JUnitConfigurable.java @@ -96,7 +96,8 @@ public class JUnitConfigurable extends SettingsEditor { private JComboBox myForkCb; @NonNls private static final String NONE = "none"; @NonNls private static final String METHOD = "method"; - private static final String[] FORK_MODE_ALL = {NONE, METHOD, "class"}; + @NonNls private static final String KLASS = "class"; + private static final String[] FORK_MODE_ALL = {NONE, METHOD, KLASS}; private static final String[] FORK_MODE = {NONE, METHOD}; public JUnitConfigurable(final Project project) { @@ -203,6 +204,10 @@ public class JUnitConfigurable extends SettingsEditor { } private void changePanel () { + String selectedItem = (String)myForkCb.getSelectedItem(); + if (selectedItem == null) { + selectedItem = NONE; + } if (myAllInPackageButton.isSelected()) { myPackagePanel.setVisible(true); myPattern.setVisible(false); @@ -210,7 +215,7 @@ public class JUnitConfigurable extends SettingsEditor { myMethod.setVisible(false); myForkCb.setEnabled(true); myForkCb.setModel(new DefaultComboBoxModel(FORK_MODE_ALL)); - myForkCb.setSelectedItem(NONE); + myForkCb.setSelectedItem(selectedItem); } else if (myClassButton.isSelected()){ myPackagePanel.setVisible(false); @@ -219,7 +224,7 @@ public class JUnitConfigurable extends SettingsEditor { myMethod.setVisible(false); myForkCb.setEnabled(true); myForkCb.setModel(new DefaultComboBoxModel(FORK_MODE)); - myForkCb.setSelectedItem(NONE); + myForkCb.setSelectedItem(selectedItem != KLASS ? selectedItem : METHOD); } else if (myTestMethodButton.isSelected()){ myPackagePanel.setVisible(false); @@ -235,7 +240,7 @@ public class JUnitConfigurable extends SettingsEditor { myMethod.setVisible(false); myForkCb.setEnabled(true); myForkCb.setModel(new DefaultComboBoxModel(FORK_MODE_ALL)); - myForkCb.setSelectedItem(NONE); + myForkCb.setSelectedItem(selectedItem); } } diff --git a/xml/impl/src/com/intellij/xml/util/ColorSampleLookupValue.java b/xml/impl/src/com/intellij/xml/util/ColorSampleLookupValue.java index da36441b16f8..d10d90ca45fb 100644 --- a/xml/impl/src/com/intellij/xml/util/ColorSampleLookupValue.java +++ b/xml/impl/src/com/intellij/xml/util/ColorSampleLookupValue.java @@ -289,7 +289,12 @@ public class ColorSampleLookupValue implements LookupValueWithUIHint, DeferredUs public Icon getIcon(int flags) { if (myColor == null) { if (myValue.startsWith("#")) { - myColor = Color.decode("0x" + myValue.substring(1)); + try { + myColor = Color.decode("0x" + myValue.substring(1)); + } + catch (NumberFormatException e) { + return null; + } } }