Merge remote branch 'origin/master'
authorDmitry Jemerov <yole@jetbrains.com>
Fri, 27 Jan 2012 15:02:37 +0000 (16:02 +0100)
committerDmitry Jemerov <yole@jetbrains.com>
Fri, 27 Jan 2012 15:02:37 +0000 (16:02 +0100)
40 files changed:
java/execution/impl/src/com/intellij/execution/impl/DefaultJavaProgramRunner.java
java/java-impl/src/com/intellij/refactoring/introduceVariable/IntroduceVariableBase.java
java/java-psi-impl/src/com/intellij/psi/impl/source/PsiImmediateClassType.java
platform/icons/src/actions/move-to-button-top.png [new file with mode: 0644]
platform/icons/src/actions/move-to-button.png [new file with mode: 0644]
platform/lang-api/src/com/intellij/execution/DefaultExecutionResult.java
platform/lang-impl/src/com/intellij/execution/ui/layout/actions/MinimizeViewAction.java
platform/lang-impl/src/com/intellij/execution/ui/layout/impl/GridCellImpl.java
platform/lang-impl/src/com/intellij/execution/ui/layout/impl/JBRunnerTabs.java
platform/lang-impl/src/com/intellij/execution/ui/layout/impl/RunnerContentUi.java
platform/lang-impl/src/com/intellij/refactoring/rename/RenameDialog.java
platform/lang-impl/src/com/intellij/refactoring/rename/RenameFileAction.java [new file with mode: 0644]
platform/platform-api/src/com/intellij/ui/AnActionButton.java
platform/platform-api/src/com/intellij/ui/AnActionButtonUpdater.java [new file with mode: 0644]
platform/platform-api/src/com/intellij/ui/tabs/impl/JBTabsImpl.java
platform/platform-impl/src/com/intellij/openapi/fileEditor/impl/EditorTabbedContainer.java
platform/platform-resources/src/idea/LangActions.xml
plugins/InspectionGadgets/src/META-INF/plugin.xml
plugins/InspectionGadgets/src/com/siyeh/InspectionGadgetsBundle.properties
plugins/InspectionGadgets/src/com/siyeh/ig/style/StringBufferReplaceableByStringInspection.java [moved from plugins/InspectionGadgets/src/com/siyeh/ig/performance/StringBufferReplaceableByStringInspection.java with 99% similarity]
plugins/InspectionGadgets/src/com/siyeh/ig/style/VariableIsModifiedVisitor.java [moved from plugins/InspectionGadgets/src/com/siyeh/ig/performance/VariableIsModifiedVisitor.java with 98% similarity]
plugins/InspectionGadgets/src/inspectionDescriptions/StringBufferReplaceableByString.html
plugins/InspectionGadgets/test/com/siyeh/igtest/performance/StringBufferReplaceableByStringInspection.java [deleted file]
plugins/InspectionGadgets/test/com/siyeh/igtest/performance/constant_string_buffer_may_be_string/StringBufferReplaceableByString.java [deleted file]
plugins/InspectionGadgets/test/com/siyeh/igtest/performance/constant_string_buffer_may_be_string/expected.xml [deleted file]
plugins/InspectionGadgets/test/com/siyeh/igtest/performance/string_buffer_replaceable_by_string/StringBufferReplaceableByString.java [new file with mode: 0644]
plugins/InspectionGadgets/test/com/siyeh/igtest/performance/string_buffer_replaceable_by_string/expected.xml [new file with mode: 0644]
plugins/InspectionGadgets/testsrc/com/siyeh/ig/style/StringBufferReplaceableByStringInspectionTest.java [moved from plugins/InspectionGadgets/testsrc/com/siyeh/ig/performance/StringBufferReplaceableByStringInspectionTest.java with 67% similarity]
plugins/groovy/src/META-INF/plugin.xml
plugins/groovy/src/org/jetbrains/plugins/groovy/debugger/GroovyCodeFragmentFactory.java
plugins/groovy/src/org/jetbrains/plugins/groovy/formatter/AlignmentProvider.java [new file with mode: 0644]
plugins/groovy/src/org/jetbrains/plugins/groovy/formatter/GeeseUtil.java
plugins/groovy/src/org/jetbrains/plugins/groovy/formatter/GroovyBlock.java
plugins/groovy/src/org/jetbrains/plugins/groovy/formatter/GroovyBlockGenerator.java
plugins/groovy/src/org/jetbrains/plugins/groovy/formatter/GroovyFormattingModelBuilder.java
plugins/groovy/src/org/jetbrains/plugins/groovy/formatter/MethodCallWithoutQualifierBlock.java
plugins/groovy/src/org/jetbrains/plugins/groovy/refactoring/javaToGrovyRename/RenameJavaFileToGroovyFileAction.java [deleted file]
plugins/groovy/test/org/jetbrains/plugins/groovy/lang/formatter/FormatterTest.java
plugins/groovy/testdata/groovy/formatter/geese8.test [new file with mode: 0644]
plugins/ui-designer/src/com/intellij/uiDesigner/inspections/NoLabelForInspection.java

