Merge remote-tracking branch 'origin/master'
authorAlexander Lobas <Alexander.Lobas@jetbrains.com>
Fri, 27 Jan 2012 12:23:45 +0000 (16:23 +0400)
committerAlexander Lobas <Alexander.Lobas@jetbrains.com>
Fri, 27 Jan 2012 12:23:45 +0000 (16:23 +0400)
35 files changed:
jps/jps-builders/src/org/jetbrains/jps/incremental/BuilderRegistry.java
jps/jps-builders/src/org/jetbrains/jps/incremental/resources/ResourcesBuilder.java [moved from jps/jps-builders/src/org/jetbrains/jps/incremental/resourses/ResourcesBuilder.java with 98% similarity]
platform/platform-resources-en/src/messages/ExecutionBundle.properties
platform/smRunner/src/com/intellij/execution/testframework/sm/runner/SMTRunnerNodeDescriptor.java
platform/smRunner/src/com/intellij/execution/testframework/sm/runner/SMTRunnerTreeBuilder.java
platform/smRunner/src/com/intellij/execution/testframework/sm/runner/ui/SMTestRunnerResultsForm.java
platform/testRunner/src/com/intellij/execution/testframework/TestConsoleProperties.java
platform/testRunner/src/com/intellij/execution/testframework/TestFrameworkRunningModel.java
platform/testRunner/src/com/intellij/execution/testframework/ToolbarPanel.java
platform/testRunner/src/com/intellij/execution/testframework/ui/AbstractTestTreeBuilder.java
platform/testRunner/src/com/intellij/execution/testframework/ui/BaseTestProxyNodeDescriptor.java [new file with mode: 0644]
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/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/test/org/jetbrains/plugins/groovy/lang/formatter/FormatterTest.java
plugins/groovy/testdata/groovy/formatter/geese8.test [new file with mode: 0644]
plugins/junit/src/com/intellij/execution/junit2/ui/model/TestProxyDescriptor.java
plugins/junit/src/com/intellij/execution/junit2/ui/model/TestTreeBuilder.java
plugins/testng/src/com/theoryinpractice/testng/model/TestNodeDescriptor.java
plugins/testng/src/com/theoryinpractice/testng/model/TestTreeBuilder.java
plugins/testng/src/com/theoryinpractice/testng/ui/TestNGResults.java

index ee20e5a5d8e392baeba208c4d67fccaf8bdc369f..51a128ddc6ff0670bcb8a7e7d0c113dcba979932 100644 (file)
@@ -2,7 +2,7 @@ package org.jetbrains.jps.incremental;
 
 import org.jetbrains.jps.incremental.groovy.GroovyBuilder;
 import org.jetbrains.jps.incremental.java.JavaBuilder;
-import org.jetbrains.jps.incremental.resourses.ResourcesBuilder;
+import org.jetbrains.jps.incremental.resources.ResourcesBuilder;
 
 import java.util.*;
 import java.util.concurrent.ExecutorService;
similarity index 98%
rename from jps/jps-builders/src/org/jetbrains/jps/incremental/resourses/ResourcesBuilder.java
rename to jps/jps-builders/src/org/jetbrains/jps/incremental/resources/ResourcesBuilder.java
index 7aaeb006897258ed6a9ff2fb1dc265c9ff0862d1..a318f8ef4dd7ea1aba6de8b59dda0521d1f4693d 100644 (file)
@@ -1,4 +1,4 @@
-package org.jetbrains.jps.incremental.resourses;
+package org.jetbrains.jps.incremental.resources;
 
 import com.intellij.openapi.diagnostic.Logger;
 import com.intellij.openapi.util.io.FileUtil;
index 3be53cf875b1d7c67ca9431400ed669ead5b4d11..0181271196aa3f54dd6701c34ca788f789e73c01 100644 (file)
@@ -133,6 +133,8 @@ tests.passed.with.warnings.message=Tests passed (with warnings)
 junit.run.hide.passed.action.name=Hide Passed
 junit.run.hide.passed.action.description=Hide passed tests
 junit.runing.info.track.test.action.name=Track Running Test
+junit.runing.info.sort.alphabetically.action.name=Sort Alphabetically
+junit.runing.info.sort.alphabetically.action.description=Sort tests or suites alphabetically
 junit.runing.info.track.test.action.description=Select currently running test in tree
 junit.runing.info.collapse.test.action.name=Collapse all test suites
 junit.runing.info.expand.test.action.name=Expand all test suites
index a5afce41398c597bec5f6851c697f171adfa557f..eccd92344e1f4174d6b3a6ee4fea35ab3c4b2181 100644 (file)
  */
 package com.intellij.execution.testframework.sm.runner;
 
+import com.intellij.execution.testframework.ui.BaseTestProxyNodeDescriptor;
 import com.intellij.ide.util.treeView.NodeDescriptor;
 import com.intellij.openapi.project.Project;
 
 /**
  * @author: Roman Chernyatchik
  */
