diff --git a/platform/platform-impl/src/com/intellij/ide/actions/Switcher.java b/platform/platform-impl/src/com/intellij/ide/actions/Switcher.java index 63b0ae1525a1..757c5a9d194a 100644 --- a/platform/platform-impl/src/com/intellij/ide/actions/Switcher.java +++ b/platform/platform-impl/src/com/intellij/ide/actions/Switcher.java @@ -1,5 +1,5 @@ /* - * Copyright 2000-2011 JetBrains s.r.o. + * Copyright 2000-2012 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. @@ -34,6 +34,7 @@ import com.intellij.openapi.ui.popup.JBPopupFactory; import com.intellij.openapi.util.Computable; import com.intellij.openapi.util.Iconable; import com.intellij.openapi.util.Pair; +import com.intellij.openapi.util.text.StringUtil; import com.intellij.openapi.vcs.FileStatus; import com.intellij.openapi.vcs.FileStatusManager; import com.intellij.openapi.vfs.VirtualFile; @@ -43,10 +44,8 @@ import com.intellij.openapi.wm.ToolWindowManager; import com.intellij.openapi.wm.ex.WindowManagerEx; import com.intellij.openapi.wm.impl.IdeFrameImpl; import com.intellij.openapi.wm.impl.ToolWindowManagerImpl; -import com.intellij.ui.ColoredListCellRenderer; -import com.intellij.ui.Gray; -import com.intellij.ui.IdeBorderFactory; -import com.intellij.ui.SimpleTextAttributes; +import com.intellij.openapi.wm.impl.content.GraphicsConfig; +import com.intellij.ui.*; import com.intellij.ui.components.JBList; import com.intellij.util.Alarm; import com.intellij.util.ArrayUtil; @@ -62,6 +61,8 @@ import javax.swing.event.ListSelectionEvent; import javax.swing.event.ListSelectionListener; import java.awt.*; import java.awt.event.*; +import java.beans.PropertyChangeEvent; +import java.beans.PropertyChangeListener; import java.io.File; import java.util.*; import java.util.List; @@ -121,10 +122,12 @@ public class Switcher extends AnAction implements DumbAware { ToolWindow tw; if (SWITCHER != null && event instanceof KeyEvent) { final KeyEvent keyEvent = (KeyEvent)event; - if (event.getID() == KEY_RELEASED && keyEvent.getKeyCode() == CTRL_KEY && UISettings.getInstance().HIDE_SWITCHER_ON_CONTROL_RELEASE) { + if (event.getID() == KEY_RELEASED && keyEvent.getKeyCode() == CTRL_KEY && isAutoHide()) { SwingUtilities.invokeLater(CHECKER); } - else if (event.getID() == KEY_PRESSED && (tw = SWITCHER.twShortcuts.get(String.valueOf((char)keyEvent.getKeyCode()))) != null) { + else if (isAutoHide() + && event.getID() == KEY_PRESSED + && (tw = SWITCHER.twShortcuts.get(String.valueOf((char)keyEvent.getKeyCode()))) != null) { SWITCHER.myPopup.closeOk(null); tw.activate(null, true, true); } @@ -176,6 +179,7 @@ public class Switcher extends AnAction implements DumbAware { final Project project; final Map twShortcuts; final Alarm myAlarm; + final SwitcherSpeedSearch mySpeedSearch = isAutoHide() ? null : new SwitcherSpeedSearch(); @SuppressWarnings({"ManualArrayToCollectionCopy"}) SwitcherPanel(Project project) { @@ -225,7 +229,7 @@ public class Switcher extends AnAction implements DumbAware { toolWindows = new JBList(twModel); toolWindows.setBorder(IdeBorderFactory.createEmptyBorder(5, 5, 5, 20)); toolWindows.setSelectionMode(ListSelectionModel.SINGLE_SELECTION); - toolWindows.setCellRenderer(new SwitcherToolWindowsListRenderer(ids, map) { + toolWindows.setCellRenderer(new SwitcherToolWindowsListRenderer(mySpeedSearch, ids, map) { @Override public Component getListCellRendererComponent(JList list, Object value, @@ -297,7 +301,7 @@ public class Switcher extends AnAction implements DumbAware { files = new JBList(filesModel); files.setSelectionMode(ListSelectionModel.SINGLE_SELECTION); files.setBorder(IdeBorderFactory.createEmptyBorder(5, 5, 5, 20)); - files.setCellRenderer(new VirtualFilesRenderer(project) { + files.setCellRenderer(new VirtualFilesRenderer(project, mySpeedSearch) { @Override public Component getListCellRendererComponent(JList list, Object value, @@ -381,19 +385,33 @@ public class Switcher extends AnAction implements DumbAware { .setRequestFocus(true) .setTitle(SWITCHER_TITLE) .setMovable(false) + .setCancelKeyEnabled(false) .setCancelCallback(new Computable() { - public Boolean compute() { - SWITCHER = null; - return true; - } - }).createPopup(); + public Boolean compute() { + SWITCHER = null; + return true; + } + }).createPopup(); - new AnAction(null, null, null){ + if (!isAutoHide()) { + new AnAction(null, null, null) { @Override public void actionPerformed(AnActionEvent e) { //suppress all actions to activate a toolwindow : IDEA-71277 } }.registerCustomShortcutSet(TW_SHORTCUT, this, myPopup); + new AnAction(null, null, null) { + + @Override + public void actionPerformed(AnActionEvent e) { + if (mySpeedSearch != null && mySpeedSearch.isPopupActive()) { + mySpeedSearch.hidePopup(); + } else { + myPopup.cancel(); + } + } + }.registerCustomShortcutSet(CustomShortcutSet.fromString("ESCAPE"), this, myPopup); + } Component comp = null; final EditorWindow result = FileEditorManagerEx.getInstanceEx(project).getActiveWindow().getResult(); @@ -407,6 +425,7 @@ public class Switcher extends AnAction implements DumbAware { myPopup.showInCenterOf(comp); } + private Map createShortcuts(List windows) { final Map keymap = new HashMap(windows.size()); final List pluginToolWindows = new ArrayList(); @@ -441,7 +460,7 @@ public class Switcher extends AnAction implements DumbAware { } public void keyReleased(KeyEvent e) { - if ((e.getKeyCode() == CTRL_KEY && UISettings.getInstance().HIDE_SWITCHER_ON_CONTROL_RELEASE) + if ((e.getKeyCode() == CTRL_KEY && isAutoHide()) || e.getKeyCode() == VK_ENTER) { navigate(); } else @@ -453,6 +472,8 @@ public class Switcher extends AnAction implements DumbAware { } public void keyPressed(KeyEvent e) { + if (mySpeedSearch != null && mySpeedSearch.isPopupActive()) return; + switch (e.getKeyCode()) { case VK_UP: goBack(); @@ -546,7 +567,7 @@ public class Switcher extends AnAction implements DumbAware { } private void goRight() { - if ((isFilesSelected() || !isFilesVisible()) && UISettings.getInstance().HIDE_SWITCHER_ON_CONTROL_RELEASE) { + if ((isFilesSelected() || !isFilesVisible()) && isAutoHide()) { cancel(); } else { @@ -562,7 +583,7 @@ public class Switcher extends AnAction implements DumbAware { } private void goLeft() { - if (isToolWindowsSelected() && UISettings.getInstance().HIDE_SWITCHER_ON_CONTROL_RELEASE) { + if (isToolWindowsSelected() && isAutoHide()) { cancel(); } else { @@ -699,26 +720,102 @@ public class Switcher extends AnAction implements DumbAware { repaintLists(); } public void mouseDragged(MouseEvent e) {} + + private class SwitcherSpeedSearch extends SpeedSearchBase implements PropertyChangeListener { + private Object[] myElements; + + public SwitcherSpeedSearch() { + super(SwitcherPanel.this); + addChangeListener(this); + } + + @Override + protected int getSelectedIndex() { + return isFilesSelected() + ? files.getSelectedIndex() + : files.getModel().getSize() + toolWindows.getSelectedIndex(); + } + + @Override + protected Object[] getAllElements() { + if (myElements == null) { + final SwitcherPanel switcher = SwitcherPanel.this; + final Object[] files = ((DefaultListModel)switcher.files.getModel()).toArray(); + final Object[] toolWindows = ((DefaultListModel)switcher.toolWindows.getModel()).toArray(); + myElements = new Object[files.length + toolWindows.length]; + System.arraycopy(files, 0, myElements, 0, files.length); + System.arraycopy(toolWindows, 0, myElements, files.length, toolWindows.length); + } + return myElements; + } + + + @Override + protected String getElementText(Object element) { + return element instanceof ToolWindow + ? ids.get(element) + : element instanceof FileInfo + ? ((FileInfo)element).getFirst().getName() : ""; + } + + @Override + protected void selectElement(Object element, String selectedText) { + if (element instanceof FileInfo) { + toolWindows.getSelectionModel().clearSelection(); + files.setSelectedValue(element, false); + } else { + files.clearSelection(); + toolWindows.setSelectedValue(element, false); + } + } + + @Override + public void propertyChange(PropertyChangeEvent evt) { + files.repaint(); + toolWindows.repaint(); + } + } + } + + private static boolean isAutoHide() { + return UISettings.getInstance().HIDE_SWITCHER_ON_CONTROL_RELEASE; } private static class VirtualFilesRenderer extends ColoredListCellRenderer { private final Project myProject; + private final SpeedSearchBase mySearch; + private boolean hide = false; - public VirtualFilesRenderer(Project project) { + public VirtualFilesRenderer(Project project, SpeedSearchBase search) { myProject = project; + mySearch = search; } protected void customizeCellRenderer(JList list, Object value, int index, boolean selected, boolean hasFocus) { + hide = false; if (value instanceof FileInfo) { final VirtualFile virtualFile = ((FileInfo)value).first; final String name = virtualFile.getPresentableName(); setIcon(IconUtil.getIcon(virtualFile, Iconable.ICON_FLAG_READ_STATUS, myProject)); + if ( mySearch != null && mySearch.isPopupActive()) { + hide = mySearch.matchingFragments(name) == null && !StringUtil.isEmpty(mySearch.getEnteredPrefix()); + } final FileStatus fileStatus = FileStatusManager.getInstance(myProject).getStatus(virtualFile); final TextAttributes attributes = new TextAttributes(fileStatus.getColor(), null, null, EffectType.LINE_UNDERSCORE, Font.PLAIN); append(name, SimpleTextAttributes.fromTextAttributes(attributes)); } } + + @Override + protected void doPaint(Graphics2D g) { + GraphicsConfig config = new GraphicsConfig(g); + if (hide) { + g.setComposite(AlphaComposite.getInstance(AlphaComposite.SRC_OVER, 0.4f)); + } + super.doPaint(g); + config.restore(); + } } private static class FileInfo extends Pair { diff --git a/platform/platform-impl/src/com/intellij/ide/actions/SwitcherToolWindowsListRenderer.java b/platform/platform-impl/src/com/intellij/ide/actions/SwitcherToolWindowsListRenderer.java index c56a31fd792d..e9117d735aa7 100644 --- a/platform/platform-impl/src/com/intellij/ide/actions/SwitcherToolWindowsListRenderer.java +++ b/platform/platform-impl/src/com/intellij/ide/actions/SwitcherToolWindowsListRenderer.java @@ -1,5 +1,5 @@ /* - * Copyright 2000-2011 JetBrains s.r.o. + * Copyright 2000-2012 JetBrains s.r.o. * * Licensed under the Apache License, Version 2.0 (the "License"); * you may not use this file except in compliance with the License. @@ -15,11 +15,15 @@ */ package com.intellij.ide.actions; +import com.intellij.ide.ui.UISettings; import com.intellij.openapi.editor.markup.EffectType; import com.intellij.openapi.editor.markup.TextAttributes; +import com.intellij.openapi.util.text.StringUtil; import com.intellij.openapi.wm.ToolWindow; +import com.intellij.openapi.wm.impl.content.GraphicsConfig; import com.intellij.ui.ColoredListCellRenderer; import com.intellij.ui.SimpleTextAttributes; +import com.intellij.ui.SpeedSearchBase; import com.intellij.util.PlatformIcons; import javax.swing.*; @@ -34,26 +38,51 @@ import java.util.Map; class SwitcherToolWindowsListRenderer extends ColoredListCellRenderer { private static final Map iconCache = new HashMap(); private static final SimpleTextAttributes ID_STYLE = new SimpleTextAttributes(SimpleTextAttributes.STYLE_UNDERLINE, Color.black); + private final SpeedSearchBase mySpeedSearch; private final Map ids; private final Map shortcuts; + private boolean hide = false; - SwitcherToolWindowsListRenderer(Map ids, Map shortcuts) { + SwitcherToolWindowsListRenderer(SpeedSearchBase speedSearch, + Map ids, + Map shortcuts) { + mySpeedSearch = speedSearch; this.ids = ids; this.shortcuts = shortcuts; } protected void customizeCellRenderer(JList list, Object value, int index, boolean selected, boolean hasFocus) { + hide = false; if (value instanceof ToolWindow) { final ToolWindow tw = (ToolWindow)value; setIcon(getIcon(tw)); - append(shortcuts.get(tw), ID_STYLE); - final String name = ": " + ids.get(tw); + final String name; + + if (UISettings.getInstance().HIDE_SWITCHER_ON_CONTROL_RELEASE) { + append(shortcuts.get(tw), ID_STYLE); + name = ": " + ids.get(tw); + } else { + name = ids.get(tw); + } final TextAttributes attributes = new TextAttributes(Color.BLACK, null, null, EffectType.LINE_UNDERSCORE, Font.PLAIN); append(name, SimpleTextAttributes.fromTextAttributes(attributes)); + if (mySpeedSearch != null && mySpeedSearch.isPopupActive()) { + hide = mySpeedSearch.matchingFragments(ids.get(tw)) == null && !StringUtil.isEmpty(mySpeedSearch.getEnteredPrefix()); + } } } + @Override + protected void doPaint(Graphics2D g) { + GraphicsConfig config = new GraphicsConfig(g); + if (hide) { + g.setComposite(AlphaComposite.getInstance(AlphaComposite.SRC_OVER, 0.4f)); + } + super.doPaint(g); + config.restore(); + } + private Icon getIcon(ToolWindow toolWindow) { Icon icon = iconCache.get(ids.get(toolWindow)); if (icon != null) return icon; diff --git a/platform/platform-impl/src/com/intellij/ui/SpeedSearchBase.java b/platform/platform-impl/src/com/intellij/ui/SpeedSearchBase.java index 797edb0b4f98..458426a846dd 100644 --- a/platform/platform-impl/src/com/intellij/ui/SpeedSearchBase.java +++ b/platform/platform-impl/src/com/intellij/ui/SpeedSearchBase.java @@ -1,5 +1,5 @@ /* - * Copyright 2000-2009 JetBrains s.r.o. + * Copyright 2000-2012 JetBrains s.r.o. * * Licensed under the Apache License, Version 2.0 (the "License"); * you may not use this file except in compliance with the License. @@ -17,6 +17,7 @@ package com.intellij.ui; import com.intellij.featureStatistics.FeatureUsageTracker; import com.intellij.ide.DataManager; +import com.intellij.ide.ui.UISettings; import com.intellij.openapi.actionSystem.AnAction; import com.intellij.openapi.actionSystem.AnActionEvent; import com.intellij.openapi.actionSystem.CustomShortcutSet; @@ -198,6 +199,15 @@ public abstract class SpeedSearchBase extends SpeedSear final Object element = it.next(); if (isMatchingElement(element, _s)) return element; } + + if (UISettings.getInstance().CYCLE_SCROLLING) { + final ListIterator i = getElementIterator(0); + while (i.hasNext()) { + final Object element = i.next(); + if (isMatchingElement(element, _s)) return element; + } + } + return ( current != null && isMatchingElement(current, _s) ) ? current : null; } @@ -217,6 +227,15 @@ public abstract class SpeedSearchBase extends SpeedSear final Object element = it.previous(); if (isMatchingElement(element, _s)) return element; } + + if (UISettings.getInstance().CYCLE_SCROLLING) { + final ListIterator i = getElementIterator(getAllElements().length); + while (i.hasPrevious()) { + final Object element = i.previous(); + if (isMatchingElement(element, _s)) return element; + } + } + return selectedIndex != -1 && isMatchingElement(current, _s) ? current : null; } diff --git a/plugins/groovy/src/org/jetbrains/plugins/groovy/codeInspection/noReturnMethod/MissingReturnInspection.java b/plugins/groovy/src/org/jetbrains/plugins/groovy/codeInspection/noReturnMethod/MissingReturnInspection.java index f2e268a51217..bf16de6542e3 100644 --- a/plugins/groovy/src/org/jetbrains/plugins/groovy/codeInspection/noReturnMethod/MissingReturnInspection.java +++ b/plugins/groovy/src/org/jetbrains/plugins/groovy/codeInspection/noReturnMethod/MissingReturnInspection.java @@ -18,9 +18,7 @@ package org.jetbrains.plugins.groovy.codeInspection.noReturnMethod; import com.intellij.codeInspection.ProblemsHolder; import com.intellij.openapi.util.Ref; import com.intellij.openapi.util.TextRange; -import com.intellij.psi.PsiElement; -import com.intellij.psi.PsiElementVisitor; -import com.intellij.psi.PsiType; +import com.intellij.psi.*; import org.jetbrains.annotations.Nls; import org.jetbrains.annotations.NonNls; import org.jetbrains.annotations.NotNull; @@ -65,14 +63,33 @@ public class MissingReturnInspection extends GroovySuppressableInspectionTool { return GroovyInspectionBundle.message("no.return.display.name"); } + public enum ReturnStatus { + mustReturnValue, shouldReturnValue, shouldNotReturnValue; + + public static ReturnStatus getReturnStatus(PsiElement subject) { + if (subject instanceof GrClosableBlock) { + final PsiType inferredReturnType = GroovyExpectedTypesProvider.getExpectedClosureReturnType((GrClosableBlock)subject); + if (inferredReturnType instanceof PsiClassType) { + PsiClass resolved = ((PsiClassType)inferredReturnType).resolve(); + if (resolved != null && !(resolved instanceof PsiTypeParameter)) return mustReturnValue; + } + return inferredReturnType != null && inferredReturnType != PsiType.VOID ? shouldReturnValue : shouldNotReturnValue; + } + else if (subject instanceof GrMethod) { + return ((GrMethod)subject).getReturnTypeElementGroovy() != null && ((GrMethod)subject).getReturnType() != PsiType.VOID + ? mustReturnValue + : shouldNotReturnValue; + } + return shouldNotReturnValue; + } + } + @NotNull public PsiElementVisitor buildVisitor(@NotNull final ProblemsHolder problemsHolder, boolean onTheFly) { return new GroovyPsiElementVisitor(new GroovyElementVisitor() { public void visitClosure(GrClosableBlock closure) { super.visitClosure(closure); - - final PsiType expectedClosureType = GroovyExpectedTypesProvider.getExpectedClosureReturnType(closure); - check(closure, problemsHolder, expectedClosureType != null && expectedClosureType != PsiType.VOID); + check(closure, problemsHolder, ReturnStatus.getReturnStatus(closure)); } public void visitMethod(GrMethod method) { @@ -80,72 +97,70 @@ public class MissingReturnInspection extends GroovySuppressableInspectionTool { final GrOpenBlock block = method.getBlock(); if (block != null) { - final boolean mustReturnValue = method.getReturnTypeElementGroovy() != null && method.getReturnType() != PsiType.VOID; - check(block, problemsHolder, mustReturnValue); + check(block, problemsHolder, ReturnStatus.getReturnStatus(method)); } } }); - } - private static void check(GrCodeBlock block, ProblemsHolder holder, boolean mustReturnValue) { - if (methodMissesSomeReturns(block, mustReturnValue)) { + private static void check(GrCodeBlock block, ProblemsHolder holder, ReturnStatus returnStatus) { + if (methodMissesSomeReturns(block, returnStatus)) { addNoReturnMessage(block, holder); } } - public static boolean methodMissesSomeReturns(GrControlFlowOwner block, boolean mustReturnValue) { - if (!mustReturnValue) { + public static boolean methodMissesSomeReturns(GrControlFlowOwner block, ReturnStatus returnStatus) { + if (returnStatus == ReturnStatus.shouldNotReturnValue) { return false; } - final Ref always = new Ref(true); + final Ref alwaysHaveReturn = new Ref(true); + final Ref sometimesHaveReturn = new Ref(false); final Ref hasExplicitReturn = new Ref(false); - final Ref sometimes = new Ref(false); ControlFlowUtils.visitAllExitPoints(block, new ControlFlowUtils.ExitPointVisitor() { @Override public boolean visitExitPoint(Instruction instruction, @Nullable GrExpression returnValue) { if (instruction instanceof MaybeReturnInstruction) { if (((MaybeReturnInstruction)instruction).mayReturnValue()) { - sometimes.set(true); + sometimesHaveReturn.set(true); } else { - always.set(false); + alwaysHaveReturn.set(false); } return true; } final PsiElement element = instruction.getElement(); if (element instanceof GrReturnStatement) { - sometimes.set(true); + sometimesHaveReturn.set(true); if (returnValue != null) { hasExplicitReturn.set(true); } } else if (instruction instanceof ThrowingInstruction) { - sometimes.set(true); + sometimesHaveReturn.set(true); } else if (element instanceof GrAssertStatement) { - sometimes.set(true); + sometimesHaveReturn.set(true); int count = 0; for (Instruction _i : instruction.allSuccessors()) { count++; } if (count <= 1) { - always.set(false); + alwaysHaveReturn.set(false); } } else { - always.set(false); + alwaysHaveReturn.set(false); } return true; } }); - if (!sometimes.get()) { + if (returnStatus == ReturnStatus.mustReturnValue && !sometimesHaveReturn.get()) { return true; } - return sometimes.get() && !always.get(); + return sometimesHaveReturn.get() && !alwaysHaveReturn.get(); } private static void addNoReturnMessage(GrCodeBlock block, ProblemsHolder holder) { diff --git a/plugins/groovy/src/org/jetbrains/plugins/groovy/formatter/GroovyCodeStyleSettings.java b/plugins/groovy/src/org/jetbrains/plugins/groovy/formatter/GroovyCodeStyleSettings.java index 895f178c762a..2869eb12bcf2 100644 --- a/plugins/groovy/src/org/jetbrains/plugins/groovy/formatter/GroovyCodeStyleSettings.java +++ b/plugins/groovy/src/org/jetbrains/plugins/groovy/formatter/GroovyCodeStyleSettings.java @@ -43,6 +43,7 @@ public class GroovyCodeStyleSettings extends CustomCodeStyleSettings { public boolean SPACE_IN_NAMED_ARGUMENT = true; public boolean ALIGN_MULTILINE_LIST_OR_MAP = false; + public boolean SPACE_WITHIN_LIST_OR_MAP = false; public GroovyCodeStyleSettings(CodeStyleSettings container) { super("GroovyCodeStyleSettings", container); diff --git a/plugins/groovy/src/org/jetbrains/plugins/groovy/formatter/GroovyLanguageCodeStyleSettingsProvider.java b/plugins/groovy/src/org/jetbrains/plugins/groovy/formatter/GroovyLanguageCodeStyleSettingsProvider.java index 6cd8df934c1a..a93b3cf1549b 100644 --- a/plugins/groovy/src/org/jetbrains/plugins/groovy/formatter/GroovyLanguageCodeStyleSettingsProvider.java +++ b/plugins/groovy/src/org/jetbrains/plugins/groovy/formatter/GroovyLanguageCodeStyleSettingsProvider.java @@ -115,6 +115,7 @@ public class GroovyLanguageCodeStyleSettingsProvider extends LanguageCodeStyleSe "SPACE_WITHIN_ANNOTATION_PARENTHESES" ); consumer.showCustomOption(GroovyCodeStyleSettings.class, "SPACE_IN_NAMED_ARGUMENT", "In named argument after ':'", CodeStyleSettingsCustomizable.SPACES_OTHER); + consumer.showCustomOption(GroovyCodeStyleSettings.class, "SPACE_WITHIN_LIST_OR_MAP", "List and maps literals", CodeStyleSettingsCustomizable.SPACES_WITHIN); return; } consumer.showAllStandardOptions(); 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 970d869780a1..46805d001b79 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 @@ -546,7 +546,7 @@ public class GroovySpacingProcessor extends GroovyElementVisitor { @Override public void visitListOrMap(GrListOrMap listOrMap) { if (myType1 == mLBRACK || myType2 == mRBRACK) { - createSpaceInCode(mySettings.SPACE_WITHIN_BRACKETS); + createSpaceInCode(myGroovySettings.SPACE_WITHIN_LIST_OR_MAP); } } diff --git a/plugins/groovy/src/org/jetbrains/plugins/groovy/lang/folding/GroovyFoldingBuilder.java b/plugins/groovy/src/org/jetbrains/plugins/groovy/lang/folding/GroovyFoldingBuilder.java index 574c5c9d4e1b..f695d0ebe0d8 100644 --- a/plugins/groovy/src/org/jetbrains/plugins/groovy/lang/folding/GroovyFoldingBuilder.java +++ b/plugins/groovy/src/org/jetbrains/plugins/groovy/lang/folding/GroovyFoldingBuilder.java @@ -24,10 +24,7 @@ import com.intellij.openapi.editor.Document; import com.intellij.openapi.editor.FoldingGroup; import com.intellij.openapi.project.DumbAware; import com.intellij.openapi.util.TextRange; -import com.intellij.psi.PsiAnonymousClass; -import com.intellij.psi.PsiClass; -import com.intellij.psi.PsiElement; -import com.intellij.psi.PsiFile; +import com.intellij.psi.*; import com.intellij.psi.impl.source.tree.LeafPsiElement; import com.intellij.psi.tree.IElementType; import com.intellij.util.containers.hash.HashSet; @@ -215,6 +212,7 @@ public class GroovyFoldingBuilder extends CustomFoldingBuilder implements Groovy return text.contains("\n") || text.contains("\r") || text.contains("\r\n"); } + @Nullable @Override protected String getLanguagePlaceholderText(@NotNull ASTNode node, @NotNull TextRange range) { final IElementType elemType = node.getElementType(); @@ -245,8 +243,21 @@ public class GroovyFoldingBuilder extends CustomFoldingBuilder implements Groovy return settings.isCollapseImports(); } - if (node.getElementType() == GROOVY_DOC_COMMENT) { - return settings.isCollapseJavadocs(); + if (node.getElementType() == GROOVY_DOC_COMMENT || node.getElementType() == mML_COMMENT) { + PsiElement element = node.getPsi(); + PsiElement parent = element.getParent(); + if (parent instanceof GroovyFile) { + PsiElement firstChild = parent.getFirstChild(); + if (firstChild instanceof PsiWhiteSpace) { + firstChild = firstChild.getNextSibling(); + } + if (element.equals(firstChild)) { + return settings.isCollapseFileHeader(); + } + } + if (node.getElementType() == GROOVY_DOC_COMMENT) { + return settings.isCollapseJavadocs(); + } } if ((node.getElementType() == OPEN_BLOCK || node.getElementType() == CONSTRUCTOR_BODY) && node.getTreeParent().getElementType() == METHOD_DEFINITION) { diff --git a/plugins/groovy/src/org/jetbrains/plugins/groovy/refactoring/convertToJava/ClassItemGeneratorImpl.java b/plugins/groovy/src/org/jetbrains/plugins/groovy/refactoring/convertToJava/ClassItemGeneratorImpl.java index 32355663ea49..f47fbf22631a 100644 --- a/plugins/groovy/src/org/jetbrains/plugins/groovy/refactoring/convertToJava/ClassItemGeneratorImpl.java +++ b/plugins/groovy/src/org/jetbrains/plugins/groovy/refactoring/convertToJava/ClassItemGeneratorImpl.java @@ -247,7 +247,7 @@ public class ClassItemGeneratorImpl implements ClassItemGenerator { ExpressionContext extended = context.extend(); extended.searchForLocalVarsToWrap((GroovyPsiElement)scriptFile); new CodeBlockGenerator(builder, extended, exitPoints) - .visitStatementOwner((GroovyFile)scriptFile, MissingReturnInspection.methodMissesSomeReturns((GroovyFile)scriptFile, true)); + .visitStatementOwner((GroovyFile)scriptFile, MissingReturnInspection.methodMissesSomeReturns((GroovyFile)scriptFile, MissingReturnInspection.ReturnStatus.mustReturnValue)); builder.append("\n}\n"); } diff --git a/plugins/groovy/src/org/jetbrains/plugins/groovy/refactoring/convertToJava/ClosureGenerator.java b/plugins/groovy/src/org/jetbrains/plugins/groovy/refactoring/convertToJava/ClosureGenerator.java index b526545ce770..ff4ac8cd4acc 100644 --- a/plugins/groovy/src/org/jetbrains/plugins/groovy/refactoring/convertToJava/ClosureGenerator.java +++ b/plugins/groovy/src/org/jetbrains/plugins/groovy/refactoring/convertToJava/ClosureGenerator.java @@ -87,7 +87,7 @@ public class ClosureGenerator { Collection myExitPoints = ControlFlowUtils.collectReturns(block); boolean shouldInsertReturnNull = - !(returnType instanceof PsiPrimitiveType) && MissingReturnInspection.methodMissesSomeReturns(block, false); + !(returnType instanceof PsiPrimitiveType) && MissingReturnInspection.methodMissesSomeReturns(block, MissingReturnInspection.ReturnStatus.shouldNotReturnValue); new CodeBlockGenerator(builder, context.extend(), myExitPoints).generateCodeBlock(block, shouldInsertReturnNull); builder.append('\n'); 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 f42e83d4de65..f921633f3d27 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 @@ -101,7 +101,8 @@ public class CodeBlockGenerator extends Generator { if (!method.isConstructor() && returnType != PsiType.VOID) { myExitPoints.addAll(ControlFlowUtils.collectReturns(block)); shouldInsertReturnNull = !(returnType instanceof PsiPrimitiveType) && - MissingReturnInspection.methodMissesSomeReturns(block, method.getReturnTypeElementGroovy() != null); + MissingReturnInspection.methodMissesSomeReturns(block, + MissingReturnInspection.ReturnStatus.getReturnStatus(method)); } if (block != null) { diff --git a/plugins/groovy/test/org/jetbrains/plugins/groovy/lang/MissingReturnTest.groovy b/plugins/groovy/test/org/jetbrains/plugins/groovy/lang/MissingReturnTest.groovy index e85cc9cd0a44..538fac39a666 100644 --- a/plugins/groovy/test/org/jetbrains/plugins/groovy/lang/MissingReturnTest.groovy +++ b/plugins/groovy/test/org/jetbrains/plugins/groovy/lang/MissingReturnTest.groovy @@ -41,6 +41,7 @@ public class MissingReturnTest extends LightCodeInsightFixtureTestCase { public void testImplicitReturnNull() throws Throwable {doTest();} public void testMissingReturnInClosure() {doTest();} public void testFinally() {doTest();} + public void testClosureWithExplicitExpectedType() {doTest()} private void doTest() { myFixture.enableInspections(new MissingReturnInspection()); diff --git a/plugins/groovy/testdata/highlighting/missingReturn/ClosureWithExplicitExpectedType.groovy b/plugins/groovy/testdata/highlighting/missingReturn/ClosureWithExplicitExpectedType.groovy new file mode 100644 index 000000000000..d8a58ad50356 --- /dev/null +++ b/plugins/groovy/testdata/highlighting/missingReturn/ClosureWithExplicitExpectedType.groovy @@ -0,0 +1,19 @@ +def foo(Closure c) { + return c().substring(1) +} + +foo { + print 2 +} + +foo { + 's' +} + +foo { + if (a) 's' +} + +foo { + if (a) 'a' else 'b' +} diff --git a/plugins/groovy/testdata/highlighting/missingReturn/MissingReturnInClosure.groovy b/plugins/groovy/testdata/highlighting/missingReturn/MissingReturnInClosure.groovy index dd8a60c60789..4fc8273eeaee 100644 --- a/plugins/groovy/testdata/highlighting/missingReturn/MissingReturnInClosure.groovy +++ b/plugins/groovy/testdata/highlighting/missingReturn/MissingReturnInClosure.groovy @@ -2,7 +2,7 @@ def mkString(def i) {} print([1, 2, 3].collect { mkString(it) -}) +}) print([1, 2, 3].collect { @@ -10,5 +10,5 @@ print([1, 2, 3].collect { }) Closure c1 = { mkString(it)} -Closure c2 = {mkString(it)} +Closure c2 = {mkString(it); if (a) return 2} def c3 = {mkString(it)} \ No newline at end of file