index 6707b6ab50104b8dd0bf7d30d9cee6afe5b8733e..566719bce954b259b79ffa356baeabc083558756 100644 (file)
@@ -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.
@@ -108,6 +108,7 @@ public class DefaultJavaProgramRunner extends JavaPatchableProgramRunner {
     if (consoleComponent != null) {
       controlBreakAction.registerCustomShortcutSet(controlBreakAction.getShortcutSet(), consoleComponent);
       final ProcessHandler processHandler = executionResult.getProcessHandler();
+      assert processHandler != null : executionResult;
       processHandler.addProcessListener(new ProcessAdapter() {
         public void processTerminated(final ProcessEvent event) {
           processHandler.removeProcessListener(this);
index 818fb9b5d33720476c3031a44b10c0899d56b55f..dfa8c7417307f7ed495810c2eb6a89772aa93edf 100644 (file)
@@ -47,7 +47,10 @@ import com.intellij.psi.codeStyle.*;
 import com.intellij.psi.impl.PsiDiamondTypeUtil;
 import com.intellij.psi.impl.source.resolve.DefaultParameterTypeInferencePolicy;
 import com.intellij.psi.impl.source.tree.java.ReplaceExpressionUtil;
-import com.intellij.psi.util.*;
+import com.intellij.psi.util.PsiExpressionTrimRenderer;
+import com.intellij.psi.util.PsiTreeUtil;
+import com.intellij.psi.util.PsiUtil;
+import com.intellij.psi.util.PsiUtilBase;
 import com.intellij.refactoring.*;
 import com.intellij.refactoring.introduce.inplace.AbstractInplaceIntroducer;
 import com.intellij.refactoring.introduce.inplace.OccurrencesChooser;
@@ -100,8 +103,7 @@ public abstract class IntroduceVariableBase extends IntroduceHandlerBase {
       final PsiElement[] statementsInRange = findStatementsAtOffset(editor, file, offset);
 
       //try line selection
-      if (statementsInRange.length == 1 && (PsiUtilCore.hasErrorElementChild(statementsInRange[0]) ||
-                                            !PsiUtil.isStatement(statementsInRange[0]) ||
+      if (statementsInRange.length == 1 && (!PsiUtil.isStatement(statementsInRange[0]) ||
                                             statementsInRange[0].getTextRange().getStartOffset() > offset ||
                                             statementsInRange[0].getTextRange().getEndOffset() < offset ||
                                             isPreferStatements())) {
index 06947461b9efbf17263e122bf44aa0eeaee1b6b4..bba0cfe69f2266f8efad6da92c5538ba722b8407 100644 (file)
@@ -171,7 +171,7 @@ public class PsiImmediateClassType extends PsiClassType {
     PsiClass parentClass = null;
     if (!aClass.hasModifierProperty(PsiModifier.STATIC)) {
       final PsiElement parent = aClass.getParent();
-      if (parent instanceof PsiClass) {
+      if (parent instanceof PsiClass && !(parent instanceof PsiAnonymousClass)) {
         parentClass = (PsiClass)parent;
       }
     }
diff --git a/platform/icons/src/actions/move-to-button-top.png b/platform/icons/src/actions/move-to-button-top.png
new file mode 100644 (file)
index 0000000..4516cba
Binary files /dev/null and b/platform/icons/src/actions/move-to-button-top.png differ
diff --git a/platform/icons/src/actions/move-to-button.png b/platform/icons/src/actions/move-to-button.png
new file mode 100644 (file)
index 0000000..c634775
Binary files /dev/null and b/platform/icons/src/actions/move-to-button.png differ
index e236c63676ecb995ea264c8201ddc51f5a2db5ea..1251e87e2f67eac13a9c5e26ee7d8686ad25eed8 100644 (file)
@@ -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.
@@ -36,11 +36,11 @@ public class DefaultExecutionResult implements ExecutionResult {
   private AnAction[] myRestartActions;
   private final List<AnAction> myStopActions = new ArrayList<AnAction>();
 
-  public DefaultExecutionResult(final ExecutionConsole console, final ProcessHandler processHandler) {
+  public DefaultExecutionResult(final ExecutionConsole console, @NotNull final ProcessHandler processHandler) {
     this(console, processHandler, AnAction.EMPTY_ARRAY);
   }
 
-  public DefaultExecutionResult(final ExecutionConsole console, final ProcessHandler processHandler, final AnAction... actions) {
+  public DefaultExecutionResult(final ExecutionConsole console, @NotNull final ProcessHandler processHandler, final AnAction... actions) {
     myConsole = console;
     myProcessHandler = processHandler;
     myActions = actions;
index fc16369ed6885fd7082a000594caefaa93047215..eaff624c45545ec46e0f37e75b060c39bcdb4a74 100644 (file)
@@ -20,12 +20,18 @@ import com.intellij.execution.ui.layout.Tab;
 import com.intellij.execution.ui.layout.ViewContext;
 import com.intellij.execution.ui.actions.BaseViewAction;
 import com.intellij.openapi.actionSystem.AnActionEvent;
+import com.intellij.openapi.util.IconLoader;
 import com.intellij.ui.content.Content;
 
+import javax.swing.*;
+
 public class MinimizeViewAction extends BaseViewAction {
+  private static final Icon ICON = IconLoader.getIcon("/actions/move-to-button.png");
+  private static final Icon ICON_TOP = IconLoader.getIcon("/actions/move-to-button-top.png");
 
   protected void update(final AnActionEvent e, final ViewContext context, final Content[] content) {
     setEnabled(e, isEnabled(context, content, e.getPlace()));
+    e.getPresentation().setIcon(ViewContext.TAB_TOOLBAR_PLACE.equals(e.getPlace()) ? ICON_TOP : ICON);
   }
 
   protected void actionPerformed(final AnActionEvent e, final ViewContext context, final Content[] content) {
index 53df6f2e8ea8b7a8c4066b87924dbf04ecef6259..8a03f1bc543fcfd3b27e61cbee12f28ca9c570ca 100644 (file)
@@ -67,7 +67,17 @@ public class GridCellImpl implements GridCell {
 
     myPlaceInGrid = placeInGrid;
     myPlaceholder = placeholder;
-    myTabs = new JBTabsImpl(myContext.getProject(), myContext.getActionManager(), myContext.getFocusManager(), container).setDataProvider(new DataProvider() {
+    myTabs = new JBTabsImpl(myContext.getProject(), myContext.getActionManager(), myContext.getFocusManager(), container) {
+      @Override
+      protected Color getFocusedTopFillColor() {
+        return new Color(202, 211, 227);
+      }
+
+      @Override
+      protected Color getFocusedBottomFillColor() {
+        return new Color(194, 203, 219);
+      }
+    }.setDataProvider(new DataProvider() {
       @Nullable
       public Object getData(@NonNls final String dataId) {
         if (ViewContext.CONTENT_KEY.is(dataId)) {
@@ -89,8 +99,8 @@ public class GridCellImpl implements GridCell {
         return new UiDecoration(null, new Insets(1, -1, 1, -1));
       }
     }).setSideComponentVertical(!context.getLayoutSettings().isToolbarHorizontal())
-      .setStealthTabMode(true)
-      .setFocusCycle(false).setPaintFocus(true).setProvideSwitchTargets(false).setTabDraggingEnabled(true);
+      .setStealthTabMode(true).setFocusCycle(false).setPaintFocus(true)
+      .setProvideSwitchTargets(false).setTabDraggingEnabled(true);
 
     myTabs.addTabMouseListener(new MouseAdapter() {
       public void mousePressed(final MouseEvent e) {
index 944876b1cca37f05a950faafa69d334a65b097e1..0873fe91e6e0b9cdc5170c312c98f7e24304f22c 100644 (file)
@@ -65,9 +65,9 @@ public class
     Insets insets = getTabsBorder().getEffectiveBorder();
 
     int _x = effectiveBounds.x + insets.left;
-    int _y = effectiveBounds.y + insets.top + 5;
+    int _y = effectiveBounds.y + insets.top + 3;
     int _width = effectiveBounds.width - insets.left - insets.right;
-    int _height = effectiveBounds.height - insets.top - insets.bottom - 5;
+    int _height = effectiveBounds.height - insets.top - insets.bottom - 3;
     _height -= TabsUtil.ACTIVE_TAB_UNDERLINE_HEIGHT;
 
     g2d
@@ -113,10 +113,10 @@ public class
     height -= TabsUtil.ACTIVE_TAB_UNDERLINE_HEIGHT;
 
     rectangle = new Rectangle(maxOffset, y, r2.width - maxOffset - insets.left - insets.right, height);
-    
+
     g2d.setPaint(UIUtil.getPanelBackground());
     g2d.fillRect(rectangle.x, rectangle.y, rectangle.width, rectangle.height);
-    g2d.fillRect(0, 0, rectangle.x + rectangle.width, 5);
+    g2d.fillRect(0, 0, rectangle.x + rectangle.width, 3);
     g2d.fillRect(2, maxLength, getSize().width, getSize().height);
     g2d.drawLine(0, 0, 0, getSize().height);
   }
@@ -126,7 +126,7 @@ public class
 
     TabLabel label = getSelectedLabel();
     Rectangle r = label.getBounds();
-    r = new Rectangle(r.x, r.y + 5, r.width, r.height - 5);
+    r = new Rectangle(r.x, r.y + 3, r.width, r.height - 3);
 
     ShapeInfo selectedShape = _computeSelectedLabelShape(r);
 
@@ -138,15 +138,22 @@ public class
     int _height = r.height;
 
     if (!isHideTabs()) {
-      g2d.setPaint(new GradientPaint(_x, _y, new SameColor(255), _x, _y + _height, UIUtil.getPanelBackground()));
+      g2d.setPaint(new GradientPaint(_x, _y, new SameColor(255), _x, _y + _height - 3, UIUtil.getPanelBackground()));
 
       g2d.fill(selectedShape.fillPath.getShape());
 
       g2d.setColor(new Color(255, 255, 255, 180));
       g2d.draw(selectedShape.fillPath.getShape());
+
+      // fix right side due to swing stupidity (fill & draw will occupy different shapes)
+      g2d.draw(selectedShape.labelPath
+                 .transformLine(selectedShape.labelPath.getMaxX() - selectedShape.labelPath.deltaX(1), selectedShape.labelPath.getY() +
+                                                                                                       selectedShape.labelPath.deltaY(1),
+                                selectedShape.labelPath.getMaxX() - selectedShape.labelPath.deltaX(1), selectedShape.labelPath.getMaxY() -
+                                                                                                       selectedShape.labelPath.deltaY(4)));
     }
     g2d.setColor(UIUtil.getPanelBackground());
-    g2d.fillRect(2, selectedShape.labelPath.getMaxY() - 3, selectedShape.path.getMaxX() - 3, 4);
+    g2d.fillRect(2, selectedShape.labelPath.getMaxY() - 2, selectedShape.path.getMaxX() - 2, 3);
     g2d.drawLine(1, selectedShape.labelPath.getMaxY(), 1, getHeight() - 1);
     g2d.drawLine(selectedShape.path.getMaxX() - 1, selectedShape.labelPath.getMaxY() - 4,
                  selectedShape.path.getMaxX() - 1, getHeight() - 1);
@@ -199,7 +206,7 @@ public class
   public int getToolbarInset() {
     return 8;
   }
-  
+
   public boolean shouldAddToGlobal(Point point) {
     final TabLabel label = getSelectedLabel();
     if (label == null || point == null) {
@@ -218,6 +225,10 @@ public class
     if (c instanceof GridImpl) {
       bounds.x -= 1;
       bounds.width += 1;
+      if (!isHideTabs()) {
+        bounds.y -= 1;
+        bounds.height += 1;
+      }
     }
     return super.layout(c, bounds);
   }
@@ -249,7 +260,7 @@ public class
     public void apply(UiDecorator.UiDecoration decoration) {
       setFont(UIUtil.getLabelFont(UIUtil.FontSize.SMALL));
       myLabel.setFont(UIUtil.getLabelFont(UIUtil.FontSize.SMALL));
-      setBorder(new EmptyBorder(7, 5, 7, 5));
+      setBorder(new EmptyBorder(5, 5, 7, 5));
     }
 
     @Override
index 4448dacb739e61b5b49bd1af431ecb31c313de97..42c2d7c48830146061ed720e47b8dc073653b1ac 100644 (file)
@@ -612,7 +612,6 @@ public class RunnerContentUi implements ContentUI, Disposable, CellTransform.Fac
     if (grid != null || !createIfMissing) return grid;
 
     grid = new GridImpl(this, mySessionName);
-    grid.setBorder(new EmptyBorder(1, 0, 0, 0));
 
     if (myCurrentOver != null || myOriginal != null) {
       Integer forcedDropIndex = content.getUserData(RunnerLayout.DROP_INDEX);
@@ -744,7 +743,11 @@ public class RunnerContentUi implements ContentUI, Disposable, CellTransform.Fac
     for (TabInfo each : tabs) {
       hasToolbarContent |= updateTabUI(each);
     }
-    myTabs.getPresentation().setHideTabs(!hasToolbarContent && tabs.size() <= 1 && myOriginal == null);
+    int tabsCount = tabs.size();
+    for (RunnerContentUi child : myChildren) {
+      tabsCount += child.myTabs.getTabCount();
+    }
+    myTabs.getPresentation().setHideTabs(!hasToolbarContent && tabsCount <= 1 && myOriginal == null);
     myTabs.updateTabActions(validateNow);
 
     if (validateNow) {
index d4c8d662af43cdf3418def20d6676de0aa6d37dd..7ab5099e12a9e44348f5b529b003d0667727cdb5 100644 (file)
@@ -118,7 +118,7 @@ public class RenameDialog extends RefactoringDialog {
     myNameSuggestionsField = new NameSuggestionsField(suggestedNames, myProject, FileTypes.PLAIN_TEXT, myEditor) {
       @Override
       protected boolean shouldSelectAll() {
-        return myEditor.getSettings().isPreselectRename();
+        return myEditor == null || myEditor.getSettings().isPreselectRename();
       }
     };
     if (myPsiElement instanceof PsiFile && myEditor == null) {
diff --git a/platform/lang-impl/src/com/intellij/refactoring/rename/RenameFileAction.java b/platform/lang-impl/src/com/intellij/refactoring/rename/RenameFileAction.java
new file mode 100644 (file)
index 0000000..a0aa127
--- /dev/null
@@ -0,0 +1,51 @@
+/*
+ * Copyright 2000-2009 JetBrains s.r.o.
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+package com.intellij.refactoring.rename;
+
+import com.intellij.openapi.actionSystem.*;
+import com.intellij.openapi.project.DumbAware;
+import com.intellij.openapi.project.Project;
+import com.intellij.openapi.vfs.VirtualFile;
+import com.intellij.psi.PsiFile;
+
+/**
+ * @author ven
+ */
+public class RenameFileAction extends AnAction implements DumbAware {
+  public static final String RENAME_FILE = "Rename File";
+
+  public void actionPerformed(final AnActionEvent e) {
+    final PsiFile file = e.getData(LangDataKeys.PSI_FILE);
+    assert file != null;
+    final VirtualFile virtualFile = file.getVirtualFile();
+    assert virtualFile != null;
+    final Project project = e.getData(PlatformDataKeys.PROJECT);
+    assert project != null;
+    new RenameDialog(project, file, file, null).show();
+  }
+
+  public void update(AnActionEvent e) {
+    PsiFile file = e.getData(LangDataKeys.PSI_FILE);
+    Presentation presentation = e.getPresentation();
+    boolean enabled = file != null && e.getPlace() != ActionPlaces.EDITOR_POPUP && e.getData(PlatformDataKeys.PROJECT) != null;
+    presentation.setEnabled(enabled);
+    presentation.setVisible(enabled);
+    if (enabled) {
+      presentation.setText(RENAME_FILE);
+      presentation.setDescription(RENAME_FILE);
+    }
+  }
+}
index 7ecf3b2af4771a3871e57f428bab54641e0a6d79..99c74f1ea744de42a224bcb62ea0a0d76522bf37 100644 (file)
@@ -18,10 +18,13 @@ package com.intellij.ui;
 import com.intellij.openapi.actionSystem.*;
 import com.intellij.ui.awt.RelativePoint;
 import com.intellij.util.ui.UIUtil;
+import org.jetbrains.annotations.NotNull;
 import org.jetbrains.annotations.Nullable;
 
 import javax.swing.*;
 import java.awt.*;
+import java.util.HashSet;
+import java.util.Set;
 
 /**
  * @author Konstantin Bulenkov
@@ -32,6 +35,7 @@ public abstract class AnActionButton extends AnAction implements ShortcutProvide
   private ShortcutSet myShortcut;
   private AnAction myAction = null;
   private JComponent myContextComponent;
+  private Set<AnActionButtonUpdater> myUpdaters;
 
   public AnActionButton(String text) {
     super(text);
@@ -92,12 +96,20 @@ public abstract class AnActionButton extends AnAction implements ShortcutProvide
   public final void update(AnActionEvent e) {
     boolean myActionVisible = true;
     boolean myActionEnabled = true;
-    if (myAction != null) {
+    if (myAction != null) {      
       myAction.update(e);
-      myActionEnabled = myAction.getTemplatePresentation().isEnabled();
-      myActionVisible = myAction.getTemplatePresentation().isVisible();
+      myActionEnabled = e.getPresentation().isEnabled();
+      myActionVisible = e.getPresentation().isVisible();
+    }
+    boolean enabled = isEnabled() && isContextComponentOk() && myActionEnabled;
+    if (enabled) {
+      for (AnActionButtonUpdater updater : myUpdaters) {
+        if (!updater.isEnabled(e)) {
+          enabled = false;
+          break;
+        }
+      }
     }
-    final boolean enabled = isEnabled() && isContextComponentOk() && myActionEnabled;
     e.getPresentation().setEnabled(enabled);
     e.getPresentation().setVisible(isVisible() && myActionVisible);
 
@@ -105,6 +117,13 @@ public abstract class AnActionButton extends AnAction implements ShortcutProvide
       updateButton(e);
     }
   }
+  
+  public final void addCustomUpdater(@NotNull AnActionButtonUpdater updater) {
+    if (myUpdaters == null) {
+      myUpdaters = new HashSet<AnActionButtonUpdater>();
+    }
+    myUpdaters.add(updater);
+  }
 
   public void updateButton(AnActionEvent e) {
   }
diff --git a/platform/platform-api/src/com/intellij/ui/AnActionButtonUpdater.java b/platform/platform-api/src/com/intellij/ui/AnActionButtonUpdater.java
new file mode 100644 (file)
index 0000000..bc9cc43
--- /dev/null
@@ -0,0 +1,25 @@
+/*
+ * 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.
+ * 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;
+
+import com.intellij.openapi.actionSystem.AnActionEvent;
+
+/**
+ * @author Konstantin Bulenkov
+ */
+public interface AnActionButtonUpdater {
+  boolean isEnabled(AnActionEvent e);
+}
index 6d49d1718d60c5beae3ce0f95042340d2dd3aa8a..a360e8af39ab44bd04fb476d860ba8fc19f9a677 100644 (file)
@@ -1614,8 +1614,8 @@ public class JBTabsImpl extends JComponent
     if (paintFocused) {
       final Color bgColor = getActiveTabColor(getActiveTabFillIn());
       if (bgColor == null) {
-        shapeInfo.from = UIUtil.getFocusedFillColor();
-        shapeInfo.to = UIUtil.getFocusedFillColor();
+        shapeInfo.from = getFocusedTopFillColor();
+        shapeInfo.to = getFocusedBottomFillColor();
       }
       else {
         bgPreFill = bgColor;
@@ -1674,6 +1674,14 @@ public class JBTabsImpl extends JComponent
     paintBorder(g2d, shapeInfo, borderColor);
   }
 
+  protected Color getFocusedTopFillColor() {
+    return UIUtil.getFocusedFillColor();
+  }
+
+  protected Color getFocusedBottomFillColor() {
+    return UIUtil.getFocusedFillColor();
+  }
+
   protected ShapeInfo computeSelectedLabelShape() {
     final ShapeInfo shape = new ShapeInfo();
 
index 244021290c1ca171ba605ba0827f501bc0e8feca..6dfcfde538f93bd3722edd7c073c344554a48425 100644 (file)
@@ -46,8 +46,8 @@ import com.intellij.ui.docking.DragSession;
 import com.intellij.ui.switcher.SwitchProvider;
 import com.intellij.ui.switcher.SwitchTarget;
 import com.intellij.ui.tabs.*;
-import com.intellij.ui.tabs.impl.JBTabsImpl;
 import com.intellij.ui.tabs.impl.JBEditorTabs;
+import com.intellij.ui.tabs.impl.JBTabsImpl;
 import com.intellij.util.ui.AwtVisitor;
 import com.intellij.util.ui.TimedDeadzone;
 import com.intellij.util.ui.UIUtil;
@@ -86,7 +86,7 @@ final class EditorTabbedContainer implements Disposable, CloseAction.CloseTarget
       public ActionGroup get() {
         return (ActionGroup)CustomActionsSchema.getInstance().getCorrectedAction(IdeActions.GROUP_EDITOR_TAB_POPUP);
       }
-    }, ActionPlaces.EDITOR_POPUP, false).setNavigationActionsEnabled(false).addTabMouseListener(new TabMouseListener()).getPresentation()
+    }, ActionPlaces.EDITOR_TAB_POPUP, false).setNavigationActionsEnabled(false).addTabMouseListener(new TabMouseListener()).getPresentation()
       .setTabDraggingEnabled(true).setUiDecorator(new UiDecorator() {
       @NotNull
       public UiDecoration getDecoration() {
index 12a87ccd6ed0052b6286bfca7cf7ca2e383e3459..7238c588fb279428eeb87d3b2a3f8642ab7c4b20 100644 (file)
               class = "com.intellij.refactoring.actions.RefactoringQuickListPopupAction"
               text = "Refactor This..." description="Context aware popup with list of refactoring actions"/>
       <action id="RenameElement" class="com.intellij.refactoring.actions.RenameElementAction"/>
+      <action id="RenameFile" class="com.intellij.refactoring.rename.RenameFileAction"/>
       <action id="ChangeSignature" class="com.intellij.refactoring.actions.ChangeSignatureAction"/>
       <separator/>
       <action id="Move" class="com.intellij.refactoring.actions.MoveAction"/>
       <reference ref="AddToFavorites"/>
       <reference ref="AddAllToFavorites"/>
       <separator/>
+      <reference ref="RenameFile"/>
+      <separator/>
       <reference ref="MoveToChangeList"/>
       <separator/>
       <reference ref="RunContextPopupGroup"/>
index 6569e065320d5e063743d761c2841ba02ad99804..cc4fbc49ed02813badab809104ef3859d6a8e5c6 100644 (file)
                      bundle="com.siyeh.InspectionGadgetsBundle" key="string.buffer.must.have.initial.capacity.display.name"
                      groupBundle="messages.InspectionsBundle" groupKey="group.names.performance.issues" enabledByDefault="false"
                      level="WARNING" implementationClass="com.siyeh.ig.performance.StringBufferMustHaveInitialCapacityInspection"/>
-    <localInspection language="JAVA" shortName="StringBufferReplaceableByString" bundle="com.siyeh.InspectionGadgetsBundle"
-                     key="string.buffer.replaceable.by.string.display.name" groupBundle="messages.InspectionsBundle"
-                     groupKey="group.names.performance.issues" enabledByDefault="false" level="WARNING"
-                     implementationClass="com.siyeh.ig.performance.StringBufferReplaceableByStringInspection"/>
     <localInspection language="JAVA" shortName="StringBufferToStringInConcatenation" bundle="com.siyeh.InspectionGadgetsBundle"
                      key="string.buffer.to.string.in.concatenation.display.name" groupBundle="messages.InspectionsBundle"
                      groupKey="group.names.performance.issues" enabledByDefault="false" level="WARNING"
                      key="simplifiable.equals.expression.display.name" groupBundle="messages.InspectionsBundle"
                      groupKey="group.names.code.style.issues" enabledByDefault="false" level="WARNING"
                      implementationClass="com.siyeh.ig.style.SimplifiableEqualsExpressionInspection"/>
+    <localInspection language="JAVA" shortName="StringBufferReplaceableByString" bundle="com.siyeh.InspectionGadgetsBundle"
+                     key="string.buffer.replaceable.by.string.display.name" groupBundle="messages.InspectionsBundle"
+                     groupKey="group.names.performance.issues" enabledByDefault="true" level="WARNING"
+                     implementationClass="com.siyeh.ig.style.StringBufferReplaceableByStringInspection"/>
     <localInspection language="JAVA" suppressId="TypeParameterExplicitlyExtendsObject" shortName="TypeParameterExtendsObject"
                      bundle="com.siyeh.InspectionGadgetsBundle" key="type.parameter.extends.object.display.name"
                      groupBundle="messages.InspectionsBundle" groupKey="group.names.code.style.issues" enabledByDefault="true"
index 1e9817d92927ab53ba154be4c865840a86b2aebf..92894cd75ab9d2477c6a71ae04a8c6af4c5632df 100644 (file)
@@ -764,7 +764,7 @@ for.loop.with.missing.component.collection.loop.option=Ignore collection iterati
 double.checked.locking.display.name=Double-checked locking
 double.checked.locking.problem.descriptor=Double-checked locking #loc
 double.checked.locking.ignore.on.volatiles.option=Ignore double-checked locking on volatile fields
-string.buffer.replaceable.by.string.display.name=Constant 'StringBuffer' may be 'String'
+string.buffer.replaceable.by.string.display.name='StringBuffer' can be replaced with 'String'
 boolean.method.name.must.start.with.question.display.name=Boolean method name must start with question word
 class.name.same.as.ancestor.name.display.name=Class name same as ancestor name
 error.rethrown.display.name='java.lang.Error' not rethrown
@@ -1044,7 +1044,7 @@ set.replaceable.by.enum.set.problem.descriptor=<code>#ref</code> replaceable wit
 inner.class.may.be.static.problem.descriptor=Inner class <code>#ref</code> may be 'static' #loc
 string.buffer.must.have.initial.capacity.problem.descriptor=<code>#ref</code> without initial capacity #loc
 string.buffer.replaceable.by.string.builder.problem.descriptor=<code>StringBuffer #ref</code> may be declared as ''StringBuilder'' #loc
-string.buffer.replaceable.by.string.problem.descriptor=Constant <code>{0} #ref</code> may be declared as ''String'' #loc
+string.buffer.replaceable.by.string.problem.descriptor=<code>{0} #ref</code> can be replaced with ''String'' #loc
 string.replaceable.by.string.buffer.problem.descriptor=Non-constant <code>String #ref</code> should probably be declared as ''StringBuilder'' #loc
 collections.must.have.initial.capacity.problem.descriptor=<code>#ref</code> without initial capacity #loc
 string.concatenation.in.loops.problem.descriptor=String concatenation <code>#ref</code> in loop #loc
similarity index 99%
rename from plugins/InspectionGadgets/src/com/siyeh/ig/performance/StringBufferReplaceableByStringInspection.java
rename to plugins/InspectionGadgets/src/com/siyeh/ig/style/StringBufferReplaceableByStringInspection.java
index a77d0cc4161c0832408b3f716d1bf6b8df9ed4cc..9d56ab1b5c69663cd0bc00c79a46b6ca24cc177b 100644 (file)
@@ -13,7 +13,7 @@
  * See the License for the specific language governing permissions and
  * limitations under the License.
  */
-package com.siyeh.ig.performance;
+package com.siyeh.ig.style;
 
 import com.intellij.codeInspection.ProblemDescriptor;
 import com.intellij.openapi.project.Project;
similarity index 98%
rename from plugins/InspectionGadgets/src/com/siyeh/ig/performance/VariableIsModifiedVisitor.java
rename to plugins/InspectionGadgets/src/com/siyeh/ig/style/VariableIsModifiedVisitor.java
index fcccb5a96a46f48120c9ae737dadae54625299c1..748ce1bc5966c4ab38435e3a39af12fc1ffa7b6d 100644 (file)
@@ -13,7 +13,7 @@
  * See the License for the specific language governing permissions and
  * limitations under the License.
  */
-package com.siyeh.ig.performance;
+package com.siyeh.ig.style;
 
 import com.intellij.psi.*;
 import org.jetbrains.annotations.NonNls;
index 2273ce2f01f604cfc978ae09acae52f32316b5db..832b4e495ec3d60d897671810b53a0461fbd33f5 100644 (file)
@@ -1,8 +1,8 @@
 <html>
 <body>
-This inspection reports any variables declared as <b>java.lang.StringBuffer</b>
-and <b>java.lang.StringBuilder</b> which are
-effectively constant, and may thus be declared more efficiently declared as <b>java.lang.String</b>.
+This inspection reports any variables declared as or uses of <b>java.lang.StringBuffer</b> and <b>java.lang.StringBuilder</b>
+which are effectively constant. These may be replaced with <b>java.lang.String</b> expressions which results in simpler and possibly
+more efficient code.
 <p>
 <small>Powered by InspectionGadgets</small>
 </body>
diff --git a/plugins/InspectionGadgets/test/com/siyeh/igtest/performance/StringBufferReplaceableByStringInspection.java b/plugins/InspectionGadgets/test/com/siyeh/igtest/performance/StringBufferReplaceableByStringInspection.java
deleted file mode 100644 (file)
index 085519f..0000000
+++ /dev/null
@@ -1,15 +0,0 @@
-package com.siyeh.igtest.performance;
-
-public class StringBufferReplaceableByStringInspection {
-    public void foo()
-    {
-        final StringBuffer buffer = new StringBuffer();
-        System.out.println(buffer.toString());
-    }
-
-    public void foo2()
-    {
-        final StringBuffer buffer = new StringBuffer("foo").append("bar");
-        System.out.println(buffer.toString());
-    }
-}
diff --git a/plugins/InspectionGadgets/test/com/siyeh/igtest/performance/constant_string_buffer_may_be_string/StringBufferReplaceableByString.java b/plugins/InspectionGadgets/test/com/siyeh/igtest/performance/constant_string_buffer_may_be_string/StringBufferReplaceableByString.java
deleted file mode 100644 (file)
index 7f0eb5b..0000000
+++ /dev/null
@@ -1,11 +0,0 @@
-package com.siyeh.igtest.performance.constant_string_buffer_may_be_string;
-
-public class StringBufferReplaceableByString {
-
-  StringBuilder foo() {
-    StringBuilder builder = new StringBuilder("asdfasdfasdf");
-    StringBuffer buffer = new StringBuffer("test");
-    StringBuilder result = new StringBuilder("return");
-    return result;
-  }
-}
diff --git a/plugins/InspectionGadgets/test/com/siyeh/igtest/performance/constant_string_buffer_may_be_string/expected.xml b/plugins/InspectionGadgets/test/com/siyeh/igtest/performance/constant_string_buffer_may_be_string/expected.xml
deleted file mode 100644 (file)
index 79e5261..0000000
+++ /dev/null
@@ -1,16 +0,0 @@
-<?xml version="1.0" encoding="UTF-8"?>
-<problems>
-  <problem>
-    <file>StringBufferReplaceableByString.java</file>
-    <line>6</line>
-    <problem_class severity="WARNING" attribute_key="WARNING_ATTRIBUTES">Constant StringBuffer may be String</problem_class>
-    <description>Constant &lt;code&gt;StringBuilder builder&lt;/code&gt; may be declared as 'String' #loc</description>
-  </problem>
-
-  <problem>
-    <file>StringBufferReplaceableByString.java</file>
-    <line>7</line>
-    <problem_class severity="WARNING" attribute_key="WARNING_ATTRIBUTES">Constant StringBuffer may be String</problem_class>
-    <description>Constant &lt;code&gt;StringBuffer buffer&lt;/code&gt; may be declared as 'String' #loc</description>
-  </problem>
-</problems>
\ No newline at end of file
diff --git a/plugins/InspectionGadgets/test/com/siyeh/igtest/performance/string_buffer_replaceable_by_string/StringBufferReplaceableByString.java b/plugins/InspectionGadgets/test/com/siyeh/igtest/performance/string_buffer_replaceable_by_string/StringBufferReplaceableByString.java
new file mode 100644 (file)
index 0000000..6c13850
--- /dev/null
@@ -0,0 +1,27 @@
+package com.siyeh.igtest.performance.string_buffer_replaceable_by_string;
+
+public class StringBufferReplaceableByString {
+
+  StringBuilder foo() {
+    StringBuilder builder = new StringBuilder("asdfasdfasdf");
+    StringBuffer buffer = new StringBuffer("test");
+    StringBuilder result = new StringBuilder("return");
+    return result;
+  }
+
+  public void foo1()
+  {
+    final StringBuffer buffer = new StringBuffer();
+    System.out.println(buffer.toString());
+  }
+
+  public void foo2()
+  {
+    final StringBuffer buffer = new StringBuffer("foo").append("bar");
+    System.out.println(buffer.toString());
+  }
+
+  public void bar(int i) {
+    System.out.println(new StringBuilder("asdf").append(i).toString());
+  }
+}
diff --git a/plugins/InspectionGadgets/test/com/siyeh/igtest/performance/string_buffer_replaceable_by_string/expected.xml b/plugins/InspectionGadgets/test/com/siyeh/igtest/performance/string_buffer_replaceable_by_string/expected.xml
new file mode 100644 (file)
index 0000000..fbc4c4e
--- /dev/null
@@ -0,0 +1,30 @@
+<?xml version="1.0" encoding="UTF-8"?>
+<problems>
+  <problem>
+    <file>StringBufferReplaceableByString.java</file>
+    <line>6</line>
+    <problem_class severity="WARNING" attribute_key="WARNING_ATTRIBUTES">'StringBuffer' can be replaced with 'String'</problem_class>
+    <description>&lt;code&gt;StringBuilder builder&lt;/code&gt; can be replaced with 'String' #loc</description>
+  </problem>
+
+  <problem>
+    <file>StringBufferReplaceableByString.java</file>
+    <line>7</line>
+    <problem_class severity="WARNING" attribute_key="WARNING_ATTRIBUTES">'StringBuffer' can be replaced with 'String'</problem_class>
+    <description>&lt;code&gt;StringBuffer buffer&lt;/code&gt; can be replaced with 'String' #loc</description>
+  </problem>
+
+  <problem>
+    <file>StringBufferReplaceableByString.java</file>
+    <line>14</line>
+    <problem_class severity="WARNING" attribute_key="WARNING_ATTRIBUTES">'StringBuffer' can be replaced with 'String'</problem_class>
+    <description>&lt;code&gt;StringBuffer buffer&lt;/code&gt; can be replaced with 'String' #loc</description>
+  </problem>
+
+  <problem>
+    <file>StringBufferReplaceableByString.java</file>
+    <line>20</line>
+    <problem_class severity="WARNING" attribute_key="WARNING_ATTRIBUTES">'StringBuffer' can be replaced with 'String'</problem_class>
+    <description>&lt;code&gt;StringBuffer buffer&lt;/code&gt; can be replaced with 'String' #loc</description>
+  </problem>
+</problems>
\ No newline at end of file
similarity index 67%
rename from plugins/InspectionGadgets/testsrc/com/siyeh/ig/performance/StringBufferReplaceableByStringInspectionTest.java
rename to plugins/InspectionGadgets/testsrc/com/siyeh/ig/style/StringBufferReplaceableByStringInspectionTest.java
index 7b9a0e928b64a425a0309acdbc085da201801c82..b27d8cd46527e76a5d2c6a5b7be9ecea2938ca37 100644 (file)
@@ -1,11 +1,11 @@
-package com.siyeh.ig.performance;
+package com.siyeh.ig.style;
 
 import com.siyeh.ig.IGInspectionTestCase;
 
 public class StringBufferReplaceableByStringInspectionTest extends IGInspectionTestCase {
 
   public void test() throws Exception {
-    doTest("com/siyeh/igtest/performance/constant_string_buffer_may_be_string",
+    doTest("com/siyeh/igtest/performance/string_buffer_replaceable_by_string",
            new StringBufferReplaceableByStringInspection());
   }
 }
\ No newline at end of file
index ee955978e75ce1fd711da434519aa437100d6bac..9a1384fa312ad103ac6912e0938accf5266158fb 100644 (file)
       <add-to-group group-id="Internal"/>
     </group>
 
-    <action id="RenameJavaFileToGroovyFileAction"
-            class="org.jetbrains.plugins.groovy.refactoring.javaToGrovyRename.RenameJavaFileToGroovyFileAction"
-            text="Rename To Groovy" description="Rename Java File to Groovy">
-      <add-to-group group-id="EditorTabPopupMenu" anchor="last"/>
-    </action>
     <action id="ExcludeFromStubGeneration"
             class="org.jetbrains.plugins.groovy.compiler.ExcludeFromStubGenerationAction"
             text="Exclude from stub generation" description="Don't generate Java stubs for this Groovy file on compilation">
index 9fbdb46715557a091e2f6905a0aed0ebe5cf355d..3f85a1e6649be006e95f66501e8feaf3bea267b0 100644 (file)
@@ -98,15 +98,33 @@ public class GroovyCodeFragmentFactory implements CodeFragmentFactory {
     if (!isStatic) {
       javaText.append("java.lang.Object |thiz0;\n");
 
+      String fileName;
+
       PsiElement originalContext = context.getContainingFile().getContext();
-      String fileName = originalContext == null ? null : originalContext.getContainingFile().getOriginalFile().getName();
+      if (originalContext == null) {
+        fileName = null; // The class is not reloaded by springloaded if context is in physical file.
+      }
+      else {
+        fileName = originalContext.getContainingFile().getOriginalFile().getName();
+      }
 
       if (fileName == null) {
+        // The class could not be reloaded by springloaded
         javaText.append("|thiz0 = this;\n");
       }
       else {
+        // Class could be reloaded by springloaded
+
         String s = StringUtil.escapeStringCharacters(Pattern.quote(fileName));
-        javaText.append("if (java.util.Arrays.toString(new Exception().getStackTrace()).matches(\"[^,]+\\\\$\\\\$[A-Za-z0-9]{8}\\\\.[^,]+\\\\(" + s + ":\\\\d+\\\\), .+com\\\\.springsource\\\\.loaded\\\\..+\")) {\n");
+        // We believe what class is reloaded if stacktrace matches one of two patterns:
+        // 1.) [com.package.Foo$$ENLbVXwm.methodName(FileName.groovy:12), com.package.Foo$$DNLbVXwm.methodName(Unknown Source), *
+        // 2.) [com.package.Foo$$ENLbVXwm.methodName(FileName.groovy:12), * com.springsource.loaded. *
+        // Pattern below test this.
+
+        //javaText.append("System.out.println(java.util.Arrays.toString(new Exception().getStackTrace()));\n");
+        //javaText.append("System.out.println(\"\\\\[([^,()]+\\\\$\\\\$)[A-Za-z0-9]{8}(\\\\.[^,()]+)\\\\(" + s + ":\\\\d+\\\\), (\\\\1[A-Za-z0-9]{8}\\\\2\\\\(Unknown Source\\\\), |.+com\\\\.springsource\\\\.loaded\\\\.).+\")\n");
+
+        javaText.append("if (java.util.Arrays.toString(new Exception().getStackTrace()).matches(\"\\\\[([^,()]+\\\\$\\\\$)[A-Za-z0-9]{8}(\\\\.[^,()]+)\\\\(" + s + ":\\\\d+\\\\), (\\\\1[A-Za-z0-9]{8}\\\\2\\\\(Unknown Source\\\\), $OR$.+com\\\\.springsource\\\\.loaded\\\\.).+\")) {\n");
         javaText.append("  |thiz0 = thiz;\n");
         javaText.append(" } else {\n");
         javaText.append("  |thiz0 = this;\n");
@@ -157,7 +175,8 @@ public class GroovyCodeFragmentFactory implements CodeFragmentFactory {
 
     final PsiElementFactory factory = JavaPsiFacade.getInstance(toEval.getProject()).getElementFactory();
 
-    final String hiddenJavaVars = StringUtil.replace(javaText.toString(), "|", "_$$_$$$_$$$$$$$$$_" + new Random().nextInt(42));
+    String hiddenJavaVars = StringUtil.replace(javaText.toString(), "|", "_$$_$$$_$$$$$$$$$_" + new Random().nextInt(42));
+    hiddenJavaVars = hiddenJavaVars.replaceAll("\\$OR\\$", "|");
     final String finalText = StringUtil.replace(StringUtil.replace(hiddenJavaVars, TEXT, groovyText), IMPORTS, imports);
     JavaCodeFragment result = JavaCodeFragmentFactory.getInstance(project).createCodeBlockCodeFragment(finalText, null, true);
     if (contextClass != null) {
diff --git a/plugins/groovy/src/org/jetbrains/plugins/groovy/formatter/AlignmentProvider.java b/plugins/groovy/src/org/jetbrains/plugins/groovy/formatter/AlignmentProvider.java
new file mode 100644 (file)
index 0000000..58c06ba
--- /dev/null
@@ -0,0 +1,140 @@
+/*
+ * 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.
+ * 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.lang.ASTNode;
+import com.intellij.openapi.diagnostic.Logger;
+import com.intellij.psi.PsiElement;
+import com.intellij.util.containers.hash.HashSet;
+import org.jetbrains.annotations.Nullable;
+
+import java.util.HashMap;
+import java.util.Map;
+import java.util.Set;
+
+/**
+ * @author Max Medvedev
+ */
+class AlignmentProvider {
+  private final static Logger LOG = Logger.getInstance(AlignmentProvider.class);
+
+  private final Map<PsiElement, Set<PsiElement>> myTree = new HashMap<PsiElement, Set<PsiElement>>();
+  private final Map<Set<PsiElement>, Alignment> myAlignments = new HashMap<Set<PsiElement>, Alignment>();
+
+  public void addPair(PsiElement e1, PsiElement e2) {
+    LOG.assertTrue(e1 != e2);
+
+    final Set<PsiElement> set1 = myTree.get(e1);
+    final Set<PsiElement> set2 = myTree.get(e2);
+
+    LOG.assertTrue(!(set1 != null && set2 != null));
+
+    if (set1 != null) {
+      set1.add(e2);
+      myTree.put(e2, set1);
+    }
+    else if (set2 != null) {
+      set2.add(e1);
+      myTree.put(e1, set2);
+    }
+    else {
+      final HashSet<PsiElement> set = createHashSet();
+
+      myTree.put(e1, set);
+      myTree.put(e2, set);
+    }
+  }
+
+  private static HashSet<PsiElement> createHashSet() {
+    return new HashSet<PsiElement>() {
+      private final int myhash = new Object().hashCode();
+
+      @Override
+      public int hashCode() {
+        return myhash;
+      }
+    };
+  }
+
+  public void addPair(ASTNode node1, ASTNode node2) {
+    addPair(node1.getPsi(), node2.getPsi());
+  }
+
+  private void add(PsiElement element) {
+    if (myTree.get(element) != null) return;
+
+    final HashSet<PsiElement> set = createHashSet();
+    set.add(element);
+    myTree.put(element, set);
+  }
+
+  @Nullable
+  public Alignment getAlignment(PsiElement e) {
+    final Set<PsiElement> set = myTree.get(e);
+    if (set == null) {
+      return null;
+    }
+
+    Alignment alignment = myAlignments.get(set);
+    if (alignment != null) return alignment;
+
+    alignment = Alignment.createAlignment(true);
+    myAlignments.put(set, alignment);
+    return alignment;
+  }
+
+  @Nullable
+  public Alignment getAlignment(ASTNode node) {
+    return getAlignment(node.getPsi());
+  }
+  
+  public Aligner createAligner(PsiElement expression) {
+    return new Aligner(expression);
+  }
+
+  public Aligner createAligner() {
+    return new Aligner();
+  }
+
+  /**
+   * This class helps to assign one alignment to some elements.
+   * You can create an instance of Aligner and apply 'append' to any element, you want to be aligned.
+   *
+   * @author Max Medvedev
+   */
+  class Aligner {
+    private PsiElement myRef = null;
+
+    private Aligner(){}
+
+    private Aligner(PsiElement initial) {
+      myRef = initial;
+    }
+
+    void append(@Nullable PsiElement element) {
+      if (element == null) return;
+
+      if (myRef == null) {
+        myRef = element;
+        add(element);
+      }
+      else {
+        addPair(myRef, element);
+      }
+    }
+  }
+}
index b3482defa34869f38f38a71028c650ee48acf0d1..cf080d546e77de0a68c3952a1e70a027dffdf6d2 100644 (file)
@@ -15,7 +15,6 @@
  */
 package org.jetbrains.plugins.groovy.formatter;
 
-import com.intellij.formatting.Alignment;
 import com.intellij.lang.ASTNode;
 import com.intellij.openapi.diagnostic.Logger;
 import com.intellij.psi.PsiElement;
@@ -29,8 +28,6 @@ import org.jetbrains.plugins.groovy.lang.psi.api.statements.expressions.GrMethod
 import org.jetbrains.plugins.groovy.lang.psi.api.statements.expressions.GrReferenceExpression;
 import org.jetbrains.plugins.groovy.lang.psi.util.PsiUtil;
 
-import java.util.Map;
-
 import static org.jetbrains.plugins.groovy.lang.lexer.GroovyTokenTypes.mRCURLY;
 import static org.jetbrains.plugins.groovy.lang.lexer.TokenSets.WHITE_SPACES_SET;
 import static org.jetbrains.plugins.groovy.lang.parser.GroovyElementTypes.CLOSABLE_BLOCK;
@@ -81,12 +78,11 @@ public class GeeseUtil {
     return next;
   }
 
-  @Nullable
-  static Alignment calculateRBraceAlignment(PsiElement rBrace, Map<PsiElement, Alignment> alignments) {
+  static void calculateRBraceAlignment(PsiElement rBrace, AlignmentProvider alignments) {
     int leadingBraceCount = 0;
     PsiElement next;
 
-    if (!isClosureContainLF(rBrace)) return null;
+    if (!isClosureContainLF(rBrace)) return;
 
     for (next = getPreviousNonWhitespaceToken(rBrace);
          isClosureRBrace(next) && isClosureContainLF(next);
@@ -131,7 +127,7 @@ public class GeeseUtil {
     int endOffset = rBrace.getTextRange().getStartOffset();
 
     if (rBrace.getContainingFile().getText().substring(startOffset, endOffset).indexOf('\n') < 0) {
-      return null;
+      return;
     }
 
     while (true) {
@@ -143,13 +139,7 @@ public class GeeseUtil {
         break;
       }
     }
-
-    Alignment alignment = alignments.get(cur);
-    if (alignment == null) {
-      alignment = Alignment.createAlignment(true);
-      alignments.put(cur, alignment);
-    }
-    return alignment;
+    alignments.addPair(rBrace, cur);
   }
 
   public static boolean isClosureContainLF(PsiElement rBrace) {
index 48d99924c2038d05f07f12b2ba7af6b1dbe918c2..9ed0e9a3a0d59fbf6c3666ea9031054f1447e32e 100644 (file)
@@ -48,7 +48,6 @@ import org.jetbrains.plugins.groovy.lang.psi.api.statements.expressions.GrComman
 import org.jetbrains.plugins.groovy.lang.psi.api.statements.params.GrParameterList;
 
 import java.util.List;
-import java.util.Map;
 
 /**
  * Block implementation for Groovy formatter
@@ -62,34 +61,25 @@ public class GroovyBlock implements Block, GroovyElementTypes, ASTBlock {
   final protected Wrap myWrap;
   final protected CommonCodeStyleSettings mySettings;
   final protected GroovyCodeStyleSettings myGroovySettings;
-  final protected Map<PsiElement, Alignment> myInnerAlignments;
+  final protected AlignmentProvider myAlignmentProvider;
 
   protected List<Block> mySubBlocks = null;
 
   public GroovyBlock(@NotNull final ASTNode node,
-                     @Nullable Alignment alignment,
                      @NotNull final Indent indent,
                      @Nullable final Wrap wrap,
                      final CommonCodeStyleSettings settings,
                      GroovyCodeStyleSettings groovySettings,
-                     @NotNull Map<PsiElement, Alignment> innerAlignments) {
+                     @NotNull AlignmentProvider alignmentProvider) {
     myNode = node;
-    if (groovySettings.USE_FLYING_GEESE_BRACES) {
-      PsiElement psi = myNode.getPsi();
-      if (alignment == null) {
-        alignment = innerAlignments.get(psi);
-      }
-      else {
-        innerAlignments.put(psi, alignment);
-      }
-    }
-    myAlignment = alignment;
 
     myIndent = indent;
     myWrap = wrap;
     mySettings = settings;
     myGroovySettings = groovySettings;
-    myInnerAlignments = innerAlignments;
+    myAlignmentProvider = alignmentProvider;
+
+    myAlignment = myAlignmentProvider.getAlignment(node.getPsi());
   }
 
   @NotNull
@@ -106,8 +96,8 @@ public class GroovyBlock implements Block, GroovyElementTypes, ASTBlock {
     return myGroovySettings;
   }
 
-  public Map<PsiElement, Alignment> getInnerAlignments() {
-    return myInnerAlignments;
+  public AlignmentProvider getAlignmentProvider() {
+    return myAlignmentProvider;
   }
 
   @NotNull
@@ -193,7 +183,7 @@ public class GroovyBlock implements Block, GroovyElementTypes, ASTBlock {
         SWITCH_STATEMENT.equals(astNode.getElementType())) {
 //      PsiElement psi = ((GroovyBlock)getSubBlocks().get(newChildIndex)).getNode().getPsi();
       //     if (GeeseUtil.isClosureRBrace(psi)) {
-      //     return new ChildAttributes(Indent.getNoneIndent(), GeeseUtil.calculateRBraceAlignment(psi, myInnerAlignments));
+      //     return new ChildAttributes(Indent.getNoneIndent(), GeeseUtil.calculateRBraceAlignment(psi, myAlignmentProvider));
       //  }
 
       return new ChildAttributes(Indent.getNormalIndent(), null);
index dcc7e2719d92b30f99d7573ec4830d822af88f51..cf293b66cb1924a22b1e3749ea894cc73785db46 100644 (file)
@@ -33,7 +33,6 @@ import com.intellij.psi.impl.source.tree.LeafPsiElement;
 import com.intellij.psi.templateLanguages.OuterLanguageElement;
 import com.intellij.psi.tree.IElementType;
 import com.intellij.psi.tree.TokenSet;
-import com.intellij.util.containers.ContainerUtil;
 import org.jetbrains.annotations.NotNull;
 import org.jetbrains.annotations.Nullable;
 import org.jetbrains.plugins.groovy.GroovyFileType;
@@ -60,7 +59,9 @@ import org.jetbrains.plugins.groovy.lang.psi.api.statements.params.GrParameterLi
 import org.jetbrains.plugins.groovy.lang.psi.api.statements.typedef.GrExtendsClause;
 import org.jetbrains.plugins.groovy.lang.psi.api.statements.typedef.GrTypeDefinitionBody;
 
-import java.util.*;
+import java.util.ArrayList;
+import java.util.LinkedList;
+import java.util.List;
 
 /**
  * Utility class to generate myBlock hierarchy
@@ -81,7 +82,7 @@ public class GroovyBlockGenerator implements GroovyElementTypes {
   private final Alignment myAlignment;
   private final Wrap myWrap;
   private final CommonCodeStyleSettings mySettings;
-  private final Map<PsiElement,Alignment> myInnerAlignments;
+  private final AlignmentProvider myAlignmentProvider;
   private final GroovyCodeStyleSettings myGroovySettings;
 
   public GroovyBlockGenerator(GroovyBlock block) {
@@ -90,7 +91,7 @@ public class GroovyBlockGenerator implements GroovyElementTypes {
     myAlignment = myBlock.getAlignment();
     myWrap = myBlock.getWrap();
     mySettings = myBlock.getSettings();
-    myInnerAlignments = myBlock.getInnerAlignments();
+    myAlignmentProvider = myBlock.getAlignmentProvider();
     myGroovySettings = myBlock.getGroovySettings();
   }
 
@@ -134,7 +135,10 @@ public class GroovyBlockGenerator implements GroovyElementTypes {
       for (ASTNode childNode : children) {
         if (childNode.getTextRange().getLength() > 0) {
           final Indent indent = GroovyIndentProcessor.getChildIndent(myBlock, childNode);
-          subBlocks.add(new GroovyBlock(childNode, myAlignment, indent, myWrap, mySettings, myGroovySettings, myInnerAlignments));
+          if (myAlignment != null) {
+            myAlignmentProvider.addPair(myNode, childNode);
+          }
+          subBlocks.add(new GroovyBlock(childNode, indent, myWrap, mySettings, myGroovySettings, myAlignmentProvider));
         }
       }
       return subBlocks;
@@ -143,8 +147,8 @@ public class GroovyBlockGenerator implements GroovyElementTypes {
     // chained properties, calls, indexing, etc
     if (NESTED.contains(myNode.getElementType()) && blockPsi.getParent() != null && !NESTED.contains(blockPsi.getParent().getNode().getElementType())) {
       final List<Block> subBlocks = new ArrayList<Block>();
-      Alignment dotsAlignment = mySettings.ALIGN_MULTILINE_CHAINED_METHODS ? Alignment.createAlignment() : null;
-      addNestedChildren(myNode.getPsi(), subBlocks, dotsAlignment, true);
+      AlignmentProvider.Aligner dotsAligner = mySettings.ALIGN_MULTILINE_CHAINED_METHODS ? myAlignmentProvider.createAligner() : null;
+      addNestedChildren(myNode.getPsi(), subBlocks, dotsAligner, true);
       return subBlocks;
     }
 
@@ -152,10 +156,16 @@ public class GroovyBlockGenerator implements GroovyElementTypes {
     if (isListLikeClause(blockPsi)) {
       final ArrayList<Block> subBlocks = new ArrayList<Block>();
       List<ASTNode> astNodes = visibleChildren(myNode);
-      final Alignment newAlignment = mustAlign(blockPsi, astNodes) ? Alignment.createAlignment() : null;
+
+      if (mustAlign(blockPsi, astNodes)) {
+        final AlignmentProvider.Aligner aligner = myAlignmentProvider.createAligner();
+        for (ASTNode node : astNodes) {
+          if (!isKeyword(node)) aligner.append(node.getPsi());
+        }
+      }
       for (ASTNode childNode : astNodes) {
         final Indent indent = GroovyIndentProcessor.getChildIndent(myBlock, childNode);
-        subBlocks.add(new GroovyBlock(childNode, isKeyword(childNode) ? null : newAlignment, indent, myWrap, mySettings, myGroovySettings, myInnerAlignments));
+        subBlocks.add(new GroovyBlock(childNode, indent, myWrap, mySettings, myGroovySettings, myAlignmentProvider));
       }
       return subBlocks;
     }
@@ -165,10 +175,16 @@ public class GroovyBlockGenerator implements GroovyElementTypes {
       List<ASTNode> children = visibleChildren(myNode);
       calculateAlignments(children, classLevel);
       final ArrayList<Block> subBlocks = new ArrayList<Block>();
+
+      if (classLevel && myAlignment != null) {
+        final AlignmentProvider.Aligner aligner = myAlignmentProvider.createAligner();
+        for (ASTNode child : children) {
+          aligner.append(child.getPsi());
+        }
+      }
       for (ASTNode childNode : children) {
         final Indent indent = GroovyIndentProcessor.getChildIndent(myBlock, childNode);
-        Alignment alignmentToUse = classLevel ? myAlignment : myInnerAlignments.get(childNode.getPsi());
-        subBlocks.add(new GroovyBlock(childNode, alignmentToUse, indent, myWrap, mySettings, myGroovySettings, myInnerAlignments));
+        subBlocks.add(new GroovyBlock(childNode, indent, myWrap, mySettings, myGroovySettings, myAlignmentProvider));
       }
       return subBlocks;
     }
@@ -177,13 +193,14 @@ public class GroovyBlockGenerator implements GroovyElementTypes {
     final ArrayList<Block> subBlocks = new ArrayList<Block>();
     for (ASTNode childNode : visibleChildren(myNode)) {
       final Indent indent = GroovyIndentProcessor.getChildIndent(myBlock, childNode);
-      subBlocks.add(new GroovyBlock(childNode, myInnerAlignments.get(childNode.getPsi()), indent, myWrap, mySettings, myGroovySettings, myInnerAlignments));
+      subBlocks.add(new GroovyBlock(childNode, indent, myWrap, mySettings, myGroovySettings, myAlignmentProvider));
     }
     return subBlocks;
   }
+  
 
   private void calculateAlignments(List<ASTNode> children, boolean classLevel) {
-    List<Alignment> currentGroup = null;
+    List<AlignmentProvider.Aligner> currentGroup = null;
     for (ASTNode child : children) {
       PsiElement psi = child.getPsi();
       if (psi instanceof GrLabeledStatement) {
@@ -192,43 +209,46 @@ public class GroovyBlockGenerator implements GroovyElementTypes {
           currentGroup = null;
         }
         else {
-          currentGroup = new ArrayList<Alignment>();
+          currentGroup = new ArrayList<AlignmentProvider.Aligner>();
           for (LeafPsiElement expression : table) {
-            Alignment alignment = Alignment.createAlignment(true);
-            currentGroup.add(alignment);
-            ContainerUtil.putIfNotNull(expression, alignment, myInnerAlignments);
+            currentGroup.add(myAlignmentProvider.createAligner(expression));
           }
         }
-      } else if (currentGroup != null && isTablePart(psi)) {
+      }
+      else if (currentGroup != null && isTablePart(psi)) {
         List<LeafPsiElement> table = getSpockTable((GrStatement)psi);
         for (int i = 0; i < Math.min(table.size(), currentGroup.size()); i++) {
-          myInnerAlignments.put(table.get(i), currentGroup.get(i));
+          currentGroup.get(i).append(table.get(i));
         }
-      } else if (psi instanceof GrVariableDeclaration) {
-        if (!classLevel || currentGroup == null || fieldGroupEnded(psi)) {
-          currentGroup = Arrays.asList(Alignment.createAlignment(true), Alignment.createAlignment(true), Alignment.createAlignment(true));
-        }
-
-        GrVariable[] variables = ((GrVariableDeclaration)psi).getVariables();
+      }
+      else if (psi instanceof GrVariableDeclaration) {
+        final GrVariableDeclaration varDeclaration = (GrVariableDeclaration)psi;
+        GrVariable[] variables = varDeclaration.getVariables();
         if (variables.length > 0) {
-          Alignment varName = currentGroup.get(1);
+          if (!classLevel || currentGroup == null || fieldGroupEnded(psi)) {
+            currentGroup = new ArrayList<AlignmentProvider.Aligner>();
+            currentGroup.add(myAlignmentProvider.createAligner());
+            currentGroup.add(myAlignmentProvider.createAligner());
+            currentGroup.add(myAlignmentProvider.createAligner());
+          }
+
+          AlignmentProvider.Aligner varName = currentGroup.get(1);
           for (GrVariable variable : variables) {
-            myInnerAlignments.put(variable.getNameIdentifierGroovy(), varName);
+            varName.append(variable.getNameIdentifierGroovy());
           }
 
           if (classLevel && mySettings.ALIGN_GROUP_FIELD_DECLARATIONS) {
-            ContainerUtil.putIfNotNull(((GrVariableDeclaration)psi).getTypeElementGroovy(), currentGroup.get(0), myInnerAlignments);
+            final AlignmentProvider.Aligner typeElement = currentGroup.get(0);
+            typeElement.append(varDeclaration.getTypeElementGroovy());
 
-            ASTNode eq = variables[variables.length - 1].getNode().findChildByType(GroovyTokenTypes.mASSIGN);
-            if (eq != null) {
-              myInnerAlignments.put(eq.getPsi(), currentGroup.get(2));
+            ASTNode current_eq = variables[variables.length - 1].getNode().findChildByType(GroovyTokenTypes.mASSIGN);
+            final AlignmentProvider.Aligner eq = currentGroup.get(2);
+            if (current_eq != null) {
+              eq.append(current_eq.getPsi());
             }
           }
         }
       }
-      /*else if (GeeseUtil.isClosureRBrace(psi) && myGroovySettings.USE_FLYING_GEESE_BRACES) {
-        myInnerAlignments.put(psi, GeeseUtil.calculateRBraceAlignment(psi, myInnerAlignments, myBlocks));
-      }*/
       else {
         if (psi instanceof PsiComment) {
           PsiElement prev = psi.getPrevSibling();
@@ -319,19 +339,19 @@ public class GroovyBlockGenerator implements GroovyElementTypes {
     final int start = myNode.getTextRange().getStartOffset();
     final int end = myNode.getTextRange().getEndOffset();
 
-    subBlocks.add(new GroovyBlock(myNode, myAlignment, Indent.getNoneIndent(), myWrap, mySettings, myGroovySettings, myInnerAlignments) {
+    subBlocks.add(new GroovyBlock(myNode, Indent.getNoneIndent(), myWrap, mySettings, myGroovySettings, myAlignmentProvider) {
       @NotNull
       public TextRange getTextRange() {
         return new TextRange(start, start + 3);
       }
     });
-    subBlocks.add(new GroovyBlock(myNode, myAlignment, Indent.getAbsoluteNoneIndent(), myWrap, mySettings, myGroovySettings, myInnerAlignments) {
+    subBlocks.add(new GroovyBlock(myNode, Indent.getAbsoluteNoneIndent(), myWrap, mySettings, myGroovySettings, myAlignmentProvider) {
       @NotNull
       public TextRange getTextRange() {
         return new TextRange(start + 3, end - 3);
       }
     });
-    subBlocks.add(new GroovyBlock(myNode, myAlignment, Indent.getAbsoluteNoneIndent(), myWrap, mySettings, myGroovySettings, myInnerAlignments) {
+    subBlocks.add(new GroovyBlock(myNode, Indent.getAbsoluteNoneIndent(), myWrap, mySettings, myGroovySettings, myAlignmentProvider) {
       @NotNull
       public TextRange getTextRange() {
         return new TextRange(end - 3, end);
@@ -345,13 +365,13 @@ public class GroovyBlockGenerator implements GroovyElementTypes {
     final int start = myNode.getTextRange().getStartOffset();
     final int end = myNode.getTextRange().getEndOffset();
 
-    subBlocks.add(new GroovyBlock(myNode, myAlignment, Indent.getNoneIndent(), myWrap, mySettings, myGroovySettings, myInnerAlignments) {
+    subBlocks.add(new GroovyBlock(myNode, Indent.getNoneIndent(), myWrap, mySettings, myGroovySettings, myAlignmentProvider) {
       @NotNull
       public TextRange getTextRange() {
         return new TextRange(start, start + 3);
       }
     });
-    subBlocks.add(new GroovyBlock(myNode, myAlignment, Indent.getAbsoluteNoneIndent(), myWrap, mySettings, myGroovySettings, myInnerAlignments) {
+    subBlocks.add(new GroovyBlock(myNode, Indent.getAbsoluteNoneIndent(), myWrap, mySettings, myGroovySettings, myAlignmentProvider) {
       @NotNull
       public TextRange getTextRange() {
         return new TextRange(start + 3, end);
@@ -402,12 +422,12 @@ public class GroovyBlockGenerator implements GroovyElementTypes {
    */
   private List<Block> generateForBinaryExpr() {
     final ArrayList<Block> subBlocks = new ArrayList<Block>();
-    Alignment alignment = mySettings.ALIGN_MULTILINE_BINARY_OPERATION ? Alignment.createAlignment() : null;
+    AlignmentProvider.Aligner
+      alignment = mySettings.ALIGN_MULTILINE_BINARY_OPERATION ? myAlignmentProvider.createAligner() : null;
 
     GrBinaryExpression binary = (GrBinaryExpression)myNode.getPsi();
     LOG.assertTrue(binary != null);
-    addBinaryChildrenRecursively(binary, subBlocks, Indent.getContinuationWithoutFirstIndent(), alignment
-    );
+    addBinaryChildrenRecursively(binary, subBlocks, Indent.getContinuationWithoutFirstIndent(), alignment);
     return subBlocks;
   }
 
@@ -417,37 +437,35 @@ public class GroovyBlockGenerator implements GroovyElementTypes {
    * @param elem
    * @param list
    * @param indent
-   * @param alignment
+   * @param aligner
    */
-  private void addBinaryChildrenRecursively(PsiElement elem, List<Block> list, Indent indent, Alignment alignment) {
+  private void addBinaryChildrenRecursively(PsiElement elem, List<Block> list, Indent indent, @Nullable AlignmentProvider.Aligner aligner) {
     if (elem == null) return;
     // For binary expressions
     if ((elem instanceof GrBinaryExpression)) {
       GrBinaryExpression myExpr = ((GrBinaryExpression) elem);
       if (myExpr.getLeftOperand() instanceof GrBinaryExpression) {
-        addBinaryChildrenRecursively(myExpr.getLeftOperand(), list, Indent.getContinuationWithoutFirstIndent(), alignment
-        );
+        addBinaryChildrenRecursively(myExpr.getLeftOperand(), list, Indent.getContinuationWithoutFirstIndent(), aligner);
       }
       PsiElement op = ((GrBinaryExpression)elem).getOperationToken();
       for (ASTNode childNode : visibleChildren(elem.getNode())) {
         PsiElement psi = childNode.getPsi();
         if (!(psi instanceof GrBinaryExpression)) {
-          Alignment alignmentToUse = op == psi ? myInnerAlignments.get(op) : alignment;
-          list.add(new GroovyBlock(childNode, alignmentToUse, indent, myWrap, mySettings, myGroovySettings, myInnerAlignments));
+          if (op != psi && aligner != null) {
+            aligner.append(psi);
+          }
+          list.add(new GroovyBlock(childNode, indent, myWrap, mySettings, myGroovySettings, myAlignmentProvider));
         }
       }
       if (myExpr.getRightOperand() instanceof GrBinaryExpression) {
-        addBinaryChildrenRecursively(myExpr.getRightOperand(), list, Indent.getContinuationWithoutFirstIndent(), alignment
+        addBinaryChildrenRecursively(myExpr.getRightOperand(), list, Indent.getContinuationWithoutFirstIndent(), aligner
         );
       }
     }
   }
 
 
-  private void addNestedChildren(final PsiElement elem,
-                                        List<Block> list,
-                                        @Nullable final Alignment alignment,
-                                        final boolean topLevel) {
+  private void addNestedChildren(final PsiElement elem, List<Block> list, @Nullable AlignmentProvider.Aligner aligner, final boolean topLevel) {
     final List<ASTNode> children = visibleChildren(elem.getNode());
     if (elem instanceof GrMethodCallExpression) {
       GrExpression invokedExpression = ((GrMethodCallExpression)elem).getInvokedExpression();
@@ -458,11 +476,11 @@ public class GroovyBlockGenerator implements GroovyElementTypes {
           int i = 0;
           while (i < grandChildren.size() && nameElement != grandChildren.get(i).getPsi()) { i++; }
           if (i > 0) {
-            processNestedChildrenPrefix(list, alignment, false, grandChildren, i);
+            processNestedChildrenPrefix(list, aligner, false, grandChildren, i);
           }
           if (i < grandChildren.size()) {
             LOG.assertTrue(nameElement == grandChildren.get(i).getPsi());
-            list.add(new MethodCallWithoutQualifierBlock(nameElement, null, myWrap, mySettings, myGroovySettings, topLevel, children, elem, myInnerAlignments));
+            list.add(new MethodCallWithoutQualifierBlock(nameElement, myWrap, mySettings, myGroovySettings, topLevel, children, elem, myAlignmentProvider));
           }
           return;
         }
@@ -471,24 +489,23 @@ public class GroovyBlockGenerator implements GroovyElementTypes {
     }
 
 
-    processNestedChildrenPrefix(list, alignment, topLevel, children, children.size());
+    processNestedChildrenPrefix(list, aligner, topLevel, children, children.size());
   }
 
-  private void processNestedChildrenPrefix(List<Block> list, Alignment alignment, boolean topLevel, List<ASTNode> children, int limit) {
+  private void processNestedChildrenPrefix(List<Block> list, @Nullable AlignmentProvider.Aligner aligner, boolean topLevel, List<ASTNode> children, int limit) {
     ASTNode fst = children.get(0);
     LOG.assertTrue(limit > 0);
     if (NESTED.contains(fst.getElementType())) {
-      addNestedChildren(fst.getPsi(), list, alignment, false);
+      addNestedChildren(fst.getPsi(), list, aligner, false);
     }
     else {
-      Alignment alignmentToUse = myInnerAlignments.get(fst.getPsi());
       Indent indent = Indent.getContinuationWithoutFirstIndent();
-      list.add(new GroovyBlock(fst, alignmentToUse, indent, myWrap, mySettings, myGroovySettings, myInnerAlignments));
+      list.add(new GroovyBlock(fst, indent, myWrap, mySettings, myGroovySettings, myAlignmentProvider));
     }
-    addNestedChildrenSuffix(list, alignment, topLevel, children, limit);
+    addNestedChildrenSuffix(list, aligner, topLevel, children, limit);
   }
 
-  void addNestedChildrenSuffix(List<Block> list, Alignment alignment, boolean topLevel, List<ASTNode> children, int limit) {
+  void addNestedChildrenSuffix(List<Block> list, @Nullable AlignmentProvider.Aligner aligner, boolean topLevel, List<ASTNode> children, int limit) {
     for (int i = 1; i < limit; i++) {
       ASTNode childNode = children.get(i);
       if (canBeCorrectBlock(childNode)) {
@@ -496,8 +513,13 @@ public class GroovyBlockGenerator implements GroovyElementTypes {
         Indent indent = topLevel || NESTED.contains(type) || type == mIDENT || TokenSets.DOTS.contains(type) ?
                         Indent.getContinuationWithoutFirstIndent() :
                         Indent.getNoneIndent();
-        Alignment alignmentToUse = TokenSets.DOTS.contains(type) ? alignment : myInnerAlignments.get(childNode.getPsi());
-        list.add(new GroovyBlock(childNode, alignmentToUse, indent, myWrap, mySettings, myGroovySettings, myInnerAlignments));
+
+
+        if (aligner != null && TokenSets.DOTS.contains(type)) {
+          aligner.append(childNode.getPsi());
+        }
+
+        list.add(new GroovyBlock(childNode, indent, myWrap, mySettings, myGroovySettings, myAlignmentProvider));
       }
     }
   }
index 6fd00921d65fb3a2b32a0a6dc2975cb684184e94..fe67d4f85fd153cd4d42fcdffb9aca59d8598b85 100644 (file)
 
 package org.jetbrains.plugins.groovy.formatter;
 
-import com.intellij.formatting.*;
+import com.intellij.formatting.Block;
+import com.intellij.formatting.FormattingModel;
+import com.intellij.formatting.FormattingModelBuilder;
+import com.intellij.formatting.Indent;
 import com.intellij.lang.ASTNode;
 import com.intellij.openapi.util.TextRange;
 import com.intellij.psi.PsiElement;
@@ -30,14 +33,12 @@ import com.intellij.psi.formatter.FormattingDocumentModelImpl;
 import com.intellij.psi.formatter.PsiBasedFormattingModel;
 import com.intellij.psi.impl.source.tree.TreeUtil;
 import com.intellij.psi.tree.IElementType;
-import com.intellij.util.containers.CollectionFactory;
 import org.jetbrains.annotations.NotNull;
 import org.jetbrains.annotations.Nullable;
 import org.jetbrains.plugins.groovy.GroovyFileType;
 import org.jetbrains.plugins.groovy.lang.lexer.GroovyTokenTypes;
 import org.jetbrains.plugins.groovy.lang.lexer.TokenSets;
 
-import java.util.Map;
 
 /**
  * @author ilyas
@@ -54,14 +55,13 @@ public class GroovyFormattingModelBuilder implements FormattingModelBuilder {
     CommonCodeStyleSettings groovySettings = settings.getCommonSettings(GroovyFileType.GROOVY_LANGUAGE);
     GroovyCodeStyleSettings customSettings = settings.getCustomSettings(GroovyCodeStyleSettings.class);
 
-    final Map<PsiElement, Alignment> innerAlignments = CollectionFactory.hashMap();
+    final AlignmentProvider alignments = new AlignmentProvider();
     if (customSettings.USE_FLYING_GEESE_BRACES) {
       element.accept(new PsiRecursiveElementVisitor() {
         @Override
         public void visitElement(PsiElement element) {
           if (GeeseUtil.isClosureRBrace(element)) {
-            final Alignment alignment = GeeseUtil.calculateRBraceAlignment(element, innerAlignments);
-            innerAlignments.put(element, alignment);
+            GeeseUtil.calculateRBraceAlignment(element, alignments);
           }
           else {
             super.visitElement(element);
@@ -69,8 +69,7 @@ public class GroovyFormattingModelBuilder implements FormattingModelBuilder {
         }
       });
     }
-    final GroovyBlock block =
-      new GroovyBlock(astNode, null, Indent.getAbsoluteNoneIndent(), null, groovySettings, customSettings, innerAlignments);
+    final GroovyBlock block = new GroovyBlock(astNode, Indent.getAbsoluteNoneIndent(), null, groovySettings, customSettings, alignments);
     return new GroovyFormattingModel(containingFile, block, FormattingDocumentModelImpl.createOn(containingFile));
   }
 
index 001814778e3a8c203a6f811121252b709381e246..b5d8a481de220d6cbfe6de0613a5d4bee828b6bb 100644 (file)
@@ -15,7 +15,6 @@
  */
 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;
@@ -27,7 +26,6 @@ import org.jetbrains.annotations.NotNull;
 
 import java.util.ArrayList;
 import java.util.List;
-import java.util.Map;
 
 /**
  * @author peter
@@ -39,15 +37,14 @@ public class MethodCallWithoutQualifierBlock extends GroovyBlock {
   private final PsiElement myElem;
 
   public MethodCallWithoutQualifierBlock(PsiElement nameElement,
-                                         Alignment alignment,
                                          Wrap wrap,
                                          CommonCodeStyleSettings settings,
                                          GroovyCodeStyleSettings groovySettings,
                                          boolean topLevel,
                                          List<ASTNode> children,
                                          PsiElement elem,
-                                         Map<PsiElement, Alignment> innerAlignments) {
-    super(nameElement.getNode(), alignment, Indent.getContinuationWithoutFirstIndent(), wrap, settings, groovySettings, innerAlignments);
+                                         AlignmentProvider alignmentProvider) {
+    super(nameElement.getNode(), Indent.getContinuationWithoutFirstIndent(), wrap, settings, groovySettings, alignmentProvider);
     myNameElement = nameElement;
     myTopLevel = topLevel;
     myChildren = children;
@@ -59,10 +56,9 @@ public class MethodCallWithoutQualifierBlock extends GroovyBlock {
   public List<Block> getSubBlocks() {
     if (mySubBlocks == null) {
       mySubBlocks = new ArrayList<Block>();
-      mySubBlocks.add(
-        new GroovyBlock(myNameElement.getNode(), myInnerAlignments.get(myNameElement), Indent.getContinuationWithoutFirstIndent(), myWrap,
-                        mySettings, myGroovySettings, myInnerAlignments));
-      new GroovyBlockGenerator(this).addNestedChildrenSuffix(mySubBlocks, myAlignment, myTopLevel, myChildren, myChildren.size());
+      final Indent indent = Indent.getContinuationWithoutFirstIndent();
+      mySubBlocks.add(new GroovyBlock(myNameElement.getNode(), indent, myWrap, mySettings, myGroovySettings, myAlignmentProvider));
+      new GroovyBlockGenerator(this).addNestedChildrenSuffix(mySubBlocks, null, myTopLevel, myChildren, myChildren.size());
     }
     return mySubBlocks;
   }
diff --git a/plugins/groovy/src/org/jetbrains/plugins/groovy/refactoring/javaToGrovyRename/RenameJavaFileToGroovyFileAction.java b/plugins/groovy/src/org/jetbrains/plugins/groovy/refactoring/javaToGrovyRename/RenameJavaFileToGroovyFileAction.java
deleted file mode 100644 (file)
index d94b4fd..0000000
+++ /dev/null
@@ -1,115 +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.refactoring.javaToGrovyRename;
-
-import com.intellij.lang.Language;
-import com.intellij.lang.StdLanguages;
-import com.intellij.openapi.actionSystem.AnAction;
-import com.intellij.openapi.actionSystem.AnActionEvent;
-import com.intellij.openapi.actionSystem.DataKeys;
-import com.intellij.openapi.actionSystem.Presentation;
-import com.intellij.openapi.application.AccessToken;
-import com.intellij.openapi.application.ApplicationManager;
-import com.intellij.openapi.application.WriteAction;
-import com.intellij.openapi.command.CommandProcessor;
-import com.intellij.openapi.fileTypes.StdFileTypes;
-import com.intellij.openapi.module.Module;
-import com.intellij.openapi.module.ModuleUtil;
-import com.intellij.openapi.project.DumbAware;
-import com.intellij.openapi.project.Project;
-import com.intellij.openapi.ui.Messages;
-import com.intellij.openapi.vfs.VirtualFile;
-import com.intellij.psi.PsiFile;
-import com.intellij.util.IncorrectOperationException;
-import org.jetbrains.plugins.groovy.GroovyFileType;
-import org.jetbrains.plugins.groovy.extensions.GroovyScriptType;
-import org.jetbrains.plugins.groovy.extensions.GroovyScriptTypeDetector;
-import org.jetbrains.plugins.groovy.lang.psi.GroovyFile;
-import org.jetbrains.plugins.groovy.util.LibrariesUtil;
-
-/**
- * @author ven
- */
-public class RenameJavaFileToGroovyFileAction extends AnAction implements DumbAware {
-  public void actionPerformed(final AnActionEvent e) {
-    final PsiFile file = e.getData(DataKeys.PSI_FILE);
-    assert isEnabled(file);
-    assert file != null;
-    VirtualFile virtualFile = file.getVirtualFile();
-    assert virtualFile != null;
-    String newExt = file.getLanguage() == StdLanguages.JAVA ? GroovyFileType.DEFAULT_EXTENSION : StdFileTypes.JAVA.getDefaultExtension();
-
-    final String newName = virtualFile.getNameWithoutExtension() + "." + newExt;
-    final Project project = e.getData(DataKeys.PROJECT);
-    CommandProcessor.getInstance().executeCommand(project, new Runnable() {
-      public void run() {
-        AccessToken accessToken = WriteAction.start();
-
-        try {
-          try {
-            file.setName(newName);
-          } catch (final IncorrectOperationException e1) {
-            ApplicationManager.getApplication().invokeLater(new Runnable() {
-              public void run() {
-                Messages.showErrorDialog(project, "Cannot rename java file" + e1.getMessage(), "Canot Rename");
-              }
-            });
-          }
-        }
-        finally {
-          accessToken.finish();
-        }
-      }
-    }, "Rename File", null);
-  }
-
-  public void update(AnActionEvent e) {
-    PsiFile file = e.getData(DataKeys.PSI_FILE);
-    Presentation presentation = e.getPresentation();
-    boolean enabled = isEnabled(file);
-    presentation.setEnabled(enabled);
-    presentation.setVisible(enabled);
-    if (enabled) {
-      assert file != null;
-      presentation.setText(file.getLanguage() == StdLanguages.JAVA ? "Rename To Groovy" : "Rename To Java");
-      presentation.setDescription(file.getLanguage() == StdLanguages.JAVA ? "Rename Java File to Groovy" : "Rename Groovy File to Java");
-    }
-  }
-
-  private static boolean isEnabled(PsiFile file) {
-    if (file == null) {
-      return false;
-    }
-
-    final Language language = file.getLanguage();
-    if (language == GroovyFileType.GROOVY_LANGUAGE) {
-      if (((GroovyFile)file).isScript()) {
-        final GroovyScriptType type = GroovyScriptTypeDetector.getScriptType((GroovyFile)file);
-        if (type != GroovyScriptTypeDetector.DEFAULT_TYPE) {
-          return false;
-        }
-      }
-      return true;
-    }
-
-    if (!(language == StdLanguages.JAVA)) {
-      return false;
-    }
-
-    final Module module = ModuleUtil.findModuleForPsiElement(file);
-    return module != null && LibrariesUtil.hasGroovySdk(module);
-  }
-}
index 1256e756a2fb043f175d9598c425560706420e12..2c91e3c8268626f4a87b1e3d3ca7e47559bf3461 100644 (file)
@@ -231,6 +231,7 @@ public class FormatterTest extends GroovyFormatterTestCase {
   public void testGeese5() {doGeeseTest();}
   public void testGeese6() {doGeeseTest();}
   public void testGeese7() {doGeeseTest();}
+  public void testGeese8() {doGeeseTest();}
 
   private void doGeeseTest() {
     GroovyCodeStyleSettings customSettings = myTempSettings.getCustomSettings(GroovyCodeStyleSettings.class);
diff --git a/plugins/groovy/testdata/groovy/formatter/geese8.test b/plugins/groovy/testdata/groovy/formatter/geese8.test
new file mode 100644 (file)
index 0000000..596d14a
--- /dev/null
@@ -0,0 +1,17 @@
+setupModel(
+    intellijProject {
+      module {
+        faq.
+        dependencies {
+          lib(name: "lib1")
+}}}
+)
+-----
+setupModel(
+    intellijProject {
+      module {
+        faq.
+            dependencies {
+              lib(name: "lib1")
+    } }     }
+)
\ No newline at end of file
index 97228f8579793483764d4be0d510ee7ef712f2c0..9b4672341a857d57d8b26ece30737eb574f931f2 100644 (file)
@@ -34,6 +34,8 @@ import com.intellij.uiDesigner.quickFixes.QuickFix;
 import com.intellij.uiDesigner.radComponents.RadComponent;
 import org.jetbrains.annotations.NotNull;
 
+import java.util.ArrayList;
+import java.util.List;
 import javax.swing.*;
 
 /**
@@ -58,6 +60,7 @@ public class NoLabelForInspection extends BaseFormInspection {
       }
       final Ref<Boolean> found = new Ref<Boolean>(Boolean.FALSE);
       final Ref<RadComponent> candidateLabel = new Ref<RadComponent>();
+      final List<RadComponent> allLabels = new ArrayList<RadComponent>();
       FormEditingUtil.iterate(root, new FormEditingUtil.ComponentVisitor() {
         public boolean visit(final IComponent c2) {
           if (FormInspectionUtil.isComponentClass(module, c2, JLabel.class)) {
@@ -70,6 +73,7 @@ public class NoLabelForInspection extends BaseFormInspection {
                      (prop == null || StringUtil.isEmpty((String)prop.getPropertyValue(c2)))) {
               RadComponent radComponent = (RadComponent) component;
               final RadComponent radComponent2 = ((RadComponent)c2);
+              allLabels.add(radComponent2);
               if (radComponent.getParent() == radComponent2.getParent() && radComponent.getParent().getLayoutManager().isGrid()) {
                 GridConstraints gc1 = radComponent.getConstraints();
                 GridConstraints gc2 = radComponent2.getConstraints();
@@ -86,12 +90,20 @@ public class NoLabelForInspection extends BaseFormInspection {
         }
       });
       if (!found.get().booleanValue()) {
-        collector.addError(getID(), component, null, UIDesignerBundle.message("inspection.no.label.for.error"),
-                           candidateLabel.isNull() ? null : new EditorQuickFixProvider() {
-                             public QuickFix createQuickFix(GuiEditor editor, RadComponent component) {
-                               return new MyQuickFix(editor, component, candidateLabel.get());
-                             }
-                           });
+        if (!candidateLabel.isNull()) {
+          allLabels.clear();
+          allLabels.add(candidateLabel.get());
+        }
+        EditorQuickFixProvider[] quickFixProviders = new EditorQuickFixProvider[allLabels.size()];
+        for (int i = 0; i < quickFixProviders.length; i++) {
+          final RadComponent label = allLabels.get(i);
+          quickFixProviders[i] = new EditorQuickFixProvider() {
+            public QuickFix createQuickFix(GuiEditor editor, RadComponent component) {
+              return new MyQuickFix(editor, component, label);
+            }
+          };
+        }
+        collector.addError(getID(), component, null, UIDesignerBundle.message("inspection.no.label.for.error"), quickFixProviders);
       }
     }
   }