-public class SMTRunnerNodeDescriptor extends NodeDescriptor<SMTestProxy>
-{
-  private final SMTestProxy myElement;
-
+public class SMTRunnerNodeDescriptor extends BaseTestProxyNodeDescriptor<SMTestProxy> {
   public SMTRunnerNodeDescriptor(final Project project,
-                                final SMTestProxy element,
-                                final NodeDescriptor<SMTestProxy> parentDesc) {
-    super(project, parentDesc);
-    myElement = element;
-    myName = element.getName();
-  }
-
-  @Override
-  public boolean update() {
-    return false;
-  }
-
-  @Override
-  public SMTestProxy getElement() {
-    return myElement;
-  }
-
-  public boolean expandOnDoubleClick() {
-    return !myElement.isLeaf();
-  }
-
-  @Override
-  public String toString() {
-    return myName;
+                                 final SMTestProxy testProxy,
+                                 final NodeDescriptor<SMTestProxy> parentDesc) {
+    super(project, testProxy, parentDesc);
   }
 }
 
index 95280b7fdd7caafe0dae7ba4e69a9bc056419c44..e4d9ff5c9c08ddabc6de5b031ba579901996ef8a 100644 (file)
 package com.intellij.execution.testframework.sm.runner;
 
 import com.intellij.execution.testframework.ui.AbstractTestTreeBuilder;
+import com.intellij.ide.util.treeView.AbstractTreeStructure;
+import com.intellij.ide.util.treeView.AbstractTreeUpdater;
 import com.intellij.ide.util.treeView.IndexComparator;
 import com.intellij.ide.util.treeView.NodeDescriptor;
-import com.intellij.ide.util.treeView.AbstractTreeUpdater;
-import com.intellij.ide.util.treeView.AbstractTreeStructure;
-import com.intellij.openapi.progress.ProgressIndicator;
-import com.intellij.openapi.progress.util.StatusBarProgress;
-import org.jetbrains.annotations.NotNull;
 
 import javax.swing.*;
 import javax.swing.tree.DefaultMutableTreeNode;
@@ -43,7 +40,7 @@ public class SMTRunnerTreeBuilder extends AbstractTestTreeBuilder {
   }
 
   public SMTRunnerTreeStructure getSMRunnerTreeStructure() {
-    return ((SMTRunnerTreeStructure)getTreeStructure()) ;
+    return ((SMTRunnerTreeStructure)getTreeStructure());
   }
 
   public void updateTestsSubtree(final SMTestProxy parentTestProxy) {
@@ -64,32 +61,16 @@ public class SMTRunnerTreeBuilder extends AbstractTestTreeBuilder {
     }
 
     if (((SMTestProxy)nodeElement).getParent() == rootElement
-        && ((SMTestProxy)rootElement).getChildren().size() == 1){
+        && ((SMTestProxy)rootElement).getChildren().size() == 1) {
       return true;
     }
     return false;
   }
 
-  protected boolean isAlwaysShowPlus(final NodeDescriptor descriptor) {
-    //TODO[romeo] move to base class
-    return false;
-  }
-
-  @NotNull
-  protected ProgressIndicator createProgressIndicator() {
-    //TODO[romeo] maybe move to base class
-    return new StatusBarProgress();
-  }
-
-  protected boolean isSmartExpand() {
-    //TODO[romeo] move to base class
-    return false;
-  }
-
   /**
    * for java unit tests
    */
   public void performUpdate() {
     getUpdater().performUpdate();
-  }  
+  }
 }
index 34f025b606acc6a91e668a75070908c8ad6241c0..c2b5e04dc23c5bb15da952be06ff6a225112927d 100644 (file)
@@ -54,7 +54,8 @@ import java.util.Set;
 /**
  * @author: Roman Chernyatchik
  */
-public class SMTestRunnerResultsForm extends TestResultsPanel implements TestFrameworkRunningModel, TestResultsViewer, SMTRunnerEventsListener {
+public class SMTestRunnerResultsForm extends TestResultsPanel
+  implements TestFrameworkRunningModel, TestResultsViewer, SMTRunnerEventsListener {
   @NonNls private static final String DEFAULT_SM_RUNNER_SPLITTER_PROPERTY = "SMTestRunner.Splitter.Proportion";
 
   public static final Color DARK_YELLOW = Color.YELLOW.darker();
@@ -131,12 +132,12 @@ public class SMTestRunnerResultsForm extends TestResultsPanel implements TestFra
 
     final KeyStroke shiftEnterKey = KeyStroke.getKeyStroke(KeyEvent.VK_ENTER, InputEvent.SHIFT_MASK);
     SMRunnerUtil.registerAsAction(shiftEnterKey, "show-statistics-for-test-proxy",
-                            new Runnable() {
-                              public void run() {
-                                showStatisticsForSelectedProxy();
-                              }
-                            },
-                            myTreeView);
+                                  new Runnable() {
+                                    public void run() {
+                                      showStatisticsForSelectedProxy();
+                                    }
+                                  },
+                                  myTreeView);
   }
 
   protected ToolbarPanel createToolbarPanel() {
@@ -161,7 +162,9 @@ public class SMTestRunnerResultsForm extends TestResultsPanel implements TestFra
 
     final SMTRunnerTreeStructure structure = new SMTRunnerTreeStructure(myProject, myTestsRootNode);
     myTreeBuilder = new SMTRunnerTreeBuilder(myTreeView, structure);
+    myTreeBuilder.setTestsComparator(TestConsoleProperties.SORT_ALPHABETICALLY.value(myProperties));
     Disposer.register(this, myTreeBuilder);
+
     myAnimator = new MyAnimator(this, myTreeBuilder);
 
     //TODO always hide root node
@@ -192,6 +195,7 @@ public class SMTestRunnerResultsForm extends TestResultsPanel implements TestFra
 
   /**
    * Is used for navigation from tree view to other UI components
+   *
    * @param handler
    */
   public void setShowStatisticForProxyHandler(final PropagateSelectionHandler handler) {
@@ -200,8 +204,9 @@ public class SMTestRunnerResultsForm extends TestResultsPanel implements TestFra
 
   /**
    * Returns root node, fake parent suite for all tests and suites
-   * @return
+   *
    * @param testsRoot
+   * @return
    */
   public void onTestingStarted(@NotNull SMTestProxy.SMRootTestProxy testsRoot) {
     myAnimator.setCurrentTestCase(myTestsRootNode);
@@ -333,6 +338,11 @@ public class SMTestRunnerResultsForm extends TestResultsPanel implements TestFra
     return myTreeView;
   }
 
+  @Override
+  public SMTRunnerTreeBuilder getTreeBuilder() {
+    return myTreeBuilder;
+  }
+
   public boolean hasTestSuites() {
     return getRoot().getChildren().size() > 0;
   }
@@ -345,10 +355,11 @@ public class SMTestRunnerResultsForm extends TestResultsPanel implements TestFra
   /**
    * Manual test proxy selection in tests tree. E.g. do select root node on
    * testing started or do select current node if TRACK_RUNNING_TEST is enabled
-   *
-   *
+   * <p/>
+   * <p/>
    * Will select proxy in Event Dispatch Thread. Invocation of this
    * method may be not in event dispatch thread
+   *
    * @param testProxy Test or suite
    */
   public void selectAndNotify(@Nullable final AbstractTestProxy testProxy) {
@@ -469,7 +480,8 @@ public class SMTestRunnerResultsForm extends TestResultsPanel implements TestFra
   private void updateStatusLabel(final boolean testingFinished) {
     if (myTestsFailuresCount > 0) {
       myStatusLine.setStatusColor(ColorProgressBar.RED);
-    } else if (myContainsIgnoredTests) {
+    }
+    else if (myContainsIgnoredTests) {
       myStatusLine.setStatusColor(DARK_YELLOW);
     }
 
@@ -477,7 +489,7 @@ public class SMTestRunnerResultsForm extends TestResultsPanel implements TestFra
       if (myTestsTotal == 0) {
         myStatusLine.setStatusColor(myTestsRootNode.wasLaunched() || !myTestsRootNode.isTestsReporterAttached()
                                     ? Color.LIGHT_GRAY
-                                    : ColorProgressBar.RED );
+                                    : ColorProgressBar.RED);
       }
       // else color will be according failed/passed tests
     }
@@ -486,9 +498,9 @@ public class SMTestRunnerResultsForm extends TestResultsPanel implements TestFra
     // initializing will be "launchedAndFinished"
     final boolean launchedAndFinished = myTestsRootNode.wasLaunched() && !myTestsRootNode.isInProgress();
     myStatusLine.setText(TestsPresentationUtil.getProgressStatus_Text(myStartTime, myEndTime,
-                                                                       myTestsTotal, myTestsCurrentCount,
-                                                                       myTestsFailuresCount, myMentionedCategories,
-                                                                       launchedAndFinished));
+                                                                      myTestsTotal, myTestsCurrentCount,
+                                                                      myTestsFailuresCount, myMentionedCategories,
+                                                                      launchedAndFinished));
   }
 
   /**
@@ -501,12 +513,13 @@ public class SMTestRunnerResultsForm extends TestResultsPanel implements TestFra
   /**
    * On event change selection and probably requests focus. Is used when we want
    * navigate from other component to this
+   *
    * @return Listener
    */
   public PropagateSelectionHandler createSelectMeListener() {
     return new PropagateSelectionHandler() {
       public void handlePropagateSelectionRequest(@Nullable final SMTestProxy selectedTestProxy, @NotNull final Object sender,
-                                    final boolean requestFocus) {
+                                                  final boolean requestFocus) {
         SMRunnerUtil.addToInvokeLater(new Runnable() {
           public void run() {
             selectWithoutNotify(selectedTestProxy);
@@ -543,7 +556,8 @@ public class SMTestRunnerResultsForm extends TestResultsPanel implements TestFra
     if (!isModeConsistent(isCustomMessage)) return;
 
     // for mixed tests results : mention category only if it contained tests
-    myMentionedCategories.add(myCurrentCustomProgressCategory != null ? myCurrentCustomProgressCategory : TestsPresentationUtil.DEFAULT_TESTS_CATEGORY);
+    myMentionedCategories
+      .add(myCurrentCustomProgressCategory != null ? myCurrentCustomProgressCategory : TestsPresentationUtil.DEFAULT_TESTS_CATEGORY);
 
     // Counters
     myTestsCurrentCount++;
@@ -558,7 +572,8 @@ public class SMTestRunnerResultsForm extends TestResultsPanel implements TestFra
     if (myTestsTotal != 0) {
       // if total is set
       myStatusLine.setFraction((double)myTestsCurrentCount / myTestsTotal);
-    } else {
+    }
+    else {
       // if at least one test was launcher than just set progress in the middle to show user that tests are running
       myStatusLine.setFraction(myTestsCurrentCount > 1 ? 0.5 : 0); // > 1 because count already ++
     }
@@ -583,34 +598,34 @@ public class SMTestRunnerResultsForm extends TestResultsPanel implements TestFra
   }
 
 
- private static class MyFocusTraversalPolicy extends FocusTraversalPolicy {
-   final List<Component> myComponents;
 private static class MyFocusTraversalPolicy extends FocusTraversalPolicy {
+    final List<Component> myComponents;
 
-   private MyFocusTraversalPolicy(final List<Component> components) {
-     myComponents = components;
-   }
+    private MyFocusTraversalPolicy(final List<Component> components) {
+      myComponents = components;
+    }
 
-   public Component getComponentAfter(final Container container, final Component component) {
-     return myComponents.get((myComponents.indexOf(component) + 1) % myComponents.size());
-   }
+    public Component getComponentAfter(final Container container, final Component component) {
+      return myComponents.get((myComponents.indexOf(component) + 1) % myComponents.size());
+    }
 
-   public Component getComponentBefore(final Container container, final Component component) {
-     final int prevIndex = myComponents.indexOf(component) - 1;
-     final int normalizedIndex = prevIndex < 0 ? myComponents.size() - 1 : prevIndex;
+    public Component getComponentBefore(final Container container, final Component component) {
+      final int prevIndex = myComponents.indexOf(component) - 1;
+      final int normalizedIndex = prevIndex < 0 ? myComponents.size() - 1 : prevIndex;
 
-     return myComponents.get(normalizedIndex);
-   }
+      return myComponents.get(normalizedIndex);
+    }
 
-   public Component getFirstComponent(final Container container) {
-     return myComponents.get(0);
-   }
+    public Component getFirstComponent(final Container container) {
+      return myComponents.get(0);
+    }
 
-   public Component getLastComponent(final Container container) {
-     return myComponents.get(myComponents.size() - 1);
-   }
+    public Component getLastComponent(final Container container) {
+      return myComponents.get(myComponents.size() - 1);
+    }
 
-   public Component getDefaultComponent(final Container container) {
-     return getFirstComponent(container);
-   }
+    public Component getDefaultComponent(final Container container) {
+      return getFirstComponent(container);
+    }
   }
 }
index 57332b78d4769d1524da08b6bc5f4adde54babce..fa670d6c430896ea9ce8daee84507dc7d50075ba 100644 (file)
@@ -41,6 +41,7 @@ import java.util.HashMap;
 
 public abstract class TestConsoleProperties extends StoringPropertyContainer implements Disposable {
   public static final BooleanProperty SCROLL_TO_STACK_TRACE = new BooleanProperty("scrollToStackTrace", false);
+  public static final BooleanProperty SORT_ALPHABETICALLY = new BooleanProperty("sortTestsAlphabetically", false);
   public static final BooleanProperty SELECT_FIRST_DEFECT = new BooleanProperty("selectFirtsDefect", false);
   public static final BooleanProperty TRACK_RUNNING_TEST = new BooleanProperty("trackRunningTest", true);
   public static final BooleanProperty HIDE_PASSED_TESTS = new BooleanProperty("hidePassedTests", true);
@@ -69,7 +70,7 @@ public abstract class TestConsoleProperties extends StoringPropertyContainer imp
   public GlobalSearchScope getScope() {
     Module[] modules = getConfiguration().getModules();
     if (modules.length == 0) return GlobalSearchScope.allScope(myProject);
-   
+
     GlobalSearchScope scope = GlobalSearchScope.EMPTY_SCOPE;
     for (Module each : modules) {
       scope = scope.uniteWith(GlobalSearchScope.moduleRuntimeScope(each, true));
@@ -135,12 +136,12 @@ public abstract class TestConsoleProperties extends StoringPropertyContainer imp
   /**
    * Allows to make console editable and disable/enable input sending in process stdin stream.
    * Normally tests shouldn't ask anything in stdin so console is view only by default.
-   *
+   * <p/>
    * NB1: Process input support feature isn't fully implemented. Input text will be lost after
    * switching to any other test/suite in tests results view. It's highly not recommended to change
    * default behaviour. Please do it only in critical cases and only if you are sure that you need this feature.
-   *
-   *
+   * <p/>
+   * <p/>
    * NB2: If you are using Service Messages based test runner please ensure that before each service message
    * (e.g. #teamcity[...]) you always send "\n" to the output stream.
    *
index a018a613fc41f766dd669cdc669a930c8702aa21..9080d7f466fc7c426cdefd3b7268a4a75b299699 100644 (file)
  */
 package com.intellij.execution.testframework;
 
+import com.intellij.execution.testframework.ui.AbstractTestTreeBuilder;
 import com.intellij.openapi.Disposable;
 
 public interface TestFrameworkRunningModel extends Disposable {
   TestConsoleProperties getProperties();
 
-  void setFilter(final Filter filter);
+  void setFilter(Filter filter);
 
   boolean isRunning();
 
   TestTreeView getTreeView();
 
+  AbstractTestTreeBuilder getTreeBuilder();
+
   boolean hasTestSuites();
 
   AbstractTestProxy getRoot();
 
-  void selectAndNotify(final AbstractTestProxy testProxy);
+  void selectAndNotify(AbstractTestProxy testProxy);
 }
\ No newline at end of file
index c8672fca7366a43ee5e3d5b45b5e83ec33ccb3af..9538c13bd8918418dac20cb0bee33d7b3ba4ffa4 100644 (file)
@@ -28,6 +28,7 @@ import com.intellij.execution.testframework.actions.ShowStatisticsAction;
 import com.intellij.execution.testframework.actions.TestFrameworkActions;
 import com.intellij.execution.testframework.actions.TestTreeExpander;
 import com.intellij.execution.testframework.export.ExportTestResultsAction;
+import com.intellij.execution.testframework.ui.AbstractTestTreeBuilder;
 import com.intellij.ide.CommonActionsManager;
 import com.intellij.ide.OccurenceNavigator;
 import com.intellij.openapi.Disposable;
@@ -54,19 +55,25 @@ public class ToolbarPanel extends JPanel implements OccurenceNavigator, Disposab
   public ToolbarPanel(final TestConsoleProperties properties,
                       final RunnerSettings runnerSettings,
                       final ConfigurationPerRunnerSettings configurationSettings, JComponent parent) {
-    super (new BorderLayout());
+    super(new BorderLayout());
     final DefaultActionGroup actionGroup = new DefaultActionGroup(null, false);
     actionGroup.addAction(new ToggleBooleanProperty(ExecutionBundle.message("junit.run.hide.passed.action.name"),
                                                     ExecutionBundle.message("junit.run.hide.passed.action.description"),
                                                     TestsUIUtil.loadIcon("hidePassed"),
                                                     properties, TestConsoleProperties.HIDE_PASSED_TESTS));
     actionGroup.addSeparator();
-    
+
     actionGroup.addAction(new ToggleBooleanProperty(ExecutionBundle.message("junit.runing.info.track.test.action.name"),
                                                     ExecutionBundle.message("junit.runing.info.track.test.action.description"),
                                                     TestsUIUtil.loadIcon("trackTests"),
                                                     properties, TestConsoleProperties.TRACK_RUNNING_TEST)).setAsSecondary(true);
 
+    actionGroup.addAction(new ToggleBooleanProperty(ExecutionBundle.message("junit.runing.info.sort.alphabetically.action.name"),
+                                                    ExecutionBundle.message("junit.runing.info.sort.alphabetically.action.description"),
+                                                    IconLoader.getIcon("/objectBrowser/sorted.png"),
+                                                    properties, TestConsoleProperties.SORT_ALPHABETICALLY));
+    actionGroup.addSeparator();
+
     AnAction action = CommonActionsManager.getInstance().createCollapseAllAction(myTreeExpander, parent);
     action.getTemplatePresentation().setDescription(ExecutionBundle.message("junit.runing.info.collapse.test.action.name"));
     actionGroup.add(action);
@@ -92,7 +99,8 @@ public class ToolbarPanel extends JPanel implements OccurenceNavigator, Disposab
     myScrollToSource = new ScrollToTestSourceAction(properties);
     actionGroup.addAction(myScrollToSource).setAsSecondary(true);
     actionGroup.addAction(new ToggleBooleanProperty(ExecutionBundle.message("junit.runing.info.open.source.at.exception.action.name"),
-                                                    ExecutionBundle.message("junit.runing.info.open.source.at.exception.action.description"),
+                                                    ExecutionBundle
+                                                      .message("junit.runing.info.open.source.at.exception.action.description"),
                                                     IconLoader.getIcon("/runConfigurations/sourceAtException.png"),
                                                     properties, TestConsoleProperties.OPEN_FAILURE_LINE)).setAsSecondary(true);
 
@@ -110,8 +118,8 @@ public class ToolbarPanel extends JPanel implements OccurenceNavigator, Disposab
     appendAdditionalActions(actionGroup, properties, runnerSettings, configurationSettings, parent);
 
     add(ActionManager.getInstance().
-        createActionToolbar(ActionPlaces.TESTTREE_VIEW_TOOLBAR, actionGroup, true).
-        getComponent(), BorderLayout.CENTER);
+      createActionToolbar(ActionPlaces.TESTTREE_VIEW_TOOLBAR, actionGroup, true).
+      getComponent(), BorderLayout.CENTER);
   }
 
   protected void appendAdditionalActions(DefaultActionGroup actionGroup, TestConsoleProperties properties, RunnerSettings runnerSettings,
@@ -128,6 +136,15 @@ public class ToolbarPanel extends JPanel implements OccurenceNavigator, Disposab
     for (ToggleModelAction action : myActions) {
       action.setModel(model);
     }
+    TestFrameworkActions.addPropertyListener(TestConsoleProperties.SORT_ALPHABETICALLY, new TestFrameworkPropertyListener<Boolean>() {
+      @Override
+      public void onChanged(Boolean value) {
+        final AbstractTestTreeBuilder builder = model.getTreeBuilder();
+        if (builder != null) {
+          builder.setTestsComparator(value);
+        }
+      }
+    }, model, true);
   }
 
   public boolean hasNextOccurence() {
@@ -158,5 +175,4 @@ public class ToolbarPanel extends JPanel implements OccurenceNavigator, Disposab
     myScrollToSource.setModel(null);
     myExportAction.setModel(null);
   }
-
 }
index 94a41caadb329b802cb7d1d44b117ea53f9f6fba..4db467ae7c7f72d7772cac1265177fd352ed57c1 100644 (file)
 package com.intellij.execution.testframework.ui;
 
 import com.intellij.execution.testframework.AbstractTestProxy;
-import com.intellij.ide.util.treeView.AbstractTreeBuilder;
-import com.intellij.ide.util.treeView.AbstractTreeStructure;
-import com.intellij.ide.util.treeView.IndexComparator;
+import com.intellij.ide.util.treeView.*;
+import com.intellij.openapi.progress.ProgressIndicator;
+import com.intellij.openapi.progress.util.StatusBarProgress;
+import org.jetbrains.annotations.NotNull;
 
 import javax.swing.*;
 import javax.swing.tree.DefaultMutableTreeNode;
@@ -51,4 +52,22 @@ public abstract class AbstractTestTreeBuilder extends AbstractTreeBuilder {
     }
     while (current != null);
   }
+
+  protected boolean isAlwaysShowPlus(final NodeDescriptor descriptor) {
+    return false;
+  }
+
+  @NotNull
+  protected ProgressIndicator createProgressIndicator() {
+    return new StatusBarProgress();
+  }
+
+  protected boolean isSmartExpand() {
+    return false;
+  }
+
+  public void setTestsComparator(boolean sortAlphabetically) {
+    setNodeDescriptorComparator(sortAlphabetically ? AlphaComparator.INSTANCE : null);
+    queueUpdate();
+  }
 }
diff --git a/platform/testRunner/src/com/intellij/execution/testframework/ui/BaseTestProxyNodeDescriptor.java b/platform/testRunner/src/com/intellij/execution/testframework/ui/BaseTestProxyNodeDescriptor.java
new file mode 100644 (file)
index 0000000..80c979a
--- /dev/null
@@ -0,0 +1,65 @@
+/*
+ * 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.execution.testframework.ui;
+
+import com.intellij.execution.testframework.AbstractTestProxy;
+import com.intellij.ide.util.treeView.NodeDescriptor;
+import com.intellij.openapi.project.Project;
+import org.jetbrains.annotations.NotNull;
+import org.jetbrains.annotations.Nullable;
+
+/**
+ * @author Roman.Chernyatchik
+ */
+public class BaseTestProxyNodeDescriptor<T extends AbstractTestProxy> extends NodeDescriptor<T> {
+  @NotNull private final T myTestProxy;
+
+  public BaseTestProxyNodeDescriptor(@Nullable final Project project,
+                                     @NotNull final T testProxy,
+                                     @Nullable final NodeDescriptor parentDescriptor) {
+    super(project, parentDescriptor);
+    myTestProxy = testProxy;
+    myName = testProxy.getName();
+  }
+
+  @Override
+  public int getWeight() {
+    return myTestProxy.isLeaf() ? 10 : 5;
+  }
+
+  public String getName() {
+    return myTestProxy.getName();
+  }
+
+  public boolean expandOnDoubleClick() {
+    return !getElement().isLeaf();
+  }
+
+  @Override
+  public boolean update() {
+    return false;
+  }
+
+  @Override
+  public T getElement() {
+    return myTestProxy;
+  }
+
+  @Override
+  public String toString() {
+    return myName;
+  }
+}
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
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;
   }
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 30fcb1f92321a642a74e7ef2aeb846b668a154d2..d5ef71bdeed5005bae721e5715129738f37b3774 100644 (file)
 package com.intellij.execution.junit2.ui.model;
 
 import com.intellij.execution.junit2.TestProxy;
+import com.intellij.execution.testframework.ui.BaseTestProxyNodeDescriptor;
 import com.intellij.ide.util.treeView.NodeDescriptor;
 import com.intellij.openapi.diagnostic.Logger;
 import com.intellij.openapi.project.Project;
 
-class TestProxyDescriptor extends NodeDescriptor {
+class TestProxyDescriptor extends BaseTestProxyNodeDescriptor<TestProxy> {
   private static final Logger LOG = Logger.getInstance("#com.intellij.execution.junit2.ui.model.TestProxyDescriptor");
   private static final int STATE_UP_TO_DATE = 0;
   private static final int STATE_OUT_OF_DATE = 1;
   private static final int STATE_UNKNOWN = 2;
 
-  private final TestProxy myTest;
   private int myTimestamp = -1;
   private int myLastChildCount = -1;
   //private int myNeedsUpdate = STATE_UNKNOWN;
   private int myLastMagnitude = -1;
 
   public TestProxyDescriptor(final Project project, final NodeDescriptor parentDescriptor, final TestProxy test) {
-    super(project, parentDescriptor);
-    myTest = test;
-    myTimestamp = myTest.getStateTimestamp();
-    myLastChildCount = myTest.getChildCount();
+    super(project, test, parentDescriptor);
+    myTimestamp = test.getStateTimestamp();
+    myLastChildCount = test.getChildCount();
     myName = test.toString();
   }
 
   public boolean update() {
-    boolean needsUpdate = checkNeedsUpdate();
-    myTimestamp = myTest.getStateTimestamp();
-    myLastChildCount = myTest.getChildCount();
+    final TestProxy test = getElement();
+
+    boolean needsUpdate = checkNeedsUpdate(test);
+    myTimestamp = test.getStateTimestamp();
+    myLastChildCount = test.getChildCount();
     return needsUpdate;
   }
 
-  private boolean checkNeedsUpdate() {
+  private boolean checkNeedsUpdate(TestProxy test) {
+
     int needsUpdate = STATE_UP_TO_DATE;
-    if (myTest.getChildCount() != myLastChildCount) {
+    if (test.getChildCount() != myLastChildCount) {
       needsUpdate = STATE_OUT_OF_DATE;
     }
-    else if (myTest.getStateTimestamp() != myTimestamp) needsUpdate = STATE_UNKNOWN;
+    else if (test.getStateTimestamp() != myTimestamp) needsUpdate = STATE_UNKNOWN;
     if (needsUpdate == STATE_UNKNOWN) {
-      final int magnitude = myTest.getState().getMagnitude();
+      final int magnitude = test.getState().getMagnitude();
       needsUpdate = magnitude == myLastMagnitude ? STATE_UP_TO_DATE : STATE_OUT_OF_DATE;
       myLastMagnitude = magnitude;
     }
@@ -66,8 +68,4 @@ class TestProxyDescriptor extends NodeDescriptor {
     LOG.error(String.valueOf(needsUpdate));
     return true;
   }
-
-  public Object getElement() {
-    return myTest;
-  }
 }
index f26d6aa0a1cf277cb73efe55da2126aabbd03f03..e51fafe2e1e3df02d288b854f5adcebe87b420cf 100644 (file)
@@ -16,8 +16,8 @@
 
 package com.intellij.execution.junit2.ui.model;
 
-import com.intellij.execution.junit2.events.TestEvent;
 import com.intellij.execution.junit2.TestProxy;
+import com.intellij.execution.junit2.events.TestEvent;
 import com.intellij.execution.junit2.ui.properties.JUnitConsoleProperties;
 import com.intellij.execution.testframework.AbstractTestProxy;
 import com.intellij.execution.testframework.TestTreeView;
@@ -25,9 +25,6 @@ import com.intellij.execution.testframework.ui.AbstractTestTreeBuilder;
 import com.intellij.ide.util.treeView.IndexComparator;
 import com.intellij.ide.util.treeView.NodeDescriptor;
 import com.intellij.openapi.diagnostic.Logger;
-import com.intellij.openapi.progress.ProgressIndicator;
-import com.intellij.openapi.progress.util.StatusBarProgress;
-import org.jetbrains.annotations.NotNull;
 import org.jetbrains.annotations.Nullable;
 
 import javax.swing.*;
@@ -41,8 +38,9 @@ public class TestTreeBuilder extends AbstractTestTreeBuilder {
   private static final Logger LOG = Logger.getInstance("#com.intellij.execution.junit2.ui.model.TestTreeBuilder");
 
   private JUnitRunningModel myModel;
-  private final JUnitAdapter myListener = new JUnitAdapter(){
+  private final JUnitAdapter myListener = new JUnitAdapter() {
     private final Collection<TestProxy> myNodesToUpdate = new HashSet<TestProxy>();
+
     public void onEventsDispatched(final List<TestEvent> events) {
       for (final TestEvent event : events) {
         final TestProxy testSubtree = (TestProxy)event.getTestSubtree();
@@ -75,18 +73,11 @@ public class TestTreeBuilder extends AbstractTestTreeBuilder {
     treeStructure.setSpecialNode(new SpecialNode(this, model));
     myModel = model;
     myModel.addListener(myListener);
-    init(tree, new DefaultTreeModel(new DefaultMutableTreeNode(treeStructure.createDescriptor(model.getRoot(), null))), treeStructure, IndexComparator.INSTANCE, true);
+    init(tree, new DefaultTreeModel(new DefaultMutableTreeNode(treeStructure.createDescriptor(model.getRoot(), null))), treeStructure,
+         IndexComparator.INSTANCE, true);
     initRootNode();
   }
 
-  protected boolean isSmartExpand() {
-    return false;
-  }
-
-  protected boolean isAlwaysShowPlus(final NodeDescriptor nodeDescriptor) {
-    return false;
-  }
-
   protected boolean isAutoExpandNode(final NodeDescriptor nodeDescriptor) {
     return nodeDescriptor.getElement() == myModel.getRoot();
   }
@@ -96,7 +87,7 @@ public class TestTreeBuilder extends AbstractTestTreeBuilder {
     DefaultMutableTreeNode node = getNodeForElement(test);
     if (node != null) {
       if (node.getParent() != null) {
-        expandNodeChildren((DefaultMutableTreeNode) node.getParent());
+        expandNodeChildren((DefaultMutableTreeNode)node.getParent());
         node = getNodeForElement(test);
       }
       return node;
@@ -112,9 +103,4 @@ public class TestTreeBuilder extends AbstractTestTreeBuilder {
     }
     return node;
   }
-
-  @NotNull
-  protected ProgressIndicator createProgressIndicator() {
-    return new StatusBarProgress();
-  }
 }
index e0a06884dbfcb46135a21e94482c1e971ced0867..f9b78b7a9407c4b2c2bb1dad92805c12215e627a 100644 (file)
  */
 package com.theoryinpractice.testng.model;
 
+import com.intellij.execution.testframework.ui.BaseTestProxyNodeDescriptor;
 import com.intellij.ide.util.treeView.NodeDescriptor;
 import com.intellij.openapi.project.Project;
 
 /**
  * @author Hani Suleiman Date: Jul 28, 2005 Time: 10:44:26 PM
  */
-public class TestNodeDescriptor extends NodeDescriptor<TestProxy>
-{
-    private final TestProxy node;
-
-    public TestNodeDescriptor(Project project, TestProxy node, NodeDescriptor<TestProxy> parent) {
-        super(project, parent);
-        this.node = node;
-        myName = node.getName();
-    }
-    
-    @Override
-    public boolean update() {
-        return false;
-    }
-
-    @Override
-    public TestProxy getElement() {
-        return node;
-    }
-
-    public boolean expandOnDoubleClick() {
-        return !node.isResult();
-    }
+public class TestNodeDescriptor extends BaseTestProxyNodeDescriptor<TestProxy> {
+  public TestNodeDescriptor(Project project, TestProxy node, NodeDescriptor<TestProxy> parent) {
+    super(project, node, parent);
+  }
 }
index 1bf037826de84d4eb7ee91bb8fd775b95cfbc2cd..24b45f0760882f73e1d0c93af3de7fffd46fb024 100644 (file)
@@ -27,36 +27,26 @@ import javax.swing.tree.DefaultTreeModel;
 /**
  * @author Hani Suleiman Date: Jul 28, 2005 Time: 10:49:36 PM
  */
-public class TestTreeBuilder extends AbstractTestTreeBuilder
-{
-    public TestTreeBuilder(JTree tree, AbstractTreeStructure structure) {
-        super(tree, new DefaultTreeModel(new DefaultMutableTreeNode(structure.getRootElement())), structure, IndexComparator.INSTANCE);
-        initRootNode();
+public class TestTreeBuilder extends AbstractTestTreeBuilder {
+  public TestTreeBuilder(JTree tree, AbstractTreeStructure structure) {
+    super(tree, new DefaultTreeModel(new DefaultMutableTreeNode(structure.getRootElement())), structure, IndexComparator.INSTANCE);
+    initRootNode();
+  }
+
+  @Override
+  protected boolean isAutoExpandNode(NodeDescriptor descriptor) {
+    return descriptor.getElement() == getTreeStructure().getRootElement();
+  }
+
+  public void addItem(TestProxy parent, TestProxy proxy) {
+    parent.addChild(proxy);
+    DefaultMutableTreeNode parentNode = getNodeForElement(parent);
+    if (parentNode != null) {
+      updateSubtree(parentNode);
     }
+  }
 
-    @Override
-    protected boolean isSmartExpand() {
-        return false;
-    }
-
-    @Override
-    protected boolean isAlwaysShowPlus(NodeDescriptor descriptor) {
-        return false;
-    }
-
-    @Override
-    protected boolean isAutoExpandNode(NodeDescriptor descriptor) {
-        return descriptor.getElement() == getTreeStructure().getRootElement();
-    }
-
-    public void addItem(TestProxy parent, TestProxy proxy) {
-        parent.addChild(proxy);
-        DefaultMutableTreeNode parentNode = getNodeForElement(parent);
-        if (parentNode != null)
-            updateSubtree(parentNode);
-    }
-
-    public TestProxy getRoot() {
-        return (TestProxy) getTreeStructure().getRootElement();
-    }
+  public TestProxy getRoot() {
+    return (TestProxy)getTreeStructure().getRootElement();
+  }
 }
index a6c33689e7b5204a25535b1b917f17ffe224a035..c75ec170d5bfc1c8cc0a0045a7729a550d9aa7e6 100644 (file)
@@ -214,7 +214,8 @@ public class TestNGResults extends TestResultsPanel implements TestFrameworkRunn
     final String testMethodDescriptor = result.getTestClass() + result.getMethod();
     if (startedMethods.contains(testMethodDescriptor)) {
       total++;
-    } else {
+    }
+    else {
       startedMethods.add(testMethodDescriptor);
     }
     animator.setCurrentTestCase(proxy);
@@ -241,13 +242,15 @@ public class TestNGResults extends TestResultsPanel implements TestFrameworkRunn
       final PsiElement element = getPackageClassNodeFor(result).getPsiElement();
       if (element instanceof PsiClass) {
         final PsiMethod[] methods = ApplicationManager.getApplication().runReadAction(
-            new Computable<PsiMethod[]>() {
-              public PsiMethod[] compute() {
-                return ((PsiClass)element).findMethodsByName(result.getMethod(), true);
-              }
+          new Computable<PsiMethod[]>() {
+            public PsiMethod[] compute() {
+              return ((PsiClass)element).findMethodsByName(result.getMethod(), true);
             }
+          }
         );
-        if (methods.length > 0 && methods[0] != null && !AnnotationUtil.isAnnotated(methods[0], Arrays.asList(TestNGUtil.CONFIG_ANNOTATIONS_FQN))) {
+        if (methods.length > 0 &&
+            methods[0] != null &&
+            !AnnotationUtil.isAnnotated(methods[0], Arrays.asList(TestNGUtil.CONFIG_ANNOTATIONS_FQN))) {
           for (List<TestProxy> proxies : started.values()) {
             if (proxies != null) {
               for (TestProxy proxy : proxies) {
@@ -283,7 +286,8 @@ public class TestNGResults extends TestResultsPanel implements TestFrameworkRunn
       if (failedToStart != null) {
         failedToStart.addChild(testCase);
         failedToStart.setTearDownFailure(true);
-      } else {
+      }
+      else {
         failedToStart = testCase;
       }
     }
@@ -294,7 +298,8 @@ public class TestNGResults extends TestResultsPanel implements TestFrameworkRunn
     if (result.getResult() == MessageHelper.FAILED_TEST) {
       myStatusLine.setStatusColor(ColorProgressBar.RED);
       myStatus = MessageHelper.FAILED_TEST;
-    } else if (result.getResult() == MessageHelper.SKIPPED_TEST && myStatus == MessageHelper.PASSED_TEST) {
+    }
+    else if (result.getResult() == MessageHelper.SKIPPED_TEST && myStatus == MessageHelper.PASSED_TEST) {
       myStatus = MessageHelper.SKIPPED_TEST;
     }
     myStatusLine.setFraction((double)count / total);
@@ -393,6 +398,11 @@ public class TestNGResults extends TestResultsPanel implements TestFrameworkRunn
     return tree;
   }
 
+  @Override
+  public TestTreeBuilder getTreeBuilder() {
+    return treeBuilder;
+  }
+
   public boolean hasTestSuites() {
     return rootNode.getChildren().size() > 0;
   }