Merge branch 'master' of git.labs.intellij.net:idea/community
authorKirill Likhodedov <kirill.likhodedov@jetbrains.com>
Tue, 13 Jul 2010 06:21:00 +0000 (10:21 +0400)
committerKirill Likhodedov <kirill.likhodedov@jetbrains.com>
Tue, 13 Jul 2010 06:21:00 +0000 (10:21 +0400)
110 files changed:
.idea/modules.xml
build/scripts/layouts.gant
java/compiler/impl/src/com/intellij/compiler/impl/TranslatingCompilerFilesMonitor.java
java/execution/openapi/src/com/intellij/execution/configurations/RemoteConnection.java
java/java-impl/src/com/intellij/codeInsight/daemon/impl/quickfix/CreateConstructorParameterFromFieldFix.java
java/java-impl/src/com/intellij/codeInsight/javadoc/JavaDocInfoGenerator.java
java/java-impl/src/com/intellij/codeInspection/suspiciousNameCombination/SuspiciousNameCombinationInspection.java
java/java-impl/src/com/intellij/refactoring/introduceVariable/IntroduceVariableBase.java
java/java-impl/src/com/intellij/refactoring/replaceConstructorWithBuilder/ParameterData.java
java/java-impl/src/com/intellij/refactoring/replaceConstructorWithBuilder/ReplaceConstructorWithBuilderProcessor.java
java/java-impl/src/com/intellij/refactoring/util/FieldConflictsResolver.java
java/java-impl/src/com/intellij/refactoring/util/RefactoringUtil.java
java/java-tests/testData/codeInsight/daemonCodeAnalyzer/quickFix/createConstructorParameterFromField/afterChainedCalls.java [new file with mode: 0644]
java/java-tests/testData/codeInsight/daemonCodeAnalyzer/quickFix/createConstructorParameterFromField/beforeChainedCalls.java [new file with mode: 0644]
java/java-tests/testSrc/com/intellij/refactoring/SafeDeleteTest.java
platform/lang-impl/src/com/intellij/execution/console/ConsoleFoldingConfigurable.java [moved from plugins/consoleFolding/src/com/intellij/execution/ConsoleFoldingConfigurable.java with 74% similarity]
platform/lang-impl/src/com/intellij/execution/console/ConsoleFoldingSettings.java [moved from plugins/consoleFolding/src/com/intellij/execution/ConsoleFoldingSettings.java with 93% similarity]
platform/lang-impl/src/com/intellij/execution/console/CustomizableConsoleFoldingBean.java [moved from plugins/consoleFolding/src/com/intellij/execution/CustomizableConsoleFoldingBean.java with 93% similarity]
platform/lang-impl/src/com/intellij/execution/console/FoldLinesLikeThis.java [new file with mode: 0644]
platform/lang-impl/src/com/intellij/execution/console/LanguageConsoleImpl.java
platform/lang-impl/src/com/intellij/execution/console/SubstringConsoleFolding.java [moved from plugins/consoleFolding/src/com/intellij/execution/SubstringConsoleFolding.java with 85% similarity]
platform/lang-impl/src/com/intellij/execution/impl/ConsoleViewImpl.java
platform/lang-impl/src/com/intellij/execution/impl/RunConfigurable.java
platform/lang-impl/src/com/intellij/refactoring/rename/PsiElementRenameHandler.java
platform/lang-impl/src/com/intellij/refactoring/rename/RenamePsiElementProcessor.java
platform/lang-impl/src/com/intellij/unscramble/AnalyzeStacktraceUtil.java
platform/platform-api/src/com/intellij/openapi/editor/LogicalPosition.java
platform/platform-api/src/com/intellij/ui/AddDeleteListPanel.java
platform/platform-api/src/com/intellij/ui/AddEditDeleteListPanel.java [new file with mode: 0644]
platform/platform-impl/src/com/intellij/ide/impl/ProjectUtil.java
platform/platform-impl/src/com/intellij/openapi/editor/ex/SoftWrapChangeListener.java
platform/platform-impl/src/com/intellij/openapi/editor/ex/util/EditorUtil.java
platform/platform-impl/src/com/intellij/openapi/editor/impl/EditorImpl.java
platform/platform-impl/src/com/intellij/openapi/editor/impl/SoftWrapModelImpl.java
platform/platform-impl/src/com/intellij/openapi/editor/impl/softwrap/DefaultSoftWrapApplianceManager.java
platform/platform-impl/src/com/intellij/openapi/editor/impl/softwrap/SoftWrapDataMapper.java
platform/platform-impl/src/com/intellij/openapi/editor/impl/softwrap/SoftWrapsStorage.java
platform/platform-impl/src/com/intellij/openapi/wm/impl/IdeRootPane.java
platform/platform-impl/src/com/intellij/openapi/wm/impl/status/IdeStatusBarImpl.java
platform/platform-impl/src/com/intellij/openapi/wm/impl/status/MemoryUsagePanel.java
platform/platform-impl/testSrc/com/intellij/openapi/editor/impl/softwrap/SoftWrapDataMapperTest.java
platform/platform-resources-en/src/messages/RefactoringBundle.properties
platform/platform-resources/src/META-INF/LangExtensionPoints.xml
platform/platform-resources/src/META-INF/LangExtensions.xml
platform/testRunner/src/com/intellij/execution/testframework/ui/TestsOutputConsolePrinter.java
platform/util/src/com/intellij/util/containers/ContainerUtil.java
platform/util/testSrc/com/intellij/util/containers/WeaksTestCase.java
plugins/IntelliLang/src/org/intellij/plugins/intelliLang/inject/quickedit/QuickEditAction.java
plugins/IntelliLang/xml-support/org/intellij/plugins/intelliLang/inject/config/XmlAttributeInjection.java
plugins/IntelliLang/xml-support/resources/xmlInjections.xml
plugins/consoleFolding/consoleFolding.iml [deleted file]
plugins/consoleFolding/src/META-INF/plugin.xml [deleted file]
plugins/groovy/grape/grape-rt.iml [deleted file]
plugins/groovy/grape/grape.iml [deleted file]
plugins/groovy/grape/src/META-INF/plugin.xml [deleted file]
plugins/groovy/groovypp/groovypp.iml [deleted file]
plugins/groovy/groovypp/src/META-INF/plugin.xml [deleted file]
plugins/groovy/hotswap/groovy-hotswap.iml [deleted file]
plugins/groovy/hotswap/pluginSrc/META-INF/plugin.xml [deleted file]
plugins/groovy/jetgroovy-tests.iml [deleted file]
plugins/groovy/jetgroovy.iml
plugins/groovy/resources/intentionDescriptions/GrabDependencies/after.groovy.template [moved from plugins/groovy/grape/resources/intentionDescriptions/GrabDependencies/after.groovy.template with 100% similarity]
plugins/groovy/resources/intentionDescriptions/GrabDependencies/before.groovy.template [moved from plugins/groovy/grape/resources/intentionDescriptions/GrabDependencies/before.groovy.template with 100% similarity]
plugins/groovy/resources/intentionDescriptions/GrabDependencies/description.html [moved from plugins/groovy/grape/resources/intentionDescriptions/GrabDependencies/description.html with 100% similarity]
plugins/groovy/rt/src/org/jetbrains/plugins/groovy/grape/GrapeRunner.java [moved from plugins/groovy/grape/rt/src/org/jetbrains/plugins/groovy/grape/GrapeRunner.java with 100% similarity]
plugins/groovy/src/META-INF/plugin.xml
plugins/groovy/src/org/jetbrains/plugins/groovy/GroovyFileTypeLoader.java
plugins/groovy/src/org/jetbrains/plugins/groovy/compiler/ExcludeFromStubGenerationAction.java
plugins/groovy/src/org/jetbrains/plugins/groovy/compiler/GroovyCompilerLoader.java
plugins/groovy/src/org/jetbrains/plugins/groovy/compiler/generator/GroovyToJavaGenerator.java
plugins/groovy/src/org/jetbrains/plugins/groovy/compiler/generator/GroovycStubGenerator.java
plugins/groovy/src/org/jetbrains/plugins/groovy/debugger/GroovyHotSwapper.java [moved from plugins/groovy/hotswap/pluginSrc/org/jetbrains/plugins/groovy/debugger/GroovyHotSwapper.java with 100% similarity]
plugins/groovy/src/org/jetbrains/plugins/groovy/gpp/GppClassSubstitutor.java [moved from plugins/groovy/groovypp/src/org/jetbrains/plugins/groovy/gpp/GppClassSubstitutor.java with 100% similarity]
plugins/groovy/src/org/jetbrains/plugins/groovy/gpp/GppClosureParameterTypeProvider.java [moved from plugins/groovy/groovypp/src/org/jetbrains/plugins/groovy/gpp/GppClosureParameterTypeProvider.java with 100% similarity]
plugins/groovy/src/org/jetbrains/plugins/groovy/gpp/GppExpectedTypesContributor.java [moved from plugins/groovy/groovypp/src/org/jetbrains/plugins/groovy/gpp/GppExpectedTypesContributor.java with 100% similarity]
plugins/groovy/src/org/jetbrains/plugins/groovy/gpp/GppLibraryManager.java [moved from plugins/groovy/groovypp/src/org/jetbrains/plugins/groovy/gpp/GppLibraryManager.java with 100% similarity]
plugins/groovy/src/org/jetbrains/plugins/groovy/gpp/GppPositionManager.java [moved from plugins/groovy/groovypp/src/org/jetbrains/plugins/groovy/gpp/GppPositionManager.java with 100% similarity]
plugins/groovy/src/org/jetbrains/plugins/groovy/gpp/GppReferenceContributor.java [moved from plugins/groovy/groovypp/src/org/jetbrains/plugins/groovy/gpp/GppReferenceContributor.java with 100% similarity]
plugins/groovy/src/org/jetbrains/plugins/groovy/gpp/GppStdLibSupport.java [moved from plugins/groovy/groovypp/src/org/jetbrains/plugins/groovy/gpp/GppStdLibSupport.java with 100% similarity]
plugins/groovy/src/org/jetbrains/plugins/groovy/gpp/GppTypeConverter.java [moved from plugins/groovy/groovypp/src/org/jetbrains/plugins/groovy/gpp/GppTypeConverter.java with 87% similarity]
plugins/groovy/src/org/jetbrains/plugins/groovy/grape/GrabDependencies.java [moved from plugins/groovy/grape/src/org/jetbrains/plugins/groovy/grape/GrabDependencies.java with 100% similarity]
plugins/groovy/src/org/jetbrains/plugins/groovy/lang/completion/GroovyCompletionContributor.java
plugins/groovy/src/org/jetbrains/plugins/groovy/lang/psi/GrTypeConverter.java
plugins/groovy/src/org/jetbrains/plugins/groovy/lang/psi/api/statements/expressions/path/GrCallExpression.java
plugins/groovy/src/org/jetbrains/plugins/groovy/lang/psi/expectedTypes/GroovyExpectedTypesProvider.java
plugins/groovy/src/org/jetbrains/plugins/groovy/lang/psi/impl/GrContainerTypeConverter.java
plugins/groovy/src/org/jetbrains/plugins/groovy/lang/psi/impl/GrMapType.java
plugins/groovy/src/org/jetbrains/plugins/groovy/lang/psi/impl/GrTupleType.java
plugins/groovy/src/org/jetbrains/plugins/groovy/lang/psi/impl/statements/expressions/GrNewExpressionImpl.java
plugins/groovy/src/org/jetbrains/plugins/groovy/lang/psi/impl/statements/expressions/GrReferenceExpressionImpl.java
plugins/groovy/src/org/jetbrains/plugins/groovy/lang/psi/impl/statements/expressions/TypesUtil.java
plugins/groovy/src/org/jetbrains/plugins/groovy/lang/psi/impl/statements/expressions/path/GrMethodCallExpressionImpl.java
plugins/groovy/src/org/jetbrains/plugins/groovy/lang/psi/patterns/GroovyExpressionPattern.java
plugins/groovy/src/org/jetbrains/plugins/groovy/lang/psi/util/PsiUtil.java
plugins/groovy/src/org/jetbrains/plugins/groovy/lang/resolve/ResolveUtil.java
plugins/groovy/src/org/jetbrains/plugins/groovy/lang/resolve/processors/MethodResolverProcessor.java
plugins/groovy/test/org/jetbrains/plugins/groovy/compiler/GppCompilerTest.groovy [new file with mode: 0644]
plugins/groovy/test/org/jetbrains/plugins/groovy/compiler/GroovyCompilerTest.groovy
plugins/groovy/test/org/jetbrains/plugins/groovy/compiler/GroovyCompilerTestCase.java
plugins/groovy/test/org/jetbrains/plugins/groovy/lang/GppFunctionalTest.groovy
plugins/groovy/testdata/highlighting/SignatureIsNotApplicableToList.groovy
plugins/groovy/testdata/realGroovypp/groovypp-all-0.2.13.jar [new file with mode: 0644]
plugins/junit/src/META-INF/plugin.xml
plugins/junit/src/com/intellij/execution/junit2/inspection/JUnitUnusedCodeExtension.java
plugins/relaxng/test/org/intellij/plugins/relaxNG/RngXmlHighlightingTest.java [moved from plugins/relaxng/test/org/intellij/plugins/relaxNG/XmlHighlightingTest.java with 98% similarity]
plugins/relaxng/test/org/intellij/plugins/relaxNG/RngXmlValidationTest.java [moved from plugins/relaxng/test/org/intellij/plugins/relaxNG/XmlValidationTest.java with 97% similarity]
plugins/testng/src/com/theoryinpractice/testng/inspection/TestNGUnusedCodeExtension.java
xml/impl/src/com/intellij/codeInsight/daemon/impl/analysis/ConvertSchemaPrefixToDefaultIntention.java
xml/impl/src/com/intellij/codeInsight/template/zencoding/ZenCodingTemplate.java
xml/impl/src/com/intellij/psi/impl/source/resolve/reference/impl/manipulators/XmlTextManipulator.java

index d94269431fdf06f81e1fe9ff081574b37776fbed..454bcfb7a55b3765de5d77a294cf7864ef7e6712 100644 (file)
       <module fileurl="file://$PROJECT_DIR$/platform/forms_rt/forms_rt.iml" filepath="$PROJECT_DIR$/platform/forms_rt/forms_rt.iml" group="platform" />
       <module fileurl="file://$PROJECT_DIR$/plugins/generate-tostring/generate-tostring.iml" filepath="$PROJECT_DIR$/plugins/generate-tostring/generate-tostring.iml" group="plugins" />
       <module fileurl="file://$PROJECT_DIR$/plugins/git4idea/git4idea.iml" filepath="$PROJECT_DIR$/plugins/git4idea/git4idea.iml" group="plugins/VCS" />
-      <module fileurl="file://$PROJECT_DIR$/plugins/groovy/grape/grape.iml" filepath="$PROJECT_DIR$/plugins/groovy/grape/grape.iml" group="plugins/Groovy" />
-      <module fileurl="file://$PROJECT_DIR$/plugins/groovy/grape/grape-rt.iml" filepath="$PROJECT_DIR$/plugins/groovy/grape/grape-rt.iml" group="plugins/Groovy" />
-      <module fileurl="file://$PROJECT_DIR$/plugins/groovy/hotswap/groovy-hotswap.iml" filepath="$PROJECT_DIR$/plugins/groovy/hotswap/groovy-hotswap.iml" group="plugins/Groovy" />
-      <module fileurl="file://$PROJECT_DIR$/plugins/groovy/rt/groovy-rt.iml" filepath="$PROJECT_DIR$/plugins/groovy/rt/groovy-rt.iml" group="plugins/Groovy" />
-      <module fileurl="file://$PROJECT_DIR$/plugins/groovy/groovypp/groovypp.iml" filepath="$PROJECT_DIR$/plugins/groovy/groovypp/groovypp.iml" group="plugins/Groovy" />
       <module fileurl="file://$PROJECT_DIR$/plugins/hg4idea/hg4idea.iml" filepath="$PROJECT_DIR$/plugins/hg4idea/hg4idea.iml" group="plugins/VCS" />
       <module fileurl="file://$PROJECT_DIR$/platform/icons/icons.iml" filepath="$PROJECT_DIR$/platform/icons/icons.iml" group="platform" />
       <module fileurl="file://$PROJECT_DIR$/java/idea-ui/idea-ui.iml" filepath="$PROJECT_DIR$/java/idea-ui/idea-ui.iml" group="java" />
@@ -52,7 +47,6 @@
       <module fileurl="file://$PROJECT_DIR$/java/compiler/javac2/javac2.iml" filepath="$PROJECT_DIR$/java/compiler/javac2/javac2.iml" group="java/compiler" />
       <module fileurl="file://$PROJECT_DIR$/plugins/cvs/javacvs-src/javacvs-src.iml" filepath="$PROJECT_DIR$/plugins/cvs/javacvs-src/javacvs-src.iml" group="plugins/VCS/cvs" />
       <module fileurl="file://$PROJECT_DIR$/plugins/groovy/jetgroovy.iml" filepath="$PROJECT_DIR$/plugins/groovy/jetgroovy.iml" group="plugins/Groovy" />
-      <module fileurl="file://$PROJECT_DIR$/plugins/groovy/jetgroovy-tests.iml" filepath="$PROJECT_DIR$/plugins/groovy/jetgroovy-tests.iml" group="plugins/Groovy" />
       <module fileurl="file://$PROJECT_DIR$/java/jsp-base-openapi/jsp-base-openapi.iml" filepath="$PROJECT_DIR$/java/jsp-base-openapi/jsp-base-openapi.iml" group="java" />
       <module fileurl="file://$PROJECT_DIR$/java/jsp-openapi/jsp-openapi.iml" filepath="$PROJECT_DIR$/java/jsp-openapi/jsp-openapi.iml" group="java" />
       <module fileurl="file://$PROJECT_DIR$/java/jsp-spi/jsp-spi.iml" filepath="$PROJECT_DIR$/java/jsp-spi/jsp-spi.iml" group="java" />
index d1f251c179c394a0d4cc640bea947d02ae989661..f61a8bd91d7e2fba1f39bebc4bc100cdf80d62e9 100644 (file)
@@ -173,7 +173,7 @@ def layoutFull(String home, String targetDirectory) {
       layoutPlugin("SpellChecker", "spellchecker", "spellchecker-core")
 
       layoutPlugin("RelaxNG-Support", "relaxng") {
-        fileset(dir: "${home}/community/plugins/relaxng/lib", includes: "**/*.jar")
+        fileset(dir: "$home/plugins/relaxng/lib", includes: "**/*.jar")
       }
 
       layoutPlugin("maven") {
@@ -267,20 +267,18 @@ def layoutFull(String home, String targetDirectory) {
           dir("standardDsls") {
             fileset(dir: "$home/plugins/groovy/resources/standardDsls")
           }
+          dir("agent") {
+            fileset(dir: "${home}/plugins/groovy/hotswap") {
+              include(name: "gragent.jar")
+            }
+          }
+
 
           fileset(dir: "$home/plugins/groovy/resources/conf")
           fileset(dir: "${home}/plugins/groovy/lib")
         }
       }
 
-      dir("Groovypp") {
-        dir("lib") {
-          jar("groovypp.jar") {
-            module("groovypp")
-          }
-        }
-      }
-
     }
   }
 
index 76de9729c7e778700f96b9e0a1450c2a3264efdf..f883024fdc71a958f909009de90102957b0e5774 100644 (file)
@@ -161,14 +161,16 @@ public class TranslatingCompilerFilesMonitor implements ApplicationComponent {
     synchronized (mySourcesToRecompile) {
       final TIntHashSet pathsToRecompile = mySourcesToRecompile.get(projectId);
       if (_forceCompile || pathsToRecompile != null && !pathsToRecompile.isEmpty()) {
+        if (ourDebugMode) {
+          System.out.println("Analysing potentially recompilable files for " + compiler.getDescription());
+        }
         while (scopeSrcIterator.hasNext()) {
           final VirtualFile file = scopeSrcIterator.next();
           if (!file.isValid()) {
             if (LOG.isDebugEnabled() || ourDebugMode) {
-              final String message = "Skipping invalid file " + file.getPresentableUrl();
-              LOG.debug(message);
+              LOG.debug("Skipping invalid file " + file.getPresentableUrl());
               if (ourDebugMode) {
-                System.out.println(message);
+                System.out.println("\t SKIPPED(INVALID) " + file.getPresentableUrl());
               }
             }
             continue;
@@ -177,17 +179,38 @@ public class TranslatingCompilerFilesMonitor implements ApplicationComponent {
           if (_forceCompile) {
             if (compiler.isCompilableFile(file, context) && !configuration.isExcludedFromCompilation(file)) {
               toCompile.add(file);
+              if (ourDebugMode) {
+                System.out.println("\t INCLUDED " + file.getPresentableUrl());
+              }
               selectedForRecompilation.add(file);
               if (pathsToRecompile == null || !pathsToRecompile.contains(fileId)) {
                 addSourceForRecompilation(projectId, file, null);
               }
             }
+            else {
+              if (ourDebugMode) {
+                System.out.println("\t NOT COMPILABLE OR EXCLUDED " + file.getPresentableUrl());
+              }
+            }
           }
           else if (pathsToRecompile.contains(fileId)) {
             if (compiler.isCompilableFile(file, context) && !configuration.isExcludedFromCompilation(file)) {
               toCompile.add(file);
+              if (ourDebugMode) {
+                System.out.println("\t INCLUDED " + file.getPresentableUrl());
+              }
               selectedForRecompilation.add(file);
             }
+            else {
+              if (ourDebugMode) {
+                System.out.println("\t NOT COMPILABLE OR EXCLUDED " + file.getPresentableUrl());
+              }
+            }
+          }
+          else {
+            if (ourDebugMode) {
+              System.out.println("\t NOT INCLUDED " + file.getPresentableUrl());
+            }
           }
         }
       }
index aeb8cf6c0d1fe79413fcf4058af625975c95e1ad..a08efdc933e1deea649674496db5e6f8a069fb97 100644 (file)
@@ -17,6 +17,9 @@ package com.intellij.execution.configurations;
 
 import org.jetbrains.annotations.NonNls;
 
+import java.net.InetAddress;
+import java.net.UnknownHostException;
+
 public class RemoteConnection {
   private boolean myUseSockets;
   private boolean myServerMode;
@@ -90,8 +93,18 @@ public class RemoteConnection {
       catch (NumberFormatException e) {
       }
       if (serverMode) {
-        result = "-Xdebug -Xrunjdwp:transport=dt_socket,server=n,address=" +
-                 ((p == -1)? "..." : Integer.toString(p)) +
+        String localHostName = "<host name>:";
+        try {
+          final InetAddress localAddress = InetAddress.getLocalHost();
+          final String name = localAddress.getCanonicalHostName();
+          if (name != null) {
+            localHostName = name + ":";
+          }
+        }
+        catch (UnknownHostException e) {
+        }
+        result = "-Xdebug -Xrunjdwp:transport=dt_socket,server=n,address=" + localHostName +
+                 ((p == -1)? "<port>" : Integer.toString(p)) +
                  ONTHROW + ",suspend=y" + ONUNCAUGHT;
       }
       else {
index 5a7b05dd3b1dd2117c7282f7f750426194cdfbf0..e3aafe432b11116230d420dfb9d51520dd09cffb 100644 (file)
@@ -28,9 +28,13 @@ import com.intellij.openapi.util.Computable;
 import com.intellij.psi.*;
 import com.intellij.psi.impl.source.jsp.jspJava.JspClass;
 import com.intellij.psi.util.PsiTypesUtil;
+import com.intellij.refactoring.util.RefactoringUtil;
 import com.intellij.util.IncorrectOperationException;
 import org.jetbrains.annotations.NotNull;
 
+import java.util.Arrays;
+import java.util.Comparator;
+
 public class CreateConstructorParameterFromFieldFix implements IntentionAction {
   private final SmartPsiElementPointer<PsiField> myField;
 
@@ -76,8 +80,22 @@ public class CreateConstructorParameterFromFieldFix implements IntentionAction {
       aClass = getField().getContainingClass();
       constructors = aClass.getConstructors();
     }
-    for (int i = 0; i < constructors.length; i++){
-      if (!addParameterToConstructor(project, file, editor, getField().getContainingClass().getConstructors()[i])) break;
+    Arrays.sort(constructors, new Comparator<PsiMethod>() {
+      @Override
+      public int compare(PsiMethod c1, PsiMethod c2) {
+        final PsiMethod cc1 = RefactoringUtil.getChainedConstructor(c1);
+        final PsiMethod cc2 = RefactoringUtil.getChainedConstructor(c2);
+        if (cc1 == c2) return 1;
+        if (cc2 == c1) return -1;
+        if (cc1 == null) {
+          return cc2 == null ? 0 : compare(c1, cc2);
+        } else {
+          return cc2 == null ? compare(cc1, c2) : compare(cc1, cc2);
+        }
+      }
+    });
+    for (PsiMethod constructor : constructors) {
+      if (!addParameterToConstructor(project, file, editor, constructor)) break;
     }
   }
 
index 7453b29a9cb3d0d1bec66f7acc2de10f0b5a2558..b50a34e6d9c62cd3906c2aeaf6ce21d1dd541d5f 100644 (file)
@@ -339,7 +339,10 @@ public class JavaDocInfoGenerator {
     generateTypeParametersSection(buffer, result);
   }
 
+  @Nullable
   private static Pair<PsiDocTag, InheritDocProvider<PsiDocTag>> findInHierarchy(PsiClass psiClass, final DocTagLocator<PsiDocTag> locator) {
+    final Pair<PsiDocTag, InheritDocProvider<PsiDocTag>> inClassComment = findInClassComment(psiClass, locator);
+    if (inClassComment != null) return inClassComment;
     for (final PsiClass superClass : psiClass.getSupers()) {
       final Pair<PsiDocTag, InheritDocProvider<PsiDocTag>> pair = findInClassComment(superClass, locator);
       if (pair != null) return pair;
@@ -348,7 +351,7 @@ public class JavaDocInfoGenerator {
       final Pair<PsiDocTag, InheritDocProvider<PsiDocTag>> pair = findInClassComment(superInterface, locator);
       if (pair != null) return pair;
     }
-    return findInClassComment(psiClass, locator);
+    return null;
   }
 
   private static Pair<PsiDocTag, InheritDocProvider<PsiDocTag>> findInClassComment(final PsiClass psiClass, final DocTagLocator<PsiDocTag> locator) {
index 77ce710a95e11a885acdd5632c19e35c90392d05..33e320c53982e6d7834d78feabb76b9ae570cc44 100644 (file)
@@ -16,7 +16,6 @@
 
 package com.intellij.codeInspection.suspiciousNameCombination;
 
-import com.intellij.CommonBundle;
 import com.intellij.codeInsight.daemon.GroupNames;
 import com.intellij.codeInsight.daemon.JavaErrorMessages;
 import com.intellij.codeInspection.InspectionsBundle;
@@ -29,7 +28,7 @@ import com.intellij.openapi.util.text.StringUtil;
 import com.intellij.psi.*;
 import com.intellij.psi.codeStyle.NameUtil;
 import com.intellij.psi.util.PsiTreeUtil;
-import com.intellij.ui.AddDeleteListPanel;
+import com.intellij.ui.AddEditDeleteListPanel;
 import org.jdom.Element;
 import org.jetbrains.annotations.NonNls;
 import org.jetbrains.annotations.NotNull;
@@ -38,10 +37,6 @@ import org.jetbrains.annotations.Nullable;
 import javax.swing.*;
 import javax.swing.event.ListDataEvent;
 import javax.swing.event.ListDataListener;
-import java.awt.event.ActionEvent;
-import java.awt.event.ActionListener;
-import java.awt.event.MouseAdapter;
-import java.awt.event.MouseEvent;
 import java.util.ArrayList;
 import java.util.HashMap;
 import java.util.List;
@@ -209,23 +204,10 @@ public class SuspiciousNameCombinationInspection extends BaseLocalInspectionTool
     }
   }
 
-  private class MyOptionsPanel extends AddDeleteListPanel {
-    private JButton myEditButton;
+  private class MyOptionsPanel extends AddEditDeleteListPanel<String> {
 
     public MyOptionsPanel() {
       super(InspectionsBundle.message("suspicious.name.combination.options.title"), myNameGroups);
-      myEditButton.addActionListener(new ActionListener() {
-        public void actionPerformed(ActionEvent e) {
-          editSelectedItem();
-        }
-      });
-      myList.addMouseListener(new MouseAdapter() {
-        public void mouseClicked(MouseEvent e) {
-          if (e.getClickCount() == 2 && e.getButton() == MouseEvent.BUTTON1) {
-            editSelectedItem();
-          }
-        }
-      });
       myListModel.addListDataListener(new ListDataListener() {
         public void intervalAdded(ListDataEvent e) {
           saveChanges();
@@ -241,31 +223,20 @@ public class SuspiciousNameCombinationInspection extends BaseLocalInspectionTool
       });
     }
 
-    @Override protected JButton[] createButtons() {
-      myEditButton = new JButton(CommonBundle.message("button.edit"));
-      return new JButton[] { myAddButton, myEditButton, myDeleteButton };
-    }
-
-    protected Object findItemToAdd() {
+    protected String findItemToAdd() {
       return Messages.showInputDialog(this,
                                       InspectionsBundle.message("suspicious.name.combination.options.prompt"),
                                       InspectionsBundle.message("suspicious.name.combination.add.titile"),
                                       Messages.getQuestionIcon(), "", null);
     }
 
-    private void editSelectedItem() {
-      int index = myList.getSelectedIndex();
-      if (index >= 0) {
-        String inputValue = (String) myListModel.get(index);
-        String newValue = Messages.showInputDialog(this,
-                                                   InspectionsBundle.message("suspicious.name.combination.options.prompt"),
-                                                   InspectionsBundle.message("suspicious.name.combination.edit.title"),
-                                                   Messages.getQuestionIcon(),
-                                                   inputValue, null);
-        if (newValue != null) {
-          myListModel.set(index, newValue);
-        }
-      }
+    @Override
+    protected String editSelectedItem(String inputValue) {
+      return Messages.showInputDialog(this,
+                                      InspectionsBundle.message("suspicious.name.combination.options.prompt"),
+                                      InspectionsBundle.message("suspicious.name.combination.edit.title"),
+                                      Messages.getQuestionIcon(),
+                                      inputValue, null);
     }
 
     private void saveChanges() {
index 9d373db01edcc8962a78a92953f8cf0b650121cd..705c7f0e195adf0e7a2e465307875bff974a9cb3 100644 (file)
@@ -127,6 +127,9 @@ public abstract class IntroduceVariableBase extends IntroduceHandlerBase impleme
       correctedOffset = offset;
     }
     else if (!Character.isJavaIdentifierPart(text.charAt(correctedOffset))) {
+      if (text.charAt(correctedOffset) == ';') {//initially caret on the end of line
+        correctedOffset--;
+      }
       if (text.charAt(correctedOffset) != ')') {
         correctedOffset = offset;
       }
index 4d7307edeeb33e285682404ec72533aba678a2b4..5279cd3a3b2517ec2cabf796d572abb3d529b8c3 100644 (file)
@@ -25,7 +25,7 @@ import com.intellij.psi.*;
 import com.intellij.psi.codeStyle.JavaCodeStyleManager;
 import com.intellij.psi.codeStyle.VariableKind;
 import com.intellij.psi.util.PropertyUtil;
-import org.jetbrains.annotations.Nullable;
+import com.intellij.refactoring.util.RefactoringUtil;
 
 import java.util.Map;
 
@@ -51,7 +51,7 @@ public class ParameterData {
       initParameterData(parameter, result);
     }
 
-    final PsiMethod chainedConstructor = getChainedConstructor(constructor);
+    final PsiMethod chainedConstructor = RefactoringUtil.getChainedConstructor(constructor);
     if (chainedConstructor != null) {
       final PsiCodeBlock constructorBody = constructor.getBody();
       LOG.assertTrue(constructorBody != null);
@@ -68,24 +68,6 @@ public class ParameterData {
     }
   }
 
-  @Nullable
-  public static PsiMethod getChainedConstructor(PsiMethod constructor) {
-    final PsiCodeBlock constructorBody = constructor.getBody();
-    LOG.assertTrue(constructorBody != null);
-    final PsiStatement[] statements = constructorBody.getStatements();
-    if (statements.length == 1 && statements[0] instanceof PsiExpressionStatement) {
-      final PsiExpression expression = ((PsiExpressionStatement)statements[0]).getExpression();
-      if (expression instanceof PsiMethodCallExpression) {
-        final PsiMethodCallExpression methodCallExpression = (PsiMethodCallExpression)expression;
-        final PsiReferenceExpression methodExpr = methodCallExpression.getMethodExpression();
-        if ("this".equals(methodExpr.getReferenceName())) {
-          return (PsiMethod)methodExpr.resolve();
-        }
-      }
-    }
-    return null;
-  }
-
   private static ParameterData initParameterData(PsiParameter parameter, Map<String, ParameterData> result) {
     JavaCodeStyleManager styleManager = JavaCodeStyleManager.getInstance(parameter.getProject());
     final String paramName = parameter.getName();
index 41f53f6631d76f5547bc1a2dacdf66e1e2625366..f6b4b5e6463e433e946f4a445bac5715f4cc98a9 100644 (file)
@@ -40,6 +40,7 @@ import com.intellij.psi.util.TypeConversionUtil;
 import com.intellij.refactoring.replaceConstructorWithBuilder.usageInfo.ReplaceConstructorWithSettersChainInfo;
 import com.intellij.refactoring.util.FixableUsageInfo;
 import com.intellij.refactoring.util.FixableUsagesRefactoringProcessor;
+import com.intellij.refactoring.util.RefactoringUtil;
 import com.intellij.usageView.UsageInfo;
 import com.intellij.usageView.UsageViewDescriptor;
 import com.intellij.util.IncorrectOperationException;
@@ -234,7 +235,7 @@ public class ReplaceConstructorWithBuilderProcessor extends FixableUsagesRefacto
     if (myConstructors.length == 1) return myConstructors[0];
     PsiMethod commonConstructor = null;
     for (PsiMethod constructor : myConstructors) {
-      final PsiMethod chainedConstructor = ParameterData.getChainedConstructor(constructor);
+      final PsiMethod chainedConstructor = RefactoringUtil.getChainedConstructor(constructor);
       if (chainedConstructor == null) {
         if (commonConstructor != null) {
           if (!isChained(commonConstructor, constructor)) {
@@ -258,7 +259,7 @@ public class ReplaceConstructorWithBuilderProcessor extends FixableUsagesRefacto
   private static boolean isChained(PsiMethod first, PsiMethod last) {
     if (first == null) return false;
     if (first == last) return true;
-    return isChained(ParameterData.getChainedConstructor(first), last);
+    return isChained(RefactoringUtil.getChainedConstructor(first), last);
   }
 
   private String createMethodName() {
index 9fbea01ed06be5633ae0fe09a6289577e578cf6c..974568a2a324c4cc271ac7f167a719ad628693a1 100644 (file)
@@ -15,6 +15,7 @@
  */
 package com.intellij.refactoring.util;
 
+import com.intellij.codeInsight.daemon.impl.analysis.HighlightUtil;
 import com.intellij.openapi.diagnostic.Logger;
 import com.intellij.psi.*;
 import com.intellij.psi.codeStyle.CodeStyleManager;
@@ -113,6 +114,13 @@ public class FieldConflictsResolver {
                                                         final PsiMember member,
                                                         @Nullable final PsiClass qualifyingClass) throws IncorrectOperationException {
     PsiManager manager = referenceExpression.getManager();
+    PsiMethodCallExpression methodCallExpression = PsiTreeUtil.getParentOfType(referenceExpression, PsiMethodCallExpression.class, true);
+    while ((methodCallExpression) != null) {
+      if (HighlightUtil.isSuperOrThisMethodCall(methodCallExpression)) {
+        return referenceExpression;
+      }
+      methodCallExpression = PsiTreeUtil.getParentOfType(methodCallExpression, PsiMethodCallExpression.class, true);
+    }
     PsiReferenceExpression expressionFromText;
     final PsiElementFactory factory = JavaPsiFacade.getInstance(manager.getProject()).getElementFactory();
     if (qualifyingClass == null) {
index 5cd57a03d9dde4afb9b5eb3b31451d90e0c1ee14..9f82d897afce1326ef2fd2773d431e961a9ac5b9 100644 (file)
@@ -53,6 +53,7 @@ import com.intellij.psi.util.TypeConversionUtil;
 import com.intellij.refactoring.PackageWrapper;
 import com.intellij.refactoring.introduceField.ElementToWorkOn;
 import com.intellij.refactoring.introduceVariable.IntroduceVariableBase;
+import com.intellij.refactoring.replaceConstructorWithBuilder.ParameterData;
 import com.intellij.usageView.UsageInfo;
 import com.intellij.util.IncorrectOperationException;
 import com.intellij.util.containers.HashMap;
@@ -913,6 +914,24 @@ public class RefactoringUtil {
     return array;
   }
 
+  @Nullable
+  public static PsiMethod getChainedConstructor(PsiMethod constructor) {
+    final PsiCodeBlock constructorBody = constructor.getBody();
+    LOG.assertTrue(constructorBody != null);
+    final PsiStatement[] statements = constructorBody.getStatements();
+    if (statements.length == 1 && statements[0] instanceof PsiExpressionStatement) {
+      final PsiExpression expression = ((PsiExpressionStatement)statements[0]).getExpression();
+      if (expression instanceof PsiMethodCallExpression) {
+        final PsiMethodCallExpression methodCallExpression = (PsiMethodCallExpression)expression;
+        final PsiReferenceExpression methodExpr = methodCallExpression.getMethodExpression();
+        if ("this".equals(methodExpr.getReferenceName())) {
+          return (PsiMethod)methodExpr.resolve();
+        }
+      }
+    }
+    return null;
+  }
+
   public static interface ImplicitConstructorUsageVisitor {
     void visitConstructor(PsiMethod constructor, PsiMethod baseConstructor);
 
diff --git a/java/java-tests/testData/codeInsight/daemonCodeAnalyzer/quickFix/createConstructorParameterFromField/afterChainedCalls.java b/java/java-tests/testData/codeInsight/daemonCodeAnalyzer/quickFix/createConstructorParameterFromField/afterChainedCalls.java
new file mode 100644 (file)
index 0000000..830383e
--- /dev/null
@@ -0,0 +1,14 @@
+// "Add constructor parameter" "true"
+class A {
+  private final int field;
+  private int j;
+
+  A(int field) {
+    this(0, field);
+  }
+
+  A(int j, int field) {
+    this.j = j;
+      this.field = field;
+  }
+}
\ No newline at end of file
diff --git a/java/java-tests/testData/codeInsight/daemonCodeAnalyzer/quickFix/createConstructorParameterFromField/beforeChainedCalls.java b/java/java-tests/testData/codeInsight/daemonCodeAnalyzer/quickFix/createConstructorParameterFromField/beforeChainedCalls.java
new file mode 100644 (file)
index 0000000..5b1f931
--- /dev/null
@@ -0,0 +1,13 @@
+// "Add constructor parameter" "true"
+class A {
+  private final int <caret>field;
+  private int j;
+
+  A() {
+    this(0);
+  }
+
+  A(int j) {
+    this.j = j;
+  }
+}
\ No newline at end of file
index 87d91cc1a793197a8c99b8d4d390887dfe6f1d25..499e9a281a3251c94a1bc79fcc426093d8fe6b50 100644 (file)
@@ -91,7 +91,7 @@ public class SafeDeleteTest extends MultiFileTestCase {
     catch (BaseRefactoringProcessor.ConflictsInTestsException e) {
       String message = e.getMessage();
       assertTrue(message, message.startsWith("local variable <b><code>varName</code></b> has 1 usage that is not safe to delete.\n" +
-                                             "Of those 0 usages are in strings, comments, or non-Java files."));
+                                             "Of those 0 usages are in strings, comments, or non-code files."));
     }
   }
 
similarity index 74%
rename from plugins/consoleFolding/src/com/intellij/execution/ConsoleFoldingConfigurable.java
rename to platform/lang-impl/src/com/intellij/execution/console/ConsoleFoldingConfigurable.java
index 7e5a195e3fd37492038f404340861fca36f62d0c..826f64929dddbe17aecff0877ea7aeb56219cb72 100644 (file)
@@ -1,11 +1,12 @@
-package com.intellij.execution;
+package com.intellij.execution.console;
 
 import com.intellij.openapi.options.ConfigurationException;
 import com.intellij.openapi.options.SearchableConfigurable;
 import com.intellij.openapi.ui.Messages;
 import com.intellij.openapi.ui.VerticalFlowLayout;
-import com.intellij.ui.AddDeleteListPanel;
+import com.intellij.ui.AddEditDeleteListPanel;
 import org.jetbrains.annotations.Nls;
+import org.jetbrains.annotations.NotNull;
 import org.jetbrains.annotations.Nullable;
 
 import javax.swing.*;
@@ -20,11 +21,7 @@ public class ConsoleFoldingConfigurable implements SearchableConfigurable {
   private JPanel myMainComponent;
   private MyAddDeleteListPanel myPositivePanel;
   private MyAddDeleteListPanel myNegativePanel;
-  private final ConsoleFoldingSettings mySettings;
-
-  public ConsoleFoldingConfigurable(ConsoleFoldingSettings settings) {
-    mySettings = settings;
-  }
+  private final ConsoleFoldingSettings mySettings = ConsoleFoldingSettings.getSettings();
 
   public JComponent createComponent() {
     if (myMainComponent == null) {
@@ -37,6 +34,10 @@ public class ConsoleFoldingConfigurable implements SearchableConfigurable {
     return myMainComponent;
   }
 
+  public void addRule(@NotNull String rule) {
+    myPositivePanel.addRule(rule);
+  }
+
   public boolean isModified() {
     return !Arrays.asList(myNegativePanel.getListItems()).equals(mySettings.getNegativePatterns()) ||
            !Arrays.asList(myPositivePanel.getListItems()).equals(mySettings.getPositivePatterns());
@@ -59,6 +60,7 @@ public class ConsoleFoldingConfigurable implements SearchableConfigurable {
     myPositivePanel = null;
   }
 
+  @NotNull
   public String getId() {
     return getDisplayName();
   }
@@ -80,20 +82,23 @@ public class ConsoleFoldingConfigurable implements SearchableConfigurable {
     return null;
   }
 
-  private static class MyAddDeleteListPanel extends AddDeleteListPanel {
+  private static class MyAddDeleteListPanel extends AddEditDeleteListPanel<String> {
     private final String myQuery;
 
     public MyAddDeleteListPanel(String title, String query) {
-      super(title, new ArrayList());
+      super(title, new ArrayList<String>());
       myQuery = query;
     }
 
     @Override
     @Nullable
-    protected Object findItemToAdd() {
-      return Messages.showInputDialog(this, myQuery,
-                                      "Folding pattern",
-                                      Messages.getQuestionIcon(), "", null);
+    protected String findItemToAdd() {
+      return showEditDialog("");
+    }
+
+    @Nullable
+    private String showEditDialog(final String initialValue) {
+      return Messages.showInputDialog(this, myQuery, "Folding pattern", Messages.getQuestionIcon(), initialValue, null);
     }
 
     void resetFrom(List<String> patterns) {
@@ -109,5 +114,14 @@ public class ConsoleFoldingConfigurable implements SearchableConfigurable {
         patterns.add((String)o);
       }
     }
+
+    public void addRule(String rule) {
+      addElement(rule);
+    }
+
+    @Override
+    protected String editSelectedItem(String item) {
+      return showEditDialog(item);
+    }
   }
 }
similarity index 93%
rename from plugins/consoleFolding/src/com/intellij/execution/ConsoleFoldingSettings.java
rename to platform/lang-impl/src/com/intellij/execution/console/ConsoleFoldingSettings.java
index 43c1f8668f73bdb06fdabb72f633ee761efcf524..cc91e1a703ff51235657d3e378d3bdf47243b71c 100644 (file)
@@ -1,6 +1,7 @@
-package com.intellij.execution;
+package com.intellij.execution.console;
 
 import com.intellij.openapi.components.PersistentStateComponent;
+import com.intellij.openapi.components.ServiceManager;
 import com.intellij.openapi.components.State;
 import com.intellij.openapi.components.Storage;
 import com.intellij.util.containers.CollectionFactory;
@@ -24,6 +25,10 @@ public class ConsoleFoldingSettings implements PersistentStateComponent<ConsoleF
     }
   }
 
+  public static ConsoleFoldingSettings getSettings() {
+    return ServiceManager.getService(ConsoleFoldingSettings.class);
+  }
+
   public boolean shouldFoldLine(String line) {
     return containsAny(line, myPositivePatterns) && !containsAny(line, myNegativePatterns);
   }
similarity index 93%
rename from plugins/consoleFolding/src/com/intellij/execution/CustomizableConsoleFoldingBean.java
rename to platform/lang-impl/src/com/intellij/execution/console/CustomizableConsoleFoldingBean.java
index b9ccbdd102cebcd60fa1a09f7b61048f69521d0a..441dc98e6d5d5189bc503357f92044239bdcc65f 100644 (file)
@@ -1,4 +1,4 @@
-package com.intellij.execution;
+package com.intellij.execution.console;
 
 import com.intellij.openapi.extensions.AbstractExtensionPointBean;
 import com.intellij.openapi.extensions.ExtensionPointName;
diff --git a/platform/lang-impl/src/com/intellij/execution/console/FoldLinesLikeThis.java b/platform/lang-impl/src/com/intellij/execution/console/FoldLinesLikeThis.java
new file mode 100644 (file)
index 0000000..f5e7072
--- /dev/null
@@ -0,0 +1,79 @@
+package com.intellij.execution.console;
+
+import com.intellij.execution.impl.ConsoleViewImpl;
+import com.intellij.openapi.actionSystem.AnActionEvent;
+import com.intellij.openapi.application.ApplicationManager;
+import com.intellij.openapi.application.ModalityState;
+import com.intellij.openapi.editor.Document;
+import com.intellij.openapi.editor.Editor;
+import com.intellij.openapi.editor.SelectionModel;
+import com.intellij.openapi.options.ShowSettingsUtil;
+import com.intellij.openapi.project.DumbAwareAction;
+import com.intellij.openapi.util.text.StringUtil;
+import org.jetbrains.annotations.Nullable;
+
+/**
+ * @author peter
+ */
+public class FoldLinesLikeThis extends DumbAwareAction {
+  private final Editor myEditor;
+  private final ConsoleViewImpl myConsole;
+
+  public FoldLinesLikeThis(Editor editor, ConsoleViewImpl console) {
+    super("Fold lines like this");
+    myEditor = editor;
+    myConsole = console;
+  }
+
+  @Nullable
+  private String getSingleLineSelection() {
+    final SelectionModel model = myEditor.getSelectionModel();
+    final Document document = myEditor.getDocument();
+    if (!model.hasSelection()) {
+      final int offset = myEditor.getCaretModel().getOffset();
+      if (offset <= document.getTextLength()) {
+        final int lineNumber = document.getLineNumber(offset);
+        final String line = document.getText().substring(document.getLineStartOffset(lineNumber), document.getLineEndOffset(lineNumber)).trim();
+        if (StringUtil.isNotEmpty(line)) {
+          return line;
+        }
+      }
+
+      return null;
+    }
+    final int start = model.getSelectionStart();
+    final int end = model.getSelectionEnd();
+    if (document.getLineNumber(start) == document.getLineNumber(end)) {
+      final String selection = document.getText().substring(start, end).trim();
+      if (StringUtil.isNotEmpty(selection)) {
+        return selection;
+      }
+    }
+    return null;
+  }
+
+  @Override
+  public void update(AnActionEvent e) {
+    final boolean enabled = getSingleLineSelection() != null;
+    e.getPresentation().setEnabled(enabled);
+    e.getPresentation().setVisible(enabled);
+  }
+
+  @Override
+  public void actionPerformed(AnActionEvent e) {
+    final String selection = getSingleLineSelection();
+    assert selection != null;
+    ShowSettingsUtil.getInstance().editConfigurable(myEditor.getProject(), new ConsoleFoldingConfigurable() {
+      @Override
+      public void reset() {
+        super.reset();
+        ApplicationManager.getApplication().invokeLater(new Runnable() {
+          public void run() {
+            addRule(selection);
+          }
+        }, ModalityState.stateForComponent(createComponent()));
+      }
+    });
+    myConsole.foldImmediately();
+  }
+}
index ddf4bfa89a455cf10934c9e8f007f6f2b3842fb5..efefb4a811adaf649fd1e204db98748e3943d0c4 100644 (file)
@@ -42,6 +42,7 @@ import com.intellij.openapi.fileEditor.FileEditor;
 import com.intellij.openapi.fileEditor.FileEditorManager;
 import com.intellij.openapi.fileEditor.OpenFileDescriptor;
 import com.intellij.openapi.fileEditor.TextEditor;
+import com.intellij.openapi.fileEditor.ex.FileEditorManagerEx;
 import com.intellij.openapi.fileEditor.impl.FileDocumentManagerImpl;
 import com.intellij.openapi.fileEditor.impl.FileEditorManagerImpl;
 import com.intellij.openapi.fileTypes.FileType;
@@ -97,7 +98,7 @@ public class LanguageConsoleImpl implements Disposable, TypeSafeDataProvider {
   private final AtomicBoolean myForceScrollToEnd = new AtomicBoolean(false);
   private final MergingUpdateQueue myUpdateQueue;
   private Runnable myUiUpdateRunnable;
-  private boolean myEditorVisible = true;
+  private Editor myFullEditor;
 
   public LanguageConsoleImpl(final Project project, String title, final Language language) {
     myProject = project;
@@ -133,9 +134,14 @@ public class LanguageConsoleImpl implements Disposable, TypeSafeDataProvider {
     });
   }
 
-  public void setEditorVisible(boolean visible) {
-    if (myEditorVisible == visible) return;
-    if (visible) {
+  public void setFullEditorMode(boolean fullEditorMode) {
+    if (myFullEditor != null == fullEditorMode) return;
+    final VirtualFile virtualFile = myFile.getVirtualFile();
+    assert virtualFile != null;
+    final FileEditorManagerEx fileManager = FileEditorManagerEx.getInstanceEx(getProject());
+    if (!fullEditorMode) {
+      fileManager.closeFile(virtualFile);
+      myFullEditor = null;
       myPanel.removeAll();
       myPanel.add(myHistoryViewer.getComponent(), BorderLayout.NORTH);
       myPanel.add(myConsoleEditor.getComponent(), BorderLayout.CENTER);
@@ -143,8 +149,10 @@ public class LanguageConsoleImpl implements Disposable, TypeSafeDataProvider {
     else {
       myPanel.removeAll();
       myPanel.add(myHistoryViewer.getComponent(), BorderLayout.CENTER);
+      myFullEditor = fileManager.openTextEditor(new OpenFileDescriptor(getProject(), virtualFile, 0), true);
+      assert myFullEditor != null;
+      fileManager.getCurrentWindow().setFilePinned(virtualFile, true);
     }
-    myEditorVisible = visible;
   }
 
   private void setupComponents() {
@@ -279,6 +287,10 @@ public class LanguageConsoleImpl implements Disposable, TypeSafeDataProvider {
     printToHistory(text, attributes);
   }
 
+  public Editor getFullEditor() {
+    return myFullEditor;
+  }
+
   public void printToHistory(String text, final TextAttributes attributes) {
     text = StringUtil.convertLineSeparators(text);
     final boolean scrollToEnd = shouldScrollHistoryToEnd();
@@ -381,7 +393,7 @@ public class LanguageConsoleImpl implements Disposable, TypeSafeDataProvider {
   }
 
   private void updateSizes(boolean forceScrollToEnd) {
-    if (!myEditorVisible) return;
+    if (myFullEditor != null) return;
     final Dimension panelSize = myPanel.getSize();
     final Dimension historyContentSize = myHistoryViewer.getContentSize();
     final Dimension contentSize = myConsoleEditor.getContentSize();
@@ -512,7 +524,8 @@ public class LanguageConsoleImpl implements Disposable, TypeSafeDataProvider {
     if (prevFile != null) {
       final FileEditorManager editorManager = FileEditorManager.getInstance(getProject());
       final VirtualFile file = prevFile.getVirtualFile();
-      if (file != null && editorManager.isFileOpen(file)) {
+      if (file != null && myFullEditor != null) {
+        myFullEditor = null;
         final FileEditor prevEditor = editorManager.getSelectedEditor(file);
         final boolean focusEditor;
         final int offset;
@@ -526,7 +539,8 @@ public class LanguageConsoleImpl implements Disposable, TypeSafeDataProvider {
           offset = 0;
         }
         editorManager.closeFile(file);
-        editorManager.openTextEditor(new OpenFileDescriptor(getProject(), newVFile, offset), focusEditor);
+        myFullEditor = editorManager.openTextEditor(new OpenFileDescriptor(getProject(), newVFile, offset), focusEditor);
+        ((FileEditorManagerEx)editorManager).getCurrentWindow().setFilePinned(newVFile, true);        
       }
     }
   }
similarity index 85%
rename from plugins/consoleFolding/src/com/intellij/execution/SubstringConsoleFolding.java
rename to platform/lang-impl/src/com/intellij/execution/console/SubstringConsoleFolding.java
index bb23a8f9a75705d5cd1788b178bb13ecc2431fed..825a24763d1ed3b26313751726530cb2b9446c43 100644 (file)
@@ -1,4 +1,6 @@
-package com.intellij.execution;
+package com.intellij.execution.console;
+
+import com.intellij.execution.ConsoleFolding;
 
 import java.util.List;
 
index 842d81c2132391747204c948a20385168c329cfc..e4bd53ac8ae23bb44e0fa27bbdb7d6161985360c 100644 (file)
@@ -19,6 +19,7 @@ package com.intellij.execution.impl;
 import com.intellij.codeInsight.navigation.IncrementalSearchHandler;
 import com.intellij.execution.ConsoleFolding;
 import com.intellij.execution.ExecutionBundle;
+import com.intellij.execution.console.FoldLinesLikeThis;
 import com.intellij.execution.filters.*;
 import com.intellij.execution.process.ProcessHandler;
 import com.intellij.execution.ui.ConsoleView;
@@ -145,6 +146,28 @@ public class ConsoleViewImpl extends JPanel implements ConsoleView, ObservableCo
     myEditor.getCaretModel().moveToOffset(myEditor.getDocument().getTextLength());
   }
 
+  public void foldImmediately() {
+    ApplicationManager.getApplication().assertIsDispatchThread();
+    if (myFlushAlarm.getActiveRequestCount() > 0) {
+      myFlushAlarm.cancelAllRequests();
+      myFlushDeferredRunnable.run();
+    }
+    
+    myFoldingAlarm.cancelAllRequests();
+
+    myPendingFoldRegions.clear();
+    final FoldingModel model = myEditor.getFoldingModel();
+    model.runBatchFoldingOperation(new Runnable() {
+      public void run() {
+        for (FoldRegion region : model.getAllFoldRegions()) {
+          model.removeFoldRegion(region);
+        }
+      }
+    });
+
+    updateFoldings(0, myEditor.getDocument().getLineCount() - 1, true);
+  }
+
   private static class TokenInfo{
     private final ConsoleViewContentType contentType;
     private int startOffset;
@@ -762,6 +785,7 @@ public class ConsoleViewImpl extends JPanel implements ConsoleView, ObservableCo
     final DefaultActionGroup group = new DefaultActionGroup();
     group.add(new ClearAllAction());
     group.add(new CopyAction());
+    group.add(new FoldLinesLikeThis(myEditor, this));
     group.addSeparator();
     final ActionManager actionManager = ActionManager.getInstance();
     group.add(actionManager.getAction(DiffActions.COMPARE_WITH_CLIPBOARD));
@@ -830,10 +854,10 @@ public class ConsoleViewImpl extends JPanel implements ConsoleView, ObservableCo
     ApplicationManager.getApplication().assertIsDispatchThread();
     PsiDocumentManager.getInstance(myProject).commitAllDocuments();
     highlightHyperlinks(myEditor, myHyperlinks, myCustomFilter, myPredefinedMessageFilter, line1, endLine);
-    updateFoldings(line1, endLine);
+    updateFoldings(line1, endLine, false);
   }
 
-  private void updateFoldings(final int line1, final int endLine) {
+  private void updateFoldings(final int line1, final int endLine, boolean immediately) {
     final Document document = myEditor.getDocument();
     final CharSequence chars = document.getCharsSequence();
     final int startLine = Math.max(0, line1);
@@ -842,7 +866,7 @@ public class ConsoleViewImpl extends JPanel implements ConsoleView, ObservableCo
       addFolding(document, chars, line, toAdd);
     }
     if (!toAdd.isEmpty()) {
-      doUpdateFolding(toAdd);
+      doUpdateFolding(toAdd, immediately);
     }
   }
 
@@ -876,7 +900,7 @@ public class ConsoleViewImpl extends JPanel implements ConsoleView, ObservableCo
     }
   }
 
-  private void doUpdateFolding(final List<FoldRegion> toAdd) {
+  private void doUpdateFolding(final List<FoldRegion> toAdd, final boolean immediately) {
     assertIsDispatchThread();
     myPendingFoldRegions.addAll(toAdd);
 
@@ -885,7 +909,7 @@ public class ConsoleViewImpl extends JPanel implements ConsoleView, ObservableCo
       public void run() {
         assertIsDispatchThread();
         final FoldingModel model = myEditor.getFoldingModel();
-        model.runBatchFoldingOperationDoNotCollapseCaret(new Runnable() {
+        final Runnable operation = new Runnable() {
           public void run() {
             assertIsDispatchThread();
             for (FoldRegion region : myPendingFoldRegions) {
@@ -894,10 +918,15 @@ public class ConsoleViewImpl extends JPanel implements ConsoleView, ObservableCo
             }
             myPendingFoldRegions.clear();
           }
-        });
+        };
+        if (immediately) {
+          model.runBatchFoldingOperation(operation);
+        } else {
+          model.runBatchFoldingOperationDoNotCollapseCaret(operation);
+        }
       }
     };
-    if (myPendingFoldRegions.size() > 100) {
+    if (immediately || myPendingFoldRegions.size() > 100) {
       runnable.run();
     } else {
       myFoldingAlarm.addRequest(runnable, 50);
index d9909974b33f42c3ea116957b1f637f8426b7210..e00a6fe5cb993657155a583d9c328c4cd8ada482 100644 (file)
@@ -64,6 +64,8 @@ import java.awt.event.ActionListener;
 import java.awt.event.KeyEvent;
 import java.net.URL;
 import java.util.*;
+import java.util.regex.Matcher;
+import java.util.regex.Pattern;
 
 class RunConfigurable extends BaseConfigurable {
   private static final Icon ICON = IconLoader.getIcon("/general/configurableRunDebug.png");
@@ -646,8 +648,8 @@ class RunConfigurable extends BaseConfigurable {
     }
   }
 
-  private static String createUniqueName(DefaultMutableTreeNode typeNode) {
-    String str = ExecutionBundle.message("run.configuration.unnamed.name.prefix");
+  private static String createUniqueName(DefaultMutableTreeNode typeNode, @Nullable String baseName) {
+    String str = (baseName == null) ? ExecutionBundle.message("run.configuration.unnamed.name.prefix") : baseName;
     final ArrayList<String> currentNames = new ArrayList<String>();
     for (int i = 0; i < typeNode.getChildCount(); i++) {
       final Object userObject = ((DefaultMutableTreeNode)typeNode.getChildAt(i)).getUserObject();
@@ -659,9 +661,13 @@ class RunConfigurable extends BaseConfigurable {
       }
     }
     if (!currentNames.contains(str)) return str;
+
+    final Matcher matcher = Pattern.compile("(.*?)\\s*\\(\\d+\\)").matcher(str);
+    final String originalName = (matcher.matches()) ? matcher.group(1) : str;
     int i = 1;
     while (true) {
-      if (!currentNames.contains(str + i)) return str + i;
+      final String newName = String.format("%s (%d)", originalName, i);
+      if (!currentNames.contains(newName)) return newName;
       i++;
     }
   }
@@ -692,7 +698,7 @@ class RunConfigurable extends BaseConfigurable {
       sortTree(myRoot);
       ((DefaultTreeModel)myTree.getModel()).reload();
     }
-    final RunnerAndConfigurationSettings settings = getRunManager().createConfiguration(createUniqueName(node), factory);
+    final RunnerAndConfigurationSettings settings = getRunManager().createConfiguration(createUniqueName(node, null), factory);
     if (factory instanceof ConfigurationFactoryEx) {
       ((ConfigurationFactoryEx)factory).onNewConfigurationCreated(settings.getConfiguration());
     }
@@ -901,7 +907,7 @@ class RunConfigurable extends BaseConfigurable {
       try {
         final DefaultMutableTreeNode typeNode = getSelectedConfigurationTypeNode();
         final RunnerAndConfigurationSettings settings = configuration.getSnapshot();
-        final String copyName = createUniqueName(typeNode);
+        final String copyName = createUniqueName(typeNode, configuration.getNameText());
         settings.setName(copyName);
         final ConfigurationFactory factory = settings.getFactory();
         if (factory instanceof ConfigurationFactoryEx) {
index 8c6727ab1d1964ff0dafe6c4dd176135b7a4e5f2..e6d05a7677faffff99f797affa5e5d06a3b0f81b 100644 (file)
@@ -114,7 +114,7 @@ public class PsiElementRenameHandler implements RenameHandler {
     return true;//CommonRefactoringUtil.checkReadOnlyStatus(project, element);
   }
 
-  private static void showErrorMessage(Project project, Editor editor, String message) {
+  private static void showErrorMessage(Project project, @Nullable Editor editor, String message) {
     CommonRefactoringUtil.showErrorHint(project, editor, message, RefactoringBundle.message("rename.title"), null);
   }
 
index 05260ed2fb84c069d33763783a32b91dc986bb9f..7241c9d5423107e3dfbdffaa8ca5f3c8de132322 100644 (file)
@@ -67,6 +67,13 @@ public abstract class RenamePsiElementProcessor {
     return null;
   }
 
+  /**
+   * Builds the complete set of elements to be renamed during the refactoring.
+   *
+   * @param element the base element for the refactoring.
+   * @param newName the name into which the element is being renamed.
+   * @param allRenames the map (from element to its new name) into which all additional elements to be renamed should be stored.
+   */
   public void prepareRenaming(final PsiElement element, final String newName, final Map<PsiElement, String> allRenames) {
   }
 
@@ -127,8 +134,16 @@ public abstract class RenamePsiElementProcessor {
     }
   }
 
+  /**
+   * Returns the element to be renamed instead of the element on which the rename refactoring was invoked (for example, a super method
+   * of an inherited method).
+   *
+   * @param element the element on which the refactoring was invoked.
+   * @param editor the editor in which the refactoring was invoked.
+   * @return the element to rename, or null if the rename refactoring should be canceled.
+   */
   @Nullable
-  public PsiElement substituteElementToRename(final PsiElement element, Editor editor) {
+  public PsiElement substituteElementToRename(final PsiElement element, @Nullable Editor editor) {
     return element;
   }
 
index 6a639037024d01d6a7d78ab59f0e78a45de2eed1..05dba037c092e609ac99aa8f018f0d563c9f3e9f 100644 (file)
@@ -22,6 +22,7 @@ import com.intellij.execution.executors.DefaultRunExecutor;
 import com.intellij.execution.filters.Filter;
 import com.intellij.execution.filters.TextConsoleBuilder;
 import com.intellij.execution.filters.TextConsoleBuilderFactory;
+import com.intellij.execution.impl.ConsoleViewImpl;
 import com.intellij.execution.ui.ConsoleView;
 import com.intellij.execution.ui.ConsoleViewContentType;
 import com.intellij.execution.ui.ExecutionConsole;
@@ -61,13 +62,10 @@ public class AnalyzeStacktraceUtil {
   public static void printStacktrace(final ConsoleView consoleView, final String unscrambledTrace) {
     consoleView.clear();
     consoleView.print(unscrambledTrace+"\n", ConsoleViewContentType.ERROR_OUTPUT);
-    consoleView.performWhenNoDeferredOutput(
-      new Runnable() {
-        public void run() {
-          consoleView.scrollTo(0);
-        }
-      }
-    );
+    if (consoleView instanceof ConsoleViewImpl) {
+      ((ConsoleViewImpl)consoleView).foldImmediately();
+    }
+    consoleView.scrollTo(0);
   }
 
   @Nullable
index 8b917ca98508eb66394c68902d755dfaec02f111..04b353d7792d4635ab179e8154f4c9c50ff7614e 100644 (file)
@@ -140,7 +140,7 @@ public class LogicalPosition implements Comparable<LogicalPosition> {
   @NonNls
   public String toString() {
     return "LogicalPosition: line=" + line + " column=" + column + "; visual position aware=" + visualPositionAware
-           + " soft wrap: lines=" + (softWrapLinesBeforeCurrentLogicalLine + softWrapLinesOnCurrentLogicalLine) + " (before=" +
+           + "; soft wrap: lines=" + (softWrapLinesBeforeCurrentLogicalLine + softWrapLinesOnCurrentLogicalLine) + " (before=" +
            softWrapLinesBeforeCurrentLogicalLine + "; current=" + softWrapLinesOnCurrentLogicalLine
            + ") columns diff=" + softWrapColumnDiff + "; folding: lines = " + foldedLines + " columns diff=" + foldingColumnDiff;
   }
index 11aeb9b84797c624d36c632443768cd792624a80..448c066b5de5dde6031179e8bf7601232f4a99a8 100644 (file)
@@ -18,6 +18,7 @@ package com.intellij.ui;
 
 import com.intellij.CommonBundle;
 import com.intellij.ui.components.JBList;
+import org.jetbrains.annotations.Nullable;
 
 import javax.swing.*;
 import javax.swing.event.ListSelectionEvent;
@@ -33,7 +34,7 @@ import java.util.List;
  * @author anna
  * @since 5.1
  */
-public abstract class AddDeleteListPanel extends PanelWithButtons {
+public abstract class AddDeleteListPanel<T> extends PanelWithButtons {
   private final String myTitle;
   protected JButton myAddButton = new JButton(CommonBundle.message("button.add"));
   protected JButton myDeleteButton = new JButton(CommonBundle.message("button.delete"));
@@ -41,7 +42,7 @@ public abstract class AddDeleteListPanel extends PanelWithButtons {
   protected JList myList = new JBList(myListModel);
 
   public AddDeleteListPanel(final String title,
-                            final List initialList) {
+                            final List<T> initialList) {
     myTitle = title;
     for (Object o : initialList) {
       if (o != null) {
@@ -56,11 +57,7 @@ public abstract class AddDeleteListPanel extends PanelWithButtons {
     });
     myAddButton.addActionListener(new ActionListener(){
       public void actionPerformed(ActionEvent e) {
-        final Object itemToAdd = findItemToAdd();
-        if (itemToAdd != null){
-          myListModel.addElement(itemToAdd);
-          myList.setSelectedValue(itemToAdd, true);
-        }
+        addElement(findItemToAdd());
       }
     });
     myDeleteButton.addActionListener(new ActionListener() {
@@ -71,7 +68,15 @@ public abstract class AddDeleteListPanel extends PanelWithButtons {
     initPanel();
   }
 
-  protected abstract Object findItemToAdd();
+  protected void addElement(@Nullable T itemToAdd) {
+    if (itemToAdd != null){
+      myListModel.addElement(itemToAdd);
+      myList.setSelectedValue(itemToAdd, true);
+    }
+  }
+
+  @Nullable
+  protected abstract T findItemToAdd();
 
   public Object [] getListItems(){
     List<Object> items = new ArrayList<Object>();
diff --git a/platform/platform-api/src/com/intellij/ui/AddEditDeleteListPanel.java b/platform/platform-api/src/com/intellij/ui/AddEditDeleteListPanel.java
new file mode 100644 (file)
index 0000000..a7500f5
--- /dev/null
@@ -0,0 +1,54 @@
+package com.intellij.ui;
+
+import com.intellij.CommonBundle;
+import org.jetbrains.annotations.Nullable;
+
+import javax.swing.*;
+import java.awt.event.ActionEvent;
+import java.awt.event.ActionListener;
+import java.awt.event.MouseAdapter;
+import java.awt.event.MouseEvent;
+import java.util.List;
+
+/**
+ * @author peter
+ */
+public abstract class AddEditDeleteListPanel<T> extends AddDeleteListPanel<T> {
+  private JButton myEditButton;
+
+  public AddEditDeleteListPanel(final String title, final List<T> initialList) {
+    super(title, initialList);
+    myEditButton.addActionListener(new ActionListener() {
+      public void actionPerformed(ActionEvent e) {
+        editSelectedItem();
+      }
+    });
+    myList.addMouseListener(new MouseAdapter() {
+      public void mouseClicked(MouseEvent e) {
+        if (e.getClickCount() == 2 && e.getButton() == MouseEvent.BUTTON1) {
+          editSelectedItem();
+        }
+      }
+    });
+  }
+
+  @Override protected JButton[] createButtons() {
+    myEditButton = new JButton(CommonBundle.message("button.edit"));
+    return new JButton[] { myAddButton, myEditButton, myDeleteButton };
+  }
+
+  @Nullable
+  protected abstract T editSelectedItem(T item);
+
+  private void editSelectedItem() {
+    int index = myList.getSelectedIndex();
+    if (index >= 0) {
+      T newValue = editSelectedItem((T) myListModel.get(index));
+      if (newValue != null) {
+        myListModel.set(index, newValue);
+      }
+    }
+  }
+
+
+}
index 9a3dd2a4c89a7f03a201c545c51ef62bebee9089..d164f33a7464576a1fc002e6165ec0457acb4767 100644 (file)
@@ -112,6 +112,14 @@ public class ProjectUtil {
         virtualFile.isDirectory() && virtualFile.findChild(DIRECTORY_BASED_PROJECT_DIR) != null) {
       return openProject(path, projectToClose, forceOpenInNewFrame);
     }
+    if (virtualFile.isDirectory()) {
+      for (VirtualFile child : virtualFile.getChildren()) {
+        final String childPath = child.getPath();
+        if (childPath.endsWith(ProjectFileType.DOT_DEFAULT_EXTENSION)) {
+          return openProject(childPath, projectToClose, forceOpenInNewFrame);
+        }
+      }
+    }
     ProjectOpenProcessor provider = ProjectOpenProcessor.getImportProvider(virtualFile);
     if (provider != null) {
       return provider.doOpenProject(virtualFile, projectToClose, forceOpenInNewFrame);
index 8a4d17f3e6a2c126da1185f89ed2666426c1c4cf..281334ff0b52ac9ee2d8dd62441911366c67999e 100644 (file)
@@ -15,6 +15,9 @@
  */
 package com.intellij.openapi.editor.ex;
 
+import com.intellij.openapi.editor.TextChange;
+import org.jetbrains.annotations.NotNull;
+
 /**
  * Defines a contract for the callbacks for soft wraps management notifications (addition/removal).
  *
@@ -24,10 +27,9 @@ package com.intellij.openapi.editor.ex;
 public interface SoftWrapChangeListener {
 
   /**
-   * This method is assumed to be called every time number of soft wraps registered for the target logical line(s)
-   * is changed (soft wraps are added or remove).
+   * This method is assumed to be called every new soft wrap is registered.
    *
-   * @param changedLogicalLine   logical line for which number of registered soft wraps is changed
+   * @param softWrap   newly registered soft wrap
    */
-  void softWrapsStateChanged(int changedLogicalLine);
+  void softWrapAdded(@NotNull TextChange softWrap);
 }
index b6dc6a0970908fd112dafa87b0e42a74e12f9c57..e0e517dbbad9d4f46ba6dd5dfdabc66ba3bee572 100644 (file)
@@ -63,13 +63,20 @@ public class EditorUtil {
     List<? extends TextChange> softWraps = editor.getSoftWrapModel().getSoftWrapsForLine(resultLogLine);
     for (int i = 0; i < softWraps.size(); i++) {
       TextChange softWrap = softWraps.get(i);
+      CharSequence text = document.getCharsSequence();
+      if (visualLinesToSkip <= 0) {
+        int result = editor.offsetToVisualPosition(softWrap.getStart() - 1).column;
+        // We need to add width of the next symbol because current result column points to the last symbol before the soft wrap.
+        return  result + textWidthInColumns(editor, text, softWrap.getStart() - 1, softWrap.getStart(), result);
+      }
+
       int softWrapLineFeeds = StringUtil.countNewLines(softWrap.getText());
       if (softWrapLineFeeds < visualLinesToSkip) {
         visualLinesToSkip -= softWrapLineFeeds;
         continue;
       }
 
-      // Target visual column is the one just before line feed introduced by the next line feed.
+      // Target visual column is located on the last visual line of the current soft wrap.
       if (softWrapLineFeeds == visualLinesToSkip) {
         if (i >= softWraps.size() - 1) {
           return resVisEnd.column;
@@ -78,11 +85,11 @@ public class EditorUtil {
         TextChange nextSoftWrap = softWraps.get(i + 1);
         int result = editor.offsetToVisualPosition(nextSoftWrap.getStart() - 1).column;
 
-        // We need to add '1' because current column points to the last symbol before the next soft wrap;
-        result++;
+        // We need to add symbol width because current column points to the last symbol before the next soft wrap;
+        result += textWidthInColumns(editor, text, nextSoftWrap.getStart() - 1, nextSoftWrap.getStart(), result);
 
         int lineFeedIndex = StringUtil.indexOf(nextSoftWrap.getText(), '\n');
-        result += calcColumnNumber(editor, nextSoftWrap.getText(), 0, lineFeedIndex);
+        result += textWidthInColumns(editor, nextSoftWrap.getText(), 0, lineFeedIndex, result);
         return result;
       }
 
@@ -103,7 +110,8 @@ public class EditorUtil {
         }
       }
       int result = editor.offsetToVisualPosition(softWrap.getStart() - 1).column; // Column of the symbol just before the soft wrap
-      result++; // Because we calculated column of the symbol just before the soft wrap
+      // Target visual column is located on the last visual line of the current soft wrap.
+      result += textWidthInColumns(editor, text, softWrap.getStart() - 1, softWrap.getStart(), result);
       result += calcColumnNumber(editor, softWrap.getText(), softWrapStartOffset, softWrapEndOffset);
       return result;
     }
@@ -298,6 +306,36 @@ public class EditorUtil {
     return (nTabs + 1) * tabSize;
   }
 
+  /**
+   * Allows to answer how many columns are used to represent tabulation symbols that is started at the given visual column
+   * at the given editor.
+   *
+   * @param visualColumn    visual column where target tabulation symbol starts
+   * @param editor          target editor where tabulation symbol is to be represented
+   * @return                number of visual columns required to represent tabulation symbols that starts at the given column
+   */
+  public static int tabWidthInColumns(@NotNull Editor editor, int visualColumn) {
+    if (!editor.getSettings().isWhitespacesShown()) {
+      return 1;
+    }
+    int tabSize = getTabSize(editor);
+    int tabsNumber = visualColumn / tabSize;
+    return (tabsNumber + 1) * tabSize - visualColumn;
+  }
+
+  public static int textWidthInColumns(@NotNull Editor editor, CharSequence text, int start, int end, int columnOffset) {
+    int result = 0;
+    for (int i = start; i < end; i++) {
+      if (text.charAt(i) == '\t') {
+        result += tabWidthInColumns(editor, columnOffset + result);
+      }
+      else {
+        result++;
+      }
+    }
+    return result;
+  }
+
   /**
    * Allows to answer what width in pixels is required to draw fragment of the given char array from <code>[start; end)</code> interval
    * at the given editor.
@@ -312,9 +350,12 @@ public class EditorUtil {
    * @param start     offset within the given char array that points to target text start (inclusive)
    * @param end       offset within the given char array that points to target text end (exclusive)
    * @param fontType  font type to use for target text representation
+   * @param x         <code>'x'</code> coordinate that should be used as a starting point for target text representation.
+   *                  It's necessity is implied by the fact that IDEA editor may represent tabulation symbols in any range
+   *                  from <code>[1; tab size]</code> (check {@link #nextTabStop(int, Editor)} for more details)
    * @return          width in pixels required for target text representation
    */
-  public static int textWidth(@NotNull Editor editor, char[] text, int start, int end, int fontType) {
+  public static int textWidth(@NotNull Editor editor, char[] text, int start, int end, int fontType, int x) {
     int result = 0;
     for (int i = start; i < end; i++) {
       char c = text[i];
@@ -325,7 +366,7 @@ public class EditorUtil {
       }
 
       if (editor.getSettings().isWhitespacesShown()) {
-        result += getTabSize(editor) * getSpaceWidth(fontType, editor);
+        result += nextTabStop(x + result, editor) - result - x;
       }
       else {
         result += getSpaceWidth(fontType, editor);
index b935c71b4c0d6b49b253b6de6524d1207d7d732c..6a64a132032bba040d5aaa6a7f6b4d158c7099cb 100644 (file)
@@ -329,9 +329,10 @@ public final class EditorImpl extends UserDataHolderBase implements EditorEx, Hi
 
     mySoftWrapModel.addSoftWrapChangeListener(new SoftWrapChangeListener() {
       @Override
-      public void softWrapsStateChanged(int changedLogicalLine) {
+      public void softWrapAdded(@NotNull TextChange softWrap) {
         mySoftWrapsChanged = true;
-        mySizeContainer.update(changedLogicalLine, changedLogicalLine, changedLogicalLine);
+        int softWrapLine = myDocument.getLineNumber(softWrap.getStart());
+        mySizeContainer.update(softWrapLine, softWrapLine, softWrapLine);
       }
     });
 
@@ -1061,7 +1062,7 @@ public final class EditorImpl extends UserDataHolderBase implements EditorEx, Hi
           if (i >= 0) {
             start = i + 1;
           }
-          return new Point(EditorUtil.textWidth(this, softWrapChars, start, column + 1, Font.PLAIN), y);
+          return new Point(EditorUtil.textWidth(this, softWrapChars, start, column + 1, Font.PLAIN, 0), y);
         }
         break;
       }
@@ -1712,7 +1713,8 @@ public final class EditorImpl extends UserDataHolderBase implements EditorEx, Hi
       myGutterComponent.repaint(0, clip.y, myGutterComponent.getWidth(), myGutterComponent.getHeight() - clip.y);
 
       // Ask caret model to update visual caret position.
-      getCaretModel().moveToOffset(getCaretModel().getOffset());
+      //TODO den implement
+      //getCaretModel().moveToOffset(getCaretModel().getOffset());
     }
   }
 
@@ -4627,9 +4629,9 @@ public final class EditorImpl extends UserDataHolderBase implements EditorEx, Hi
     private       int    myMaxWidth = -1;
 
     public synchronized void reset() {
-      int visLinesCount = getDocument().getLineCount();
-      myLineWidths = new TIntArrayList(visLinesCount + 300);
-      int[] values = new int[visLinesCount];
+      int lineCount = getDocument().getLineCount();
+      myLineWidths = new TIntArrayList(lineCount + 300);
+      int[] values = new int[lineCount];
       Arrays.fill(values, -1);
       myLineWidths.add(values);
       myIsDirty = true;
index de8cbb67c426f24e47032449eed7c31dcfd9e944..f0fdd6eda82208f7ab8af554e05e040c2a0459ca 100644 (file)
@@ -43,7 +43,7 @@ import java.util.List;
  */
 public class SoftWrapModelImpl implements SoftWrapModelEx {
 
-  private final SoftWrapDataMapper myDataAdjuster;
+  private final SoftWrapDataMapper            myDataAdjuster;
   private final SoftWrapsStorage              myStorage;
   private final SoftWrapPainter               myPainter;
   private final SoftWrapApplianceManager      myApplianceManager;
@@ -54,7 +54,7 @@ public class SoftWrapModelImpl implements SoftWrapModelEx {
   private       int      myActive;
 
   public SoftWrapModelImpl(@NotNull EditorEx editor) {
-    this(editor, new SoftWrapsStorage(editor.getDocument()), new CompositeSoftWrapPainter(editor));
+    this(editor, new SoftWrapsStorage(), new CompositeSoftWrapPainter(editor));
   }
 
   public SoftWrapModelImpl(@NotNull final EditorEx editor, @NotNull SoftWrapsStorage storage, @NotNull SoftWrapPainter painter) {
@@ -278,7 +278,7 @@ public class SoftWrapModelImpl implements SoftWrapModelEx {
     }
 
     if (start < end) {
-      result += EditorUtil.textWidth(myEditor, chars, start, end, Font.PLAIN);
+      result += EditorUtil.textWidth(myEditor, chars, start, end, Font.PLAIN, 0);
     }
 
     return result;
index 63778df5f3f75275e9d4696b73efa281e4f82620..36b90dd4f12a0110bbb317794f9dc76808479eb5 100644 (file)
@@ -214,7 +214,7 @@ public class DefaultSoftWrapApplianceManager implements SoftWrapApplianceManager
     int x = myPainter.getMinDrawingWidth(SoftWrapDrawingType.BEFORE_SOFT_WRAP_LINE_FEED);
     int prevSoftWrapOffset = start;
     for (int i = start; i < end; i++) {
-      int symbolWidth = EditorUtil.textWidth(myEditor, text, i, i + 1, fontType);
+      int symbolWidth = EditorUtil.textWidth(myEditor, text, i, i + 1, fontType, x);
       if (x + symbolWidth >= myVisibleAreaWidth) {
         int offset = calculateSoftWrapOffset(text, i - 1, prevSoftWrapOffset, end);
         if (offset >= end || offset <= prevSoftWrapOffset) {
index 9281f6e5621ddb08eb2f4c6912139e094df0d9f8..96a840e27902e90d53b7485aa1cf2a87ca163ac2 100644 (file)
@@ -236,7 +236,7 @@ public class SoftWrapDataMapper {
 
     // Return eagerly if there are no soft wraps before the target offset on a line that contains it.
     if (max >= softWraps.size() || softWraps.get(max).getStart() > offset) {
-      int column = toVisualColumnSymbolsNumber(chars, targetLineStartOffset, offset);
+      int column = toVisualColumnSymbolsNumber(chars, targetLineStartOffset, offset, 0);
       LogicalPosition foldingUnawarePosition = new LogicalPosition(
         rawLineStartLogicalPosition.line, column, softWrapIntroducedLinesBefore, 0, 0, 0, 0
       );
@@ -280,8 +280,9 @@ public class SoftWrapDataMapper {
       }
 
       // Assuming that no line feed is contained before target offset on a line that holds it.
-      symbolsOnCurrentLogicalLine++;
-      symbolsOnCurrentVisibleLine++;
+      int columnsForSymbol = toVisualColumnSymbolsNumber(chars.charAt(i), symbolsOnCurrentVisibleLine);
+      symbolsOnCurrentLogicalLine += columnsForSymbol;
+      symbolsOnCurrentVisibleLine += columnsForSymbol;
     }
 
     LogicalPosition foldingUnawarePosition = new LogicalPosition(
@@ -304,8 +305,8 @@ public class SoftWrapDataMapper {
     int foldColumnDiff = 0;
     int softWrapColumnDiff = position.softWrapColumnDiff;
     Document document = myEditor.getDocument();
-    CharSequence text = document.getCharsSequence();
     int targetLine = document.getLineNumber(offset);
+    int lastFoldEndLogicalLine = -1;
     for (FoldRegion foldRegion : foldingModel.getAllFoldRegions()) {
       if (foldRegion.getStartOffset() >= offset) {
         break;
@@ -320,53 +321,52 @@ public class SoftWrapDataMapper {
       foldedLines += Math.min(targetLine, foldingEndLine) - foldingStartLine;
 
       // Process situation when target offset is located inside the folded region.
-      if (offset >= foldRegion.getStartOffset() && offset < foldRegion.getEndOffset()) {
-        // Our purpose is to define folding data in order to point to the visual folding start.
-        int visualFoldingStartColumn = calculateVisualFoldingStartColumn(foldRegion);
-        foldColumnDiff = visualFoldingStartColumn - position.column - softWrapColumnDiff;
-        break;
-      }
-
-      if (foldingEndLine != position.line) {
-        continue;
-      }
+      if (offset >= foldRegion.getStartOffset()) {
+        if (offset < foldRegion.getEndOffset()) {
+          // Our purpose is to define folding data in order to point to the visual folding start.
+          int visualFoldingStartColumn = calculateVisualFoldingStartColumn(foldRegion);
+          int diff = visualFoldingStartColumn - position.column - softWrapColumnDiff;
+          if (lastFoldEndLogicalLine == foldingStartLine) {
+            foldColumnDiff += diff;
+          }
+          else {
+            foldColumnDiff = diff;
+          }
+          return new LogicalPosition(
+            position.line, position.column, position.softWrapLinesBeforeCurrentLogicalLine, position.softWrapLinesOnCurrentLogicalLine,
+            softWrapColumnDiff, foldedLines, foldColumnDiff
+          );
+        }
 
-      // We know here that offset is at the same line where folding ends and is located after it. Hence, we process that as follows:
-      //   1. Check if the folding is single-line;
-      //   2.1. Process as follows if the folding is single-line:
-      //     3.1. Calculate column difference introduced by the folding;
-      //   2.2. Process as follows if the folding is multi-line:
-      //     3.2. Calculate visual column of folding start;
-      //     4.2. Calculate number of columns between target offset and folding end;
-      //     5.1. Calculate folding placeholder width in columns;
-      //     6.1. Calculate resulting offset visual column;
-      //     7.1. Calculate resulting folding column diff;
-
-      if (foldingStartLine == foldingEndLine) {
-        foldColumnDiff = toVisualColumnSymbolsNumber(foldRegion.getPlaceholderText())
-                         - toVisualColumnSymbolsNumber(text, foldRegion.getStartOffset(), foldRegion.getEndOffset());
-      }
-      else {
-        int endOffsetOfLineWithFoldingEnd = document.getLineEndOffset(foldingEndLine);
-        int columnsBetweenFoldingEndAndOffset = toVisualColumnSymbolsNumber(text, foldRegion.getEndOffset(), endOffsetOfLineWithFoldingEnd);
-        LogicalPosition foldingEndLineEndPosition = myEditor.offsetToLogicalPosition(endOffsetOfLineWithFoldingEnd);
-        if (position.column > foldingEndLineEndPosition.column) {
-          columnsBetweenFoldingEndAndOffset += position.column - foldingEndLineEndPosition.column;
+        int diff = getFoldColumnDiff(foldRegion);
+        if (lastFoldEndLogicalLine == foldingStartLine) {
+          foldColumnDiff += diff;
         }
-        int visualFoldingStartColumn = calculateVisualFoldingStartColumn(foldRegion);
-        int foldingPlaceholderWidth = toVisualColumnSymbolsNumber(foldRegion.getPlaceholderText());
-        int visual = columnsBetweenFoldingEndAndOffset + visualFoldingStartColumn + foldingPlaceholderWidth;
-        foldColumnDiff = visual - position.column;
-        break;
+        else {
+          foldColumnDiff = diff;
+        }
+        lastFoldEndLogicalLine = foldingEndLine;
       }
     }
 
+    if (lastFoldEndLogicalLine != position.line) {
+      foldColumnDiff = 0;
+    }
+
     return new LogicalPosition(
       position.line, position.column, position.softWrapLinesBeforeCurrentLogicalLine, position.softWrapLinesOnCurrentLogicalLine,
       softWrapColumnDiff, foldedLines, foldColumnDiff
     );
   }
 
+  private int getFoldColumnDiff(FoldRegion region) {
+    int visualFoldingStartColumn = calculateVisualFoldingStartColumn(region);
+    LogicalPosition foldEndLogical = myEditor.offsetToLogicalPosition(region.getEndOffset());
+    // Assuming that there is no tabulations symbols at placeholder text.
+    int foldingPlaceholderWidth = region.getPlaceholderText().length();
+    return visualFoldingStartColumn + foldingPlaceholderWidth - foldEndLogical.column;
+  }
+
   private int calculateVisualFoldingStartColumn(FoldRegion region) {
     Document document = myEditor.getDocument();
     int foldingStartOffset = region.getStartOffset();
@@ -380,6 +380,7 @@ public class SoftWrapDataMapper {
 
     List<TextChangeImpl> softWraps = myStorage.getSoftWraps();
     int startOffsetOfVisualLineWithFoldingStart = logicalLineStartOffset;
+    int softWrapOffsetInColumns = 0;
     for (; softWrapIndex < softWraps.size(); softWrapIndex++) {
       TextChange softWrap = softWraps.get(softWrapIndex);
       if (softWrap.getStart() >= foldingStartOffset) {
@@ -387,25 +388,46 @@ public class SoftWrapDataMapper {
       }
 
       startOffsetOfVisualLineWithFoldingStart = softWrap.getStart();
+      softWrapOffsetInColumns = numberOfSymbolsOnLastVisualLine(softWrap);
     }
 
     assert startOffsetOfVisualLineWithFoldingStart <= foldingStartOffset;
-    return toVisualColumnSymbolsNumber(document.getCharsSequence(), startOffsetOfVisualLineWithFoldingStart, foldingStartOffset);
+    return EditorUtil.textWidthInColumns(
+      myEditor, document.getCharsSequence(), startOffsetOfVisualLineWithFoldingStart, foldingStartOffset, softWrapOffsetInColumns
+    );
   }
 
-  private int toVisualColumnSymbolsNumber(char c) {
+  private static int numberOfSymbolsOnLastVisualLine(TextChange textChange) {
+    int result = 0;
+    for (int i = textChange.getText().length() - 1; i >= 0; i--) {
+      if (i == '\n') {
+        return result;
+      }
+      else {
+        result++;
+      }
+    }
+    return result;
+  }
+
+  private int toVisualColumnSymbolsNumber(char c, int offsetInColumns) {
     myCharBuffer.clear();
     myCharBuffer.put(c);
     myCharBuffer.flip();
-    return toVisualColumnSymbolsNumber(myCharBuffer, 0, 1);
-  }
-
-  private int toVisualColumnSymbolsNumber(CharSequence text) {
-    return toVisualColumnSymbolsNumber(text, 0, text.length());
+    return toVisualColumnSymbolsNumber(myCharBuffer, 0, 1, offsetInColumns);
   }
 
-  private int toVisualColumnSymbolsNumber(CharSequence text, int start, int end) {
-    return EditorUtil.calcColumnNumber(myEditor, text, start, end);
+  private int toVisualColumnSymbolsNumber(CharSequence text, int start, int end, int offsetInColumns) {
+    int result = 0;
+    for (int i = start; i < end; i++) {
+      if (text.charAt(i) == '\t') {
+        result += EditorUtil.tabWidthInColumns(myEditor, offsetInColumns + result);
+      }
+      else {
+        result++;
+      }
+    }
+    return result;
   }
 
   private class Context {
@@ -420,6 +442,12 @@ public class SoftWrapDataMapper {
     public int targetSoftWrapLines;
     public int symbolsOnCurrentLogicalLine;
     public int symbolsOnCurrentVisualLine;
+    /**
+     * There is a possible case that single tabulation symbols is shown in more than one visual column (IntelliJ editor is configured
+     * to show white spaces and tabulations and tab size is more than one). We keep track in number of such excessive visual
+     * columns used to show tabulations on a current visual line.
+     */
+    public int excessiveTabColumns;
 
     Context(LogicalPosition softWrapUnawareLogicalPosition, VisualPosition targetVisualPosition, int softWrapLinesBefore,
             int softWrapLinesOnCurrentLineBeforeTargetSoftWrap, int visualLineBeforeSoftWrapAppliance, FoldingModel foldingModel)
@@ -449,13 +477,14 @@ public class SoftWrapDataMapper {
         else {
           targetSoftWrapLines++;
           symbolsOnCurrentVisualLine = 0;
+          excessiveTabColumns = 0;
           return null;
         }
       }
 
       // Just update information about tracked symbols number if current visual line is too low.
       if (targetVisualPosition.line > visualLineBeforeSoftWrapAppliance + targetSoftWrapLines) {
-        symbolsOnCurrentVisualLine += toVisualColumnSymbolsNumber(c);
+        symbolsOnCurrentVisualLine += toVisualColumnSymbolsNumber(c, symbolsOnCurrentVisualLine);
         return null;
       }
 
@@ -467,7 +496,7 @@ public class SoftWrapDataMapper {
       }
 
       // Process non-line feed inside soft wrap.
-      symbolsOnCurrentVisualLine += toVisualColumnSymbolsNumber(c);
+      symbolsOnCurrentVisualLine++; // Don't expect tabulation to be used inside soft wrap text.
       if (targetVisualPosition.column <= symbolsOnCurrentVisualLine) {
         return build();
       }
@@ -493,8 +522,9 @@ public class SoftWrapDataMapper {
 
       // Just update information about tracked symbols number if current visual line is too low.
       if (targetVisualPosition.line > visualLineBeforeSoftWrapAppliance + targetSoftWrapLines) {
-        symbolsOnCurrentVisualLine += toVisualColumnSymbolsNumber(c);
-        symbolsOnCurrentLogicalLine++;
+        int columnsForSymbol = toVisualColumnSymbolsNumber(c, symbolsOnCurrentVisualLine);
+        symbolsOnCurrentVisualLine += columnsForSymbol;
+        symbolsOnCurrentLogicalLine += columnsForSymbol;
         return null;
       }
 
@@ -504,9 +534,14 @@ public class SoftWrapDataMapper {
         return build();
       }
 
-      symbolsOnCurrentVisualLine += toVisualColumnSymbolsNumber(c);
-      symbolsOnCurrentLogicalLine++;
-
+      int columnsForSymbol = toVisualColumnSymbolsNumber(c, symbolsOnCurrentVisualLine);
+      int diffInColumns = targetVisualPosition.column - symbolsOnCurrentVisualLine;
+      int incrementToUse = columnsForSymbol;
+      if (columnsForSymbol >= diffInColumns) {
+        incrementToUse = Math.min(columnsForSymbol, diffInColumns);
+      }
+      symbolsOnCurrentVisualLine += incrementToUse;
+      symbolsOnCurrentLogicalLine += incrementToUse;
 
       if (targetVisualPosition.column <= symbolsOnCurrentVisualLine) {
         return build();
index 5c325f5a72856ff5713f2563529ff509fd731c0e..627a5ed6ae4e4a69947ad03ca7bb3d7b6f938dea 100644 (file)
@@ -15,7 +15,6 @@
  */
 package com.intellij.openapi.editor.impl.softwrap;
 
-import com.intellij.openapi.editor.Document;
 import com.intellij.openapi.editor.ex.SoftWrapChangeListener;
 import org.jetbrains.annotations.NotNull;
 import org.jetbrains.annotations.Nullable;
@@ -40,12 +39,6 @@ public class SoftWrapsStorage {
   private final List<TextChangeImpl>        myWrapsView = Collections.unmodifiableList(myWraps);
   private final Set<SoftWrapChangeListener> myListeners = new CopyOnWriteArraySet<SoftWrapChangeListener>();
 
-  private final Document myDocument;
-
-  public SoftWrapsStorage(Document document) {
-    myDocument = document;
-  }
-
   /**
    * @return    <code>true</code> if there is at least one soft wrap registered at the current storage; <code>false</code> otherwise
    */
@@ -114,9 +107,8 @@ public class SoftWrapsStorage {
 
     i = -i - 1;
     myWraps.add(i, softWrap);
-    int changedLogicalLine = myDocument.getLineNumber(softWrap.getStart());
     for (SoftWrapChangeListener listener : myListeners) {
-      listener.softWrapsStateChanged(changedLogicalLine);
+      listener.softWrapAdded(softWrap);
     }
     return null;
   }
index 7b32bd5772ba94d7302c59a4808f27d2bccd5a90..ae59c2a7beff70a7b839f0bf7eca3c2b30de284e 100644 (file)
@@ -36,6 +36,7 @@ import com.intellij.openapi.project.Project;
 import com.intellij.openapi.util.Comparing;
 import com.intellij.openapi.util.Disposer;
 import com.intellij.openapi.util.Ref;
+import com.intellij.openapi.util.SystemInfo;
 import com.intellij.openapi.wm.CustomStatusBarWidget;
 import com.intellij.openapi.wm.StatusBar;
 import com.intellij.openapi.wm.StatusBarCustomComponentFactory;
@@ -50,7 +51,6 @@ import org.jetbrains.annotations.Nullable;
 import javax.swing.*;
 import java.awt.*;
 import java.util.ArrayList;
-import java.util.Arrays;
 import java.util.List;
 
 /**
@@ -259,6 +259,9 @@ public class IdeRootPane extends JRootPane implements UISettingsListener {
   void setMemoryIndicatorVisible(final boolean visible) {
     if (myMemoryWidget != null) {
       myMemoryWidget.setShowing(visible);
+      if (!SystemInfo.isMac) {
+        myStatusBar.setBorder(BorderFactory.createEmptyBorder(1, 4, 0, visible ? 0 : 2));
+      }
     }
   }
 
index 2176f7e9d10263c22a98c84c5c853b945d1da9d2..55506b23d6dc65d7d32b5dbce750ea292ae50034 100644 (file)
@@ -83,7 +83,7 @@ public class IdeStatusBarImpl extends JComponent implements StatusBarEx {
 
   public IdeStatusBarImpl() {
     setLayout(new BorderLayout());
-    setBorder(BorderFactory.createEmptyBorder(1, 4, 0, 2));
+    setBorder(BorderFactory.createEmptyBorder(1, 4, 0, SystemInfo.isMac ? 2 : 0));
 
     myInfoAndProgressPanel = new InfoAndProgressPanel();
     addWidget(myInfoAndProgressPanel, Position.CENTER);
index 846231437692f102a6c880f01dfe884c35f28914..14a87704e8658515c7c75e8dc714725b4a12a72f 100644 (file)
@@ -107,11 +107,11 @@ public class MemoryUsagePanel extends JButton implements CustomStatusBarWidget {
     final long maxMemory = runtime.maxMemory();
     final long freeMemory = maxMemory - runtime.totalMemory() + runtime.freeMemory();
 
-    final Insets insets = getInsets();
+    final Insets insets = SystemInfo.isMac ? getInsets() : new Insets(0, 0, 0, 0);
 
     final int totalBarLength = size.width - insets.left - insets.right - (SystemInfo.isMac ? 0 : 0);
     final int usedBarLength = totalBarLength - (int)(totalBarLength * freeMemory / maxMemory);
-    final int barHeight = HEIGHT; // size.height - insets.top - insets.bottom;
+    final int barHeight = SystemInfo.isMac ? HEIGHT : size.height - insets.top - insets.bottom;
     final Graphics2D g2 = (Graphics2D)g;
 
     final int yOffset = (size.height - barHeight) / 2;
@@ -129,12 +129,16 @@ public class MemoryUsagePanel extends JButton implements CustomStatusBarWidget {
       g2.setPaint(new GradientPaint(1, 1, new Color(175, 185, 202), 0, size.height - 2, new Color(126, 138, 168)));
       g2.fillRect(xOffset + 1, yOffset, usedBarLength, barHeight);
 
-      g2.setColor(new Color(194, 197, 203));
-      g2.drawLine(xOffset + 1, yOffset+1, xOffset + usedBarLength, yOffset+1);
+      if (SystemInfo.isMac) {
+        g2.setColor(new Color(194, 197, 203));
+        g2.drawLine(xOffset + 1, yOffset+1, xOffset + usedBarLength, yOffset+1);
+      }
     }
 
-    g2.setColor(new Color(110, 110, 110));
-    g2.drawRect(xOffset, yOffset, totalBarLength, barHeight - 1);
+    if (SystemInfo.isMac) {
+      g2.setColor(new Color(110, 110, 110));
+      g2.drawRect(xOffset, yOffset, totalBarLength, barHeight - 1);
+    }
 
     g.setFont(getFont());
     final long used = (maxMemory - freeMemory) / MEGABYTE;
@@ -151,7 +155,7 @@ public class MemoryUsagePanel extends JButton implements CustomStatusBarWidget {
 
   public final int getPreferredWidth() {
     final Insets insets = getInsets();
-    return getFontMetrics(UIUtil.getLabelFont().deriveFont(11.0f)).stringWidth(SAMPLE_STRING) + insets.left + insets.right + (SystemInfo.isMac ? 2 : 0);
+    return getFontMetrics(SystemInfo.isMac ? UIUtil.getLabelFont().deriveFont(11.0f) : UIUtil.getLabelFont()).stringWidth(SAMPLE_STRING) + insets.left + insets.right + (SystemInfo.isMac ? 2 : 0);
   }
 
   @Override
index 705f55786f1fbc7797fd98a2dc7291faae6373c9..016713112e2163d913f2f7ed20cba5765ceb13c1 100644 (file)
@@ -1,6 +1,5 @@
 package com.intellij.openapi.editor.impl.softwrap;
 
-import com.intellij.idea.Bombed;
 import com.intellij.mock.MockFoldRegion;
 import com.intellij.openapi.editor.*;
 import com.intellij.openapi.editor.ex.EditorEx;
@@ -9,16 +8,19 @@ import com.intellij.openapi.util.TextRange;
 import gnu.trove.TIntHashSet;
 import org.jetbrains.annotations.Nullable;
 import org.jmock.Expectations;
+import org.jmock.Mockery;
 import org.jmock.api.Invocation;
-import org.jmock.lib.action.CustomAction;
-import org.junit.Test;
-import org.junit.Before;
-import org.junit.After;
 import org.jmock.integration.junit4.JUnit4Mockery;
-import org.jmock.Mockery;
+import org.jmock.lib.action.CustomAction;
 import org.jmock.lib.legacy.ClassImposteriser;
+import org.junit.After;
+import org.junit.Before;
+import org.junit.Test;
 
-import java.util.*;
+import java.util.ArrayList;
+import java.util.Collections;
+import java.util.Comparator;
+import java.util.List;
 
 /**
  * @author Denis Zhdanov
@@ -38,7 +40,7 @@ public class SoftWrapDataMapperTest {
       // There is a possible case that multiple logical positions match to the same visual position (e.g. logical
       // positions for folded text match to the same visual position). We want to match to the logical position of
       // folding region start if we search by logical position from folded text.
-      if (o1.foldedSpace & o2.foldedSpace && logical1.column + logical1.foldingColumnDiff == logical2.foldingColumnDiff) {
+      if (o1.foldedSpace && o2.foldedSpace && logical1.column + logical1.foldingColumnDiff == logical2.foldingColumnDiff) {
         return o1.foldedSpace ? 1 : -1;
       }
       return logical1.column - logical2.column;
@@ -48,13 +50,19 @@ public class SoftWrapDataMapperTest {
   private static final Comparator<DataEntry> OFFSETS_COMPARATOR = new Comparator<DataEntry>() {
     @Override
     public int compare(DataEntry o1, DataEntry o2) {
+      if (o1.offset != o2.offset) {
+        return o1.offset - o2.offset;
+      }
       // There are numerous situations when multiple visual positions share the same offset (e.g. all soft wrap-introduced virtual
       // spaces share offset with the first document symbol after soft wrap or all virtual spaces after line end share the same offset
       // as the last line symbol). We want to ignore such positions during lookup by offset.
-      if (o1.offset == o2.offset && o1.virtualSpace ^ o2.virtualSpace) {
+      if (o1.virtualSpace ^ o2.virtualSpace) {
         return o1.virtualSpace ? 1 : -1;
       }
-      return o1.offset - o2.offset;
+      if (o1.insideTab ^ o2.insideTab) {
+        return o1.insideTab ? 1 : -1;
+      }
+      return 0;
     }
   };
 
@@ -86,7 +94,7 @@ public class SoftWrapDataMapperTest {
 
     myEditor = myMockery.mock(EditorEx.class);
     myDocument = myMockery.mock(Document.class);
-    myStorage = new SoftWrapsStorage(myDocument);
+    myStorage = new SoftWrapsStorage();
     myFoldingModel = myMockery.mock(FoldingModel.class);
     final EditorSettings settings = myMockery.mock(EditorSettings.class);
     final Project project = myMockery.mock(Project.class);
@@ -123,6 +131,7 @@ public class SoftWrapDataMapperTest {
       allowing(myEditor).getSettings();will(returnValue(settings));
       allowing(settings).isUseSoftWraps();will(returnValue(true));
       allowing(settings).getTabSize(project);will(returnValue(TAB_SIZE));
+      allowing(settings).isWhitespacesShown();will(returnValue(true));
       allowing(myEditor).getProject();will(returnValue(project));
 
       // Folding.
@@ -176,7 +185,6 @@ public class SoftWrapDataMapperTest {
     myMockery.assertIsSatisfied();
   }
 
-  @Bombed(day = 12, month = Calendar.JULY)
   @Test
   public void softWrapHasSymbolBeforeFirstLineFeed() {
     String document =
@@ -192,7 +200,6 @@ public class SoftWrapDataMapperTest {
     test(document);
   }
 
-  @Bombed(day = 12, month = Calendar.JULY)
   @Test
   public void multipleSoftWrappedLogicalLines() {
     String document =
@@ -212,7 +219,6 @@ public class SoftWrapDataMapperTest {
     test(document);
   }
 
-  @Bombed(day = 12, month = Calendar.JULY)
   @Test
   public void softWrapAndFoldedLines() {
     String document =
@@ -236,6 +242,70 @@ public class SoftWrapDataMapperTest {
     test(document);
   }
 
+  @Test
+  public void tabSymbolsBeforeSoftWrap() {
+    String document =
+      "class Test\t\t{<WRAP>\n" +
+      "    </WRAP> \n}";
+    test(document);
+  }
+
+  @Test
+  public void tabSymbolsAfterSoftWrap() {
+    String document =
+      "class Test {<WRAP>\n" +
+      "    </WRAP> \t\t\n" +
+      "}";
+    test(document);
+  }
+
+  @Test
+  public void multipleTabsAndSoftWraps() {
+    String document =
+      "public class \tTest {\n" +
+      "  public void foo(int[] data) {\n" +
+      "    bar(data[0], data[1],\t\t <WRAP>\n" +
+      "       </WRAP>data[2], data[3], <WRAP>\t \t\n" +
+      "       </WRAP>data[4], data[5],\t \t    \n" +
+      "       data[6], data[7],\t \t \n" +
+      "       data[8], data[9],\t \t <WRAP>\n" +
+      "       </WRAP>data[10], data[11], <WRAP>\t \t \n" +
+      "       </WRAP>data[12],\t \t data[13]);     \n" +
+      "  }\n" +
+      "  public void bar(int ... i) {\n" +
+      "  }\n" +
+      "}";
+    test(document);
+  }
+
+  @Test
+  public void tabBeforeFolding() {
+    String document =
+      "class Test\t \t <FOLD>{\n" +
+      "    </FOLD> \t\t\n" +
+      "}";
+    test(document);
+  }
+
+  @Test
+  public void multipleTabsAndFolding() {
+    String document =
+      "public class \tTest {\n" +
+      "  public void foo(int[] data) {\n" +
+      "    bar(data[0], data[1],\t\t <FOLD>\n" +
+      " \t \t      </FOLD>data[2], data[3], <FOLD>\t \t\n" +
+      " \t  \t      </FOLD>data[4], data[5],\t \t    \n" +
+      "       data[6], data[7],\t \t \n" +
+      "       data[8], data[9],\t \t <FOLD>\n" +
+      "\t   \t    </FOLD>data[10], data[11], <FOLD>\t \t \n" +
+      "  \t  \t     </FOLD>data[12],\t \t data[13]);     \n" +
+      "  }\n" +
+      "  public void bar(int ... i) {\n" +
+      "  }\n" +
+      "}";
+    test(document);
+  }
+
   private int getLineNumber(int offset) {
     int line = 0;
     for (TextRange range : myLineRanges) {
@@ -324,7 +394,7 @@ public class SoftWrapDataMapperTest {
       LogicalPosition actualLogicalByVisual = myAdjuster.adjustLogicalPosition(toSoftWrapUnawareLogicalByVisual(data), data.visual);
       // We don't want to perform the check for logical positions that correspond to the folded space because all of them relate to
       // the same logical position of the folding start.
-      if (!data.foldedSpace && !equals(data.logical, actualLogicalByVisual)) {
+      if (!data.foldedSpace && !data.insideTab && !equals(data.logical, actualLogicalByVisual)) {
         throw new AssertionError(
           String.format("Detected unmatched logical position by visual (%s). Expected: '%s', actual: '%s'. Calculation was performed "
                         + "against soft wrap-unaware logical: '%s'",
@@ -336,7 +406,7 @@ public class SoftWrapDataMapperTest {
       LogicalPosition actualLogicalByOffset = myAdjuster.offsetToLogicalPosition(data.offset);
       // We don't to perform the check for the data that points to soft wrap location here. The reason is that it shares offset
       // with the first document symbol after soft wrap, hence, examination always fails.
-      if (!data.virtualSpace && !equals(data.logical, actualLogicalByOffset)) {
+      if (!data.virtualSpace && !data.insideTab && !equals(data.logical, actualLogicalByOffset)) {
         throw new AssertionError(
           String.format("Detected unmatched logical position by offset. Expected: '%s', actual: '%s'. Calculation was performed "
                         + "against offset: '%d' and soft wrap-unaware logical: '%s'",
@@ -432,17 +502,19 @@ public class SoftWrapDataMapperTest {
     public final int             offset;
     public final boolean         foldedSpace;
     public final boolean         virtualSpace;
+    public final boolean         insideTab;
 
     DataEntry(VisualPosition visual, LogicalPosition logical, int offset, boolean foldedSpace) {
-      this(visual, logical, offset, foldedSpace, false);
+      this(visual, logical, offset, foldedSpace, false, false);
     }
 
-    DataEntry(VisualPosition visual, LogicalPosition logical, int offset, boolean foldedSpace, boolean virtualSpace) {
+    DataEntry(VisualPosition visual, LogicalPosition logical, int offset, boolean foldedSpace, boolean virtualSpace, boolean insideTab) {
       this.visual = visual;
       this.logical = logical;
       this.offset = offset;
       this.foldedSpace = foldedSpace;
       this.virtualSpace = virtualSpace;
+      this.insideTab = insideTab;
     }
 
     @Override
@@ -458,6 +530,7 @@ public class SoftWrapDataMapperTest {
 
     boolean insideSoftWrap;
     boolean insideFolding;
+    boolean insideTab;
     int     logicalLineStartOffset;
     int     logicalLine;
     int     logicalColumn;
@@ -473,6 +546,7 @@ public class SoftWrapDataMapperTest {
     int     foldingColumnDiff;
     int     foldedLines;
     int     offset;
+    int     tabAnchorColumn;
 
     public void onSoftWrapStart() {
       softWrapStartOffset = offset;
@@ -482,7 +556,6 @@ public class SoftWrapDataMapperTest {
     public void onSoftWrapEnd() {
       myStorage.storeOrReplace(new TextChangeImpl(mySoftWrapBuffer.toString(), softWrapStartOffset));
       mySoftWrapBuffer.setLength(0);
-      visualColumn++; // For the column reserved for soft wrap sign.
       insideSoftWrap = false;
     }
 
@@ -507,6 +580,29 @@ public class SoftWrapDataMapperTest {
         onNonSoftWrapSymbol(c);
         if (c == '\n') {
           foldedLines++;
+          offset++;
+          tabAnchorColumn = 0;
+        }
+        else if (c == '\t') {
+          int tabsNumber = tabAnchorColumn / TAB_SIZE;
+          int tabWidthInColumns = ((tabsNumber + 1) * TAB_SIZE) - tabAnchorColumn;
+
+          // There is a possible case that single tabulation symbols is shown in more than one visual column at IntelliJ editor.
+          // We store data entry only for the first tab column without 'inside tab' flag then.
+          insideTab = true;
+          for (int i =tabWidthInColumns - 1; i > 0; i--) {
+            logicalColumn++;
+            addData(false);
+          }
+          insideTab = false;
+
+          logicalColumn++;
+          offset++;
+          tabAnchorColumn += tabWidthInColumns;
+        } else {
+          logicalColumn++;
+          offset++;
+          tabAnchorColumn++;
         }
         foldingColumnDiff = foldingStartVisualColumn - logicalColumn;
         return;
@@ -525,12 +621,14 @@ public class SoftWrapDataMapperTest {
 
           visualLine++;
           softWrapLinesOnCurrentLogical++;
-          visualColumn = 0;
+          visualColumn = 1; // For the column reserved for soft wrap sign.
+          tabAnchorColumn = 1;
           softWrapSymbolsOnCurrentVisualLine = 0;
         }
         else {
           visualColumn++;
           softWrapSymbolsOnCurrentVisualLine++;
+          tabAnchorColumn++;
         }
         return;
       }
@@ -540,13 +638,37 @@ public class SoftWrapDataMapperTest {
       if (c == '\n') {
         visualLine++;
         visualColumn = 0;
+        tabAnchorColumn = 0;
         softWrapLinesBeforeCurrentLogical += softWrapLinesOnCurrentLogical;
         softWrapLinesOnCurrentLogical = 0;
         softWrapSymbolsOnCurrentVisualLine = 0;
         foldingColumnDiff = 0;
+        offset++;
+      }
+      else if (c == '\t') {
+        int tabsNumber = tabAnchorColumn / TAB_SIZE;
+        int tabWidthInColumns = ((tabsNumber + 1) * TAB_SIZE) - tabAnchorColumn;
+
+        // There is a possible case that single tabulation symbols is shown in more than one visual column at IntelliJ editor.
+        // We store data entry only for the first tab column without 'inside tab' flag then.
+        insideTab = true;
+        for (int i = tabWidthInColumns - 1; i > 0; i--) {
+          visualColumn++;
+          logicalColumn++;
+          addData(false);
+        }
+        insideTab = false;
+
+        visualColumn++;
+        logicalColumn++;
+        offset++;
+        tabAnchorColumn += tabWidthInColumns;
       }
       else {
         visualColumn++;
+        logicalColumn++;
+        offset++;
+        tabAnchorColumn++;
       }
     }
 
@@ -570,10 +692,6 @@ public class SoftWrapDataMapperTest {
         logicalLine++;
         logicalColumn = 0;
       }
-      else {
-        logicalColumn++;
-      }
-      offset++;
     }
 
     private void addData() {
@@ -582,7 +700,7 @@ public class SoftWrapDataMapperTest {
 
     private void addData(boolean virtualSpace) {
       myExpectedData.add(new DataEntry(
-        buildVisualPosition(), buildLogicalPosition(), offset, insideFolding && offset != foldingStartOffset, virtualSpace
+        buildVisualPosition(), buildLogicalPosition(), offset, insideFolding && offset != foldingStartOffset, virtualSpace, insideTab
       ));
     }
 
index 5c9199845e8967603cb0dd9eac00fab2948e77cd..6df93d8cb884e98d2d259c4d33e82d413ebd9688 100644 (file)
@@ -343,13 +343,13 @@ press.the.do.migrate.button=Press the "Do Migrate" button at the bottom of the s
 declaration.s.to.be.generified=Declaration(s) to be generified {0}
 occurences.to.be.migrated=Occurrences to be migrated {0}
 references.in.code=References in code {0}
-safe.delete.comment.occurences.header=Occurrences found in comments, strings and non-java files {0}. Those occurrences will not be changed
+safe.delete.comment.occurences.header=Occurrences found in comments, strings and non-code files {0}. Those occurrences will not be changed
 move.single.element.elements.header={0} to be moved to {1}
 references.in.code.to.0.1=References in code to {0} {1}
 move.classes.elements.header=Classes to be moved to {0}
 move.packages.elements.header=Packages to be moved to {0}
 references.found.in.code=References found in code
-comments.elements.header=Occurrences found in comments, strings and non-java files {0}
+comments.elements.header=Occurrences found in comments, strings and non-code files {0}
 move.files.elements.header=Files to be moved to {0}
 move.directories.elements.header=Directories to be moved to {0}
 make.static.description.label=Make {0} {1} static
@@ -548,7 +548,7 @@ replace.constructor.0.with.a.factory.method=Replace constructor {0} with a facto
 replace.default.constructor.of.0.with.a.factory.method=Replace default constructor of {0} with a factory method
 replace.constructor.with.factory.method=Replace constructor with factory method
 replace.default.constructor.with.factory.method=Replace default constructor with factory method
-occurrences.found.in.comments.strings.and.non.java.files=Occurrences found in comments, strings and non-java files
+occurrences.found.in.comments.strings.and.non.java.files=Occurrences found in comments, strings and non-code files
 0.referenced.in.1.will.not.be.accessible.in.module.2={0}, referenced in {1}, will not be accessible in module {2}
 0.referenced.in.1.will.not.be.accessible.from.module.2={0}, referenced in {1}, will not be accessible from module {2}
 0.referenced.in.1.will.not.be.accessible.from.production.of.module.2={0}, referenced in {1}, will not be accessible from the production sources of module {2}
@@ -658,8 +658,8 @@ directory.0.already.contains.a.file.named.1=Directory {0}\nalready contains a fi
 getter.and.setter.methods.found.for.the.field.0=Getter and setter methods found for the field {0}. \n{1} them as well?
 getter.method.found.for.the.field.0=Getter method found for the field {0}. \n{1} the getter as well?
 setter.method.found.for.the.field.0=Setter method found for the field {0}. \n{1} the setter as well?
-0.has.1.usages.in.comments.and.strings={0} has {1,choice,1#1 usage|2#{1,number} usages} in strings, comments, or non-Java files.
-0.has.1.usages.that.are.not.safe.to.delete.of.those.2={0} has {1,choice,1#1 usage that is|2#{1,number} usages that are} not safe to delete.\nOf those {2,choice,0#0 usages are|1#1 usage is|2#{2,number} usages are} in strings, comments, or non-Java files.
+0.has.1.usages.in.comments.and.strings={0} has {1,choice,1#1 usage|2#{1,number} usages} in strings, comments, or non-code files.
+0.has.1.usages.that.are.not.safe.to.delete.of.those.2={0} has {1,choice,1#1 usage that is|2#{1,number} usages that are} not safe to delete.\nOf those {2,choice,0#0 usages are|1#1 usage is|2#{2,number} usages are} in strings, comments, or non-code files.
 type.cook.drop.obsolete.casts=&Drop obsolete casts
 type.cook.preserve.raw.arrays=Preserve raw &arrays
 type.cook.leave.object.parameterized.types.raw=&Leave Object-parameterized types raw
index a57031b4547cf92c026d30d2512f51f7a497f470..c6322fd86420d824c2c76a2e38cb171af8882a0a 100644 (file)
   <extensionPoint name="typeIcon" beanClass="com.intellij.ide.TypeIconEP"/>
 
   <extensionPoint name="analyzeStacktraceFilter" interface="com.intellij.execution.filters.Filter" area="IDEA_PROJECT"/>
+
+  <extensionPoint name="stacktrace.fold" beanClass="com.intellij.execution.console.CustomizableConsoleFoldingBean"/>
+
 </extensionPoints>
index e92940282c5e7622bdc456ffdfe493e12ae18e0a..21b6000930ab95aea611124bf7986aca990b1baf 100644 (file)
   <completion.contributor language="any" implementationClass="com.intellij.codeInsight.completion.LegacyCompletionContributor" id="legacy" order="last"/>
   <completion.contributor language="any" implementationClass="com.intellij.codeInsight.completion.FilePathCompletionContributor" id="filePath" order="before javaClassName"/>
 
+  <applicationService serviceInterface="com.intellij.execution.console.ConsoleFoldingSettings" serviceImplementation="com.intellij.execution.console.ConsoleFoldingSettings"/>
+  <console.folding implementation="com.intellij.execution.console.SubstringConsoleFolding"/>
+  <applicationConfigurable implementation="com.intellij.execution.console.ConsoleFoldingConfigurable"/>
+
+  <stacktrace.fold substring="at java.lang.reflect.Method.invoke("/>
+  <stacktrace.fold substring="at java.lang.reflect.Constructor.newInstance("/>
+  <stacktrace.fold substring="at sun.reflect."/>
+
   <psi.referenceContributor implementation="com.intellij.psi.PsiReferenceContributorImpl"/>
 
   <lookup.charFilter implementation="com.intellij.codeInsight.completion.CompletionCharFilter" order="last" id="completion"/>
index 663312c242d0135239f37007780442e805d5b7c5..0ce237470883cf3aa581c75c8cb1d7ec82c3767e 100644 (file)
@@ -16,6 +16,7 @@
 package com.intellij.execution.testframework.ui;
 
 import com.intellij.execution.filters.HyperlinkInfo;
+import com.intellij.execution.impl.ConsoleViewImpl;
 import com.intellij.execution.testframework.*;
 import com.intellij.execution.ui.ConsoleView;
 import com.intellij.execution.ui.ConsoleViewContentType;
@@ -108,6 +109,9 @@ public class TestsOutputConsolePrinter implements Printer, Disposable {
     }
     myCurrentPrintable.printOn(this);
     scrollToBeginning();
+    if (myConsole instanceof ConsoleViewImpl) {
+      ((ConsoleViewImpl)myConsole).foldImmediately();
+    }
   }
 
   public void printHyperlink(final String text, final HyperlinkInfo info) {
index 99c8b10ffd4d24c669de28932b2408c792c6ab49..72747aca1c59538d19b7e855383d0eece1ebe24c 100644 (file)
@@ -148,8 +148,8 @@ public class ContainerUtil {
     return hashMap;
   }
 
-  public static <K, V> HashMap<K, Set<V>> classify(Iterator<V> iterator, Convertor<V, K> keyConvertor) {
-    HashMap<K, Set<V>> hashMap = new HashMap<K, Set<V>>();
+  public static <K, V> Map<K, Set<V>> classify(Iterator<V> iterator, Convertor<V, K> keyConvertor) {
+    Map<K, Set<V>> hashMap = new LinkedHashMap<K, Set<V>>();
     while (iterator.hasNext()) {
       V value = iterator.next();
       final K key = keyConvertor.convert(value);
index 6f426d0e7a1626966f9e99ad418be99f1ccab10c..fb11d803bc07a159a133fd117b570fda23f08327 100644 (file)
@@ -47,7 +47,7 @@ public abstract class WeaksTestCase extends TestCase {
     System.gc();
     try {
       List<Object> list = new ArrayList<Object>();
-      while (Runtime.getRuntime().freeMemory() > 10000) {
+      while (Runtime.getRuntime().freeMemory() > 100000) {
         list.add(new byte[1000]);
       }
 
index 5fb44b4e264717b7e6081f360a0fe2d9c3f6edb2..c94135fc6765b862c30bd4a73c03025d10ed9f41 100644 (file)
@@ -45,6 +45,7 @@ import com.intellij.openapi.util.Pair;
 import com.intellij.openapi.util.TextRange;
 import com.intellij.openapi.util.text.StringUtil;
 import com.intellij.psi.*;
+import com.intellij.psi.impl.source.PostprocessReformattingAspect;
 import com.intellij.psi.impl.source.resolve.FileContextUtil;
 import com.intellij.psi.impl.source.tree.injected.InjectedLanguageUtil;
 import com.intellij.psi.impl.source.tree.injected.Place;
@@ -292,7 +293,12 @@ public class QuickEditAction implements IntentionAction {
         new WriteCommandAction.Simple(myProject, origFile) {
           @Override
           protected void run() throws Throwable {
-            commitToOriginalInner();
+            PostprocessReformattingAspect.getInstance(myProject).disablePostprocessFormattingInside(new Runnable() {
+              @Override
+              public void run() {
+                commitToOriginalInner();
+              }
+            });
           }
         }.execute();
       }
@@ -307,11 +313,14 @@ public class QuickEditAction implements IntentionAction {
         .classify(myMarkers.entrySet().iterator(),
                   new Convertor<Map.Entry<SmartPsiElementPointer, Pair<RangeMarker, RangeMarker>>, PsiLanguageInjectionHost>() {
                     public PsiLanguageInjectionHost convert(final Map.Entry<SmartPsiElementPointer, Pair<RangeMarker, RangeMarker>> o) {
-                      return (PsiLanguageInjectionHost)o.getKey().getElement();
+                      final PsiElement element = o.getKey().getElement();
+                      return (PsiLanguageInjectionHost)element;
                     }
                   });
       PsiDocumentManager.getInstance(myProject).commitDocument(myOrigDocument);
+      int localInsideFileCursor = 0;
       for (PsiLanguageInjectionHost host : map.keySet()) {
+        if (host == null) continue;
         final String hostText = host.getText();
         TextRange insideHost = null;
         final StringBuilder sb = new StringBuilder();
@@ -321,12 +330,13 @@ public class QuickEditAction implements IntentionAction {
           final TextRange localInsideHost =
             new TextRange(origMarker.getStartOffset() - hostOffset, origMarker.getEndOffset() - hostOffset);
           final RangeMarker rangeMarker = entry.getValue().second;
-          final TextRange localInsideFile = new TextRange(rangeMarker.getStartOffset(), rangeMarker.getEndOffset());
+          final TextRange localInsideFile = new TextRange(Math.max(localInsideFileCursor, rangeMarker.getStartOffset()), rangeMarker.getEndOffset());
           if (insideHost != null) {
+            //append unchanged inter-markers fragment
             sb.append(hostText.substring(insideHost.getEndOffset(), localInsideHost.getStartOffset()));
           }
-          sb.append(localInsideFile.getEndOffset() <= text.length()? localInsideFile.substring(text) : "");
-
+          sb.append(localInsideFile.getEndOffset() <= text.length() && !localInsideFile.isEmpty()? localInsideFile.substring(text) : "");
+          localInsideFileCursor = localInsideFile.getEndOffset();
           insideHost = insideHost == null ? localInsideHost : insideHost.union(localInsideHost);
         }
         assert insideHost != null;
index 378b10489558712bb65ab018e511b60fb4a8a1c2..87b73448c419c0b927d9e3b39b2d26d34166a8dd 100644 (file)
@@ -145,7 +145,7 @@ public class XmlAttributeInjection extends AbstractTagInjection {
     if (StringUtil.isNotEmpty(name)) appendStringPattern(result, ".withLocalName(", name, ")");
     if (StringUtil.isNotEmpty(namespace)) appendStringPattern(result, ".withNamespace(", namespace, ")");
     if (StringUtil.isNotEmpty(injection.getTagName()) || StringUtil.isNotEmpty(injection.getTagNamespace())) {
-      result.append(".inside(").append(XmlTagInjection.getPatternString(injection)).append(")");
+      result.append(".withParent(").append(XmlTagInjection.getPatternString(injection)).append(")");
     }
     return result.toString();
   }
index a965c7a303f0ccbcdb43e2bf105ddbe9e64038cb..f411b6c80a7cb512cf94219fe96c41e923f4cdde 100644 (file)
@@ -7,16 +7,16 @@
   </injection>
   <injection language="XPath" injector-id="xml">
     <display-name>JAXB attribute node</display-name>
-    <place><![CDATA[xmlAttribute().withLocalName(string().equalTo("node")).inside(xmlTag().withLocalName(string().equalTo("bindings")).withNamespace(string().equalTo("http://java.sun.com/xml/ns/jaxb")))]]></place>
+    <place><![CDATA[xmlAttribute().withLocalName(string().equalTo("node")).withParent(xmlTag().withLocalName(string().equalTo("bindings")).withNamespace(string().equalTo("http://java.sun.com/xml/ns/jaxb")))]]></place>
   </injection>
   <injection language="JavaScript" injector-id="xml">
     <display-name>*/@href</display-name>
     <value-pattern>^javascript:(.+)</value-pattern>
-    <place><![CDATA[xmlAttribute().withLocalName(string().equalTo("href")).inside(xmlTag().withNamespace(string().equalTo("http://www.w3.org/1999/xhtml")))]]></place>
+    <place><![CDATA[xmlAttribute().withLocalName(string().equalTo("href")).withParent(xmlTag().withNamespace(string().equalTo("http://www.w3.org/1999/xhtml")))]]></place>
   </injection>
   <injection language="JavaScript" injector-id="xml">
     <display-name>*/@on.*</display-name>
-    <place><![CDATA[xmlAttribute().withLocalName(string().matches("on.*")).inside(xmlTag().withNamespace(string().equalTo("http://www.w3.org/1999/xhtml")))]]></place>
+    <place><![CDATA[xmlAttribute().withLocalName(string().matches("on.*")).withParent(xmlTag().withNamespace(string().equalTo("http://www.w3.org/1999/xhtml")))]]></place>
   </injection>
   <injection language="CSS" injector-id="xml">
     <display-name>*/@style</display-name>
diff --git a/plugins/consoleFolding/consoleFolding.iml b/plugins/consoleFolding/consoleFolding.iml
deleted file mode 100644 (file)
index 2d8ecbf..0000000
+++ /dev/null
@@ -1,14 +0,0 @@
-<?xml version="1.0" encoding="UTF-8"?>
-<module type="JAVA_MODULE" version="4">
-  <component name="NewModuleRootManager" inherit-compiler-output="true">
-    <exclude-output />
-    <content url="file://$MODULE_DIR$">
-      <sourceFolder url="file://$MODULE_DIR$/src" isTestSource="false" />
-    </content>
-    <orderEntry type="inheritedJdk" />
-    <orderEntry type="sourceFolder" forTests="false" />
-    <orderEntry type="module" module-name="platform-api" />
-    <orderEntry type="module" module-name="lang-impl" />
-  </component>
-</module>
-
diff --git a/plugins/consoleFolding/src/META-INF/plugin.xml b/plugins/consoleFolding/src/META-INF/plugin.xml
deleted file mode 100644 (file)
index 581ba8a..0000000
+++ /dev/null
@@ -1,33 +0,0 @@
-<idea-plugin url="http://www.jetbrains.net/confluence/display/GRVY/Groovy+Home">
-  <id>com.intellij.console.folding</id>
-  <name>Console Folding</name>
-  <description>Adds a customization for folding non-interesting lines in console</description>
-  <version>0.1</version>
-  <idea-version since-build="95.28"/>
-  <vendor logo="/images/pluginIcon.png" url="http://www.jetbrains.com">JetBrains Inc.</vendor>
-
-  <extensionPoints>
-    <extensionPoint qualifiedName="com.intellij.stacktrace.fold" beanClass="com.intellij.execution.CustomizableConsoleFoldingBean"/>
-  </extensionPoints>
-
-  <extensions defaultExtensionNs="com.intellij">
-    <applicationService serviceInterface="com.intellij.execution.ConsoleFoldingSettings" serviceImplementation="com.intellij.execution.ConsoleFoldingSettings"/>
-    <console.folding implementation="com.intellij.execution.SubstringConsoleFolding"/>
-    <applicationConfigurable implementation="com.intellij.execution.ConsoleFoldingConfigurable"/>
-
-    <!--<stacktrace.fold substring="at org.codehaus.groovy."/>
-    <stacktrace.fold substring="at groovy."/>
-    <stacktrace.fold substring="at groovy."/>
-    <stacktrace.fold substring="at org.codehaus.groovy.runtime.DefaultGroovyMethods." negate="true"/>
-    <stacktrace.fold substring="at org.codehaus.groovy.vmplugin.v5.PluginDefaultGroovyMethods." negate="true"/>
-    <stacktrace.fold substring="at org.codehaus.groovy.runtime.DefaultGroovyMethodsSupport." negate="true"/>
-
-    <stacktrace.fold substring="at java.lang.reflect.Method.invoke("/>
-    <stacktrace.fold substring="at java.lang.reflect.Constructor.newInstance("/>
-    <stacktrace.fold substring="at sun.reflect."/>-->
-
-    <stacktrace.fold substring="at org.junit.internal.runners."/>
-
-  </extensions>
-
-</idea-plugin>
diff --git a/plugins/groovy/grape/grape-rt.iml b/plugins/groovy/grape/grape-rt.iml
deleted file mode 100644 (file)
index 9dbb852..0000000
+++ /dev/null
@@ -1,13 +0,0 @@
-<?xml version="1.0" encoding="UTF-8"?>
-<module type="JAVA_MODULE" version="4">
-  <component name="NewModuleRootManager" LANGUAGE_LEVEL="JDK_1_4" inherit-compiler-output="true">
-    <exclude-output />
-    <content url="file://$MODULE_DIR$/rt">
-      <sourceFolder url="file://$MODULE_DIR$/rt/src" isTestSource="false" />
-    </content>
-    <orderEntry type="inheritedJdk" />
-    <orderEntry type="sourceFolder" forTests="false" />
-    <orderEntry type="library" name="Groovy" level="project" />
-  </component>
-</module>
-
diff --git a/plugins/groovy/grape/grape.iml b/plugins/groovy/grape/grape.iml
deleted file mode 100644 (file)
index 73ea14e..0000000
+++ /dev/null
@@ -1,18 +0,0 @@
-<?xml version="1.0" encoding="UTF-8"?>
-<module type="JAVA_MODULE" version="4">
-  <component name="NewModuleRootManager" inherit-compiler-output="true">
-    <exclude-output />
-    <content url="file://$MODULE_DIR$">
-      <sourceFolder url="file://$MODULE_DIR$/src" isTestSource="false" />
-      <sourceFolder url="file://$MODULE_DIR$/resources" isTestSource="false" />
-    </content>
-    <orderEntry type="inheritedJdk" />
-    <orderEntry type="sourceFolder" forTests="false" />
-    <orderEntry type="module" module-name="lang-api" />
-    <orderEntry type="module" module-name="jetgroovy" />
-    <orderEntry type="module" module-name="openapi" />
-    <orderEntry type="module" module-name="execution-openapi" />
-    <orderEntry type="module" module-name="grape-rt" />
-  </component>
-</module>
-
diff --git a/plugins/groovy/grape/src/META-INF/plugin.xml b/plugins/groovy/grape/src/META-INF/plugin.xml
deleted file mode 100644 (file)
index 642560f..0000000
+++ /dev/null
@@ -1,18 +0,0 @@
-<idea-plugin url="http://www.jetbrains.net/confluence/display/GRVY/Groovy+Home">
-  <id>org.intellij.groovy.grape</id>
-  <name>Groovy Grape support</name>
-  <description>An intention on @Grab annotations to download the needed dependencies</description>
-  <version>0.4</version>
-  <idea-version since-build="95.28"/>
-  <vendor logo="/org/jetbrains/plugins/groovy/images/groovy_16x16.png" url="http://www.jetbrains.com">JetBrains Inc.</vendor>
-  <depends>org.intellij.groovy</depends>
-
-  <extensions defaultExtensionNs="com.intellij">
-    <intentionAction>
-      <bundleName>org.jetbrains.plugins.groovy.intentions.GroovyIntentionsBundle</bundleName>
-      <categoryKey>intention.category.groovy</categoryKey>
-      <className>org.jetbrains.plugins.groovy.grape.GrabDependencies</className>
-    </intentionAction>
-  </extensions>
-
-</idea-plugin>
diff --git a/plugins/groovy/groovypp/groovypp.iml b/plugins/groovy/groovypp/groovypp.iml
deleted file mode 100644 (file)
index c805762..0000000
+++ /dev/null
@@ -1,17 +0,0 @@
-<?xml version="1.0" encoding="UTF-8"?>
-<module type="JAVA_MODULE" version="4">
-  <component name="NewModuleRootManager" inherit-compiler-output="true">
-    <exclude-output />
-    <content url="file://$MODULE_DIR$">
-      <sourceFolder url="file://$MODULE_DIR$/src" isTestSource="false" />
-    </content>
-    <orderEntry type="inheritedJdk" />
-    <orderEntry type="sourceFolder" forTests="false" />
-    <orderEntry type="module" module-name="jetgroovy" />
-    <orderEntry type="module" module-name="lang-api" />
-    <orderEntry type="module" module-name="idea-ui" />
-    <orderEntry type="module" module-name="openapi" />
-    <orderEntry type="module" module-name="java-impl" />
-  </component>
-</module>
-
diff --git a/plugins/groovy/groovypp/src/META-INF/plugin.xml b/plugins/groovy/groovypp/src/META-INF/plugin.xml
deleted file mode 100644 (file)
index 4c451bf..0000000
+++ /dev/null
@@ -1,25 +0,0 @@
-<idea-plugin url="http://www.jetbrains.net/confluence/display/GRVY/Groovy+Home">
-  <id>org.intellij.groovy.gpp</id>
-  <name>Groovy++ Support</name>
-  <description>Adds code assistance for the Groovy++ features</description>
-  <version>0.1</version>
-  <idea-version since-build="95.90" until-build="96.239"/>
-  <vendor logo="/org/jetbrains/plugins/groovy/images/groovy_16x16.png" url="http://www.jetbrains.com">JetBrains Inc.</vendor>
-  <depends>org.intellij.groovy</depends>
-
-  <extensions defaultExtensionNs="org.intellij.groovy">
-    <libraryManager implementation="org.jetbrains.plugins.groovy.gpp.GppLibraryManager" order="first"/>
-    <typeConverter implementation="org.jetbrains.plugins.groovy.gpp.GppTypeConverter"/>
-    <expectedTypesContributor implementation="org.jetbrains.plugins.groovy.gpp.GppExpectedTypesContributor"/>
-    <variableEnhancer implementation="org.jetbrains.plugins.groovy.gpp.GppClosureParameterTypeProvider"/>
-    <classSubstitutor implementation="org.jetbrains.plugins.groovy.gpp.GppClassSubstitutor"/>
-    <nonCodeProcessor implementation="org.jetbrains.plugins.groovy.gpp.GppStdLibSupport"/>
-    <positionManagerDelegate implementation="org.jetbrains.plugins.groovy.gpp.GppPositionManager"/>
-  </extensions>
-
-  <extensions defaultExtensionNs="com.intellij">
-    <psi.referenceContributor implementation="org.jetbrains.plugins.groovy.gpp.GppReferenceContributor"/>
-  </extensions>
-
-
-</idea-plugin>
diff --git a/plugins/groovy/hotswap/groovy-hotswap.iml b/plugins/groovy/hotswap/groovy-hotswap.iml
deleted file mode 100644 (file)
index f19c4c5..0000000
+++ /dev/null
@@ -1,22 +0,0 @@
-<?xml version="1.0" encoding="UTF-8"?>
-<module type="JAVA_MODULE" version="4">
-  <component name="NewModuleRootManager" inherit-compiler-output="true">
-    <exclude-output />
-    <content url="file://$MODULE_DIR$">
-      <sourceFolder url="file://$MODULE_DIR$/pluginSrc" isTestSource="false" />
-    </content>
-    <orderEntry type="inheritedJdk" />
-    <orderEntry type="sourceFolder" forTests="false" />
-    <orderEntry type="library" name="asm" level="project" />
-    <orderEntry type="module" module-name="debugger-impl" />
-    <orderEntry type="module" module-name="annotations" />
-    <orderEntry type="module" module-name="lang-api" />
-    <orderEntry type="module" module-name="execution-openapi" />
-    <orderEntry type="module" module-name="platform-impl" />
-    <orderEntry type="module" module-name="jetgroovy" />
-    <orderEntry type="module" module-name="lang-impl" />
-    <orderEntry type="module" module-name="execution-impl" />
-    <orderEntry type="module" module-name="openapi" />
-  </component>
-</module>
-
diff --git a/plugins/groovy/hotswap/pluginSrc/META-INF/plugin.xml b/plugins/groovy/hotswap/pluginSrc/META-INF/plugin.xml
deleted file mode 100644 (file)
index 973a4b1..0000000
+++ /dev/null
@@ -1,14 +0,0 @@
-<idea-plugin url="http://www.jetbrains.net/confluence/display/GRVY/Groovy+Home">
-  <id>org.intellij.groovy.hotswap</id>
-  <name>Groovy HotSwap</name>
-  <description>Enables HotSwap functionality in Groovy classes</description>
-  <version>0.6</version>
-  <idea-version since-build="94.632"/>
-  <vendor logo="/org/jetbrains/plugins/groovy/images/groovy_16x16.png" url="http://www.jetbrains.com">JetBrains Inc.</vendor>
-  <depends>org.intellij.groovy</depends>
-
-  <extensions defaultExtensionNs="com.intellij">
-    <java.programPatcher implementation="org.jetbrains.plugins.groovy.debugger.GroovyHotSwapper"/>
-  </extensions>
-
-</idea-plugin>
diff --git a/plugins/groovy/jetgroovy-tests.iml b/plugins/groovy/jetgroovy-tests.iml
deleted file mode 100644 (file)
index da38fa9..0000000
+++ /dev/null
@@ -1,31 +0,0 @@
-<?xml version="1.0" encoding="UTF-8"?>
-<module relativePaths="true" type="JAVA_MODULE" version="4">
-  <component name="NewModuleRootManager" inherit-compiler-output="true">
-    <exclude-output />
-    <content url="file://$MODULE_DIR$/test">
-      <sourceFolder url="file://$MODULE_DIR$/test" isTestSource="true" />
-    </content>
-    <content url="file://$MODULE_DIR$/testdata" />
-    <orderEntry type="inheritedJdk" />
-    <orderEntry type="sourceFolder" forTests="false" />
-    <orderEntry type="module" module-name="openapi" />
-    <orderEntry type="module" module-name="xml" />
-    <orderEntry type="module" module-name="debugger-openapi" />
-    <orderEntry type="module" module-name="groovy-rt" />
-    <orderEntry type="module" module-name="compiler-impl" />
-    <orderEntry type="module" module-name="debugger-impl" />
-    <orderEntry type="library" name="JUnit4" level="project" />
-    <orderEntry type="module" module-name="lang-api" />
-    <orderEntry type="module" module-name="properties" />
-    <orderEntry type="module" module-name="execution-impl" />
-    <orderEntry type="module" module-name="jetgroovy" />
-    <orderEntry type="module" module-name="testFramework-java" />
-    <orderEntry type="library" name="Groovy" level="project" />
-    <orderEntry type="module" module-name="execution-openapi" />
-    <orderEntry type="module" module-name="java-impl" />
-    <orderEntry type="module" module-name="IntelliLang-java" />
-    <orderEntry type="module" module-name="IntelliLang-xml" />
-    <orderEntry type="module" module-name="groovypp" />
-  </component>
-</module>
-
index 78f65558faccad25e38bf0f0285c25cf529209f4..3b210de157c4fa073c2ef54bbd5b8ac5caf825c9 100644 (file)
@@ -5,6 +5,7 @@
     <content url="file://$MODULE_DIR$">
       <sourceFolder url="file://$MODULE_DIR$/resources" isTestSource="false" />
       <sourceFolder url="file://$MODULE_DIR$/src" isTestSource="false" />
+      <sourceFolder url="file://$MODULE_DIR$/test" isTestSource="true" />
     </content>
     <orderEntry type="inheritedJdk" />
     <orderEntry type="sourceFolder" forTests="false" />
@@ -16,7 +17,6 @@
     <orderEntry type="module" module-name="lang-api" />
     <orderEntry type="module" module-name="properties" />
     <orderEntry type="module" module-name="execution-impl" />
-    <orderEntry type="library" name="Ant" level="project" />
     <orderEntry type="module" module-name="compiler-openapi" />
     <orderEntry type="module" module-name="execution-openapi" />
     <orderEntry type="module" module-name="idea-ui" />
@@ -34,6 +34,7 @@
     <orderEntry type="module" module-name="copyright" />
     <orderEntry type="module" module-name="IntelliLangJava" />
     <orderEntry type="module" module-name="ant" />
+    <orderEntry type="module" module-name="testFramework-java" scope="TEST" />
   </component>
 </module>
 
index 10c662e4b25d4feccd9e675bb036d8d16689a946..75aaadb6326c5ad3a72e59eb02f8f7b7c2c9a7c0 100644 (file)
@@ -16,7 +16,7 @@
 
 <idea-plugin url="http://www.jetbrains.net/confluence/display/GRVY/Groovy+Home">
   <id>org.intellij.groovy</id>
-  <name>JetGroovy</name>
+  <name>Groovy</name>
   <description>Plugin for Groovy language support</description>
   <version>9.0</version>
   <vendor logo="/org/jetbrains/plugins/groovy/images/groovy_16x16.png" url="http://www.jetbrains.com">JetBrains Inc.
 
     <membersContributor implementation="org.jetbrains.plugins.groovy.gant.GantMemberContributor"/>
 
-    <typeConverter implementation="org.jetbrains.plugins.groovy.lang.psi.impl.GrContainerTypeConverter"/> 
+    <typeConverter implementation="org.jetbrains.plugins.groovy.lang.psi.impl.GrContainerTypeConverter"/>
+
+    <libraryManager implementation="org.jetbrains.plugins.groovy.gpp.GppLibraryManager" order="first"/>
+    <typeConverter implementation="org.jetbrains.plugins.groovy.gpp.GppTypeConverter"/>
+    <expectedTypesContributor implementation="org.jetbrains.plugins.groovy.gpp.GppExpectedTypesContributor"/>
+    <variableEnhancer implementation="org.jetbrains.plugins.groovy.gpp.GppClosureParameterTypeProvider"/>
+    <classSubstitutor implementation="org.jetbrains.plugins.groovy.gpp.GppClassSubstitutor"/>
+    <nonCodeProcessor implementation="org.jetbrains.plugins.groovy.gpp.GppStdLibSupport"/>
+    <positionManagerDelegate implementation="org.jetbrains.plugins.groovy.gpp.GppPositionManager"/>
+    
   </extensions>
 
   <extensions defaultExtensionNs="com.intellij">
 
     <patterns.patternClass className="org.jetbrains.plugins.groovy.lang.psi.patterns.GroovyPatterns" alias="groovy"/>
 
+    <stacktrace.fold substring="at org.codehaus.groovy."/>
+    <stacktrace.fold substring="at groovy."/>
+    <stacktrace.fold substring="at org.codehaus.groovy.runtime.DefaultGroovyMethods." negate="true"/>
+    <stacktrace.fold substring="at org.codehaus.groovy.vmplugin.v5.PluginDefaultGroovyMethods." negate="true"/>
+    <stacktrace.fold substring="at org.codehaus.groovy.runtime.DefaultGroovyMethodsSupport." negate="true"/>
+
     <!-- control flow -->
     <intentionAction>
       <bundleName>org.jetbrains.plugins.groovy.intentions.GroovyIntentionsBundle</bundleName>
       <className>org.jetbrains.plugins.groovy.intentions.style.ReplaceAbstractClassInstanceByMapIntention</className>
     </intentionAction>
 
+    <intentionAction>
+      <bundleName>org.jetbrains.plugins.groovy.intentions.GroovyIntentionsBundle</bundleName>
+      <categoryKey>intention.category.groovy</categoryKey>
+      <className>org.jetbrains.plugins.groovy.grape.GrabDependencies</className>
+    </intentionAction>
+
+
     <projectService serviceInterface="org.jetbrains.plugins.groovy.annotator.intentions.dynamic.DynamicToolWindowWrapper"
                     serviceImplementation="org.jetbrains.plugins.groovy.annotator.intentions.dynamic.DynamicToolWindowWrapper"/>
+
+    <java.programPatcher implementation="org.jetbrains.plugins.groovy.debugger.GroovyHotSwapper"/>
+    <psi.referenceContributor implementation="org.jetbrains.plugins.groovy.gpp.GppReferenceContributor"/>
   </extensions>
 
   <extensions defaultExtensionNs="com.intellij.debugger">
index 92d5af825aaa9116f1c07401a4eb4d464a33362c..9d498c762e0b12bef0619bc072ec1e5efcfbf915 100644 (file)
@@ -40,6 +40,8 @@ public class GroovyFileTypeLoader extends FileTypeFactory{
   public static Set<String> getCustomGroovyScriptExtensions() {
     final LinkedHashSet<String> strings = new LinkedHashSet<String>();
     strings.add("gdsl");
+    strings.add("gpp");
+    strings.add("grunit");
     for (GroovyScriptTypeEP ep : GroovyScriptType.EP_NAME.getExtensions()) {
       ContainerUtil.addAll(strings, ep.extensions.split(";"));
     }
index 1283d3152988bc79e4f010cf3c0e9150f4a8b00a..1933fabf3281b14ac4b50c474d836d9e04d463ff 100644 (file)
@@ -36,6 +36,11 @@ public class ExcludeFromStubGenerationAction extends AnAction implements DumbAwa
     final PsiFile file = e.getData(DataKeys.PSI_FILE);
 
     assert file != null && file.getLanguage() == GroovyFileType.GROOVY_LANGUAGE;
+
+    doExcludeFromStubGeneration(file);
+  }
+
+  public static void doExcludeFromStubGeneration(PsiFile file) {
     final VirtualFile virtualFile = file.getVirtualFile();
     assert virtualFile != null;
     final Project project = file.getProject();
@@ -46,7 +51,6 @@ public class ExcludeFromStubGenerationAction extends AnAction implements DumbAwa
         configurable.getExcludes().addEntry(new ExcludeEntryDescription(virtualFile, false, true, project));
       }
     });
-
   }
 
   public void update(AnActionEvent e) {
index 11f5e50feba64cc91c0c075d71bc07d65e13831f..a8ab5ded516efa8429cbb682fb7fd828ac391dce 100644 (file)
@@ -17,9 +17,16 @@ package org.jetbrains.plugins.groovy.compiler;
 
 import com.intellij.openapi.compiler.CompilerManager;
 import com.intellij.openapi.components.AbstractProjectComponent;
+import com.intellij.openapi.fileEditor.FileEditor;
+import com.intellij.openapi.fileEditor.FileEditorManager;
+import com.intellij.openapi.fileEditor.FileEditorManagerAdapter;
+import com.intellij.openapi.fileEditor.FileEditorManagerListener;
 import com.intellij.openapi.fileTypes.FileType;
 import com.intellij.openapi.fileTypes.StdFileTypes;
 import com.intellij.openapi.project.Project;
+import com.intellij.openapi.vfs.VirtualFile;
+import com.intellij.psi.PsiClass;
+import com.intellij.ui.EditorNotificationPanel;
 import org.jetbrains.annotations.NotNull;
 import org.jetbrains.plugins.groovy.GroovyFileType;
 import org.jetbrains.plugins.groovy.compiler.generator.GroovycStubGenerator;
@@ -47,6 +54,47 @@ public class GroovyCompilerLoader extends AbstractProjectComponent {
     compilerManager.addTranslatingCompiler(new GroovyCompiler(myProject),
                                            new HashSet<FileType>(Arrays.asList(GroovyFileType.GROOVY_FILE_TYPE, StdFileTypes.CLASS)),
                                            new HashSet<FileType>(Arrays.asList(StdFileTypes.CLASS)));
+
+    myProject.getMessageBus().connect().subscribe(FileEditorManagerListener.FILE_EDITOR_MANAGER, new FileEditorManagerAdapter() {
+      @Override
+      public void fileOpened(FileEditorManager source, final VirtualFile file) {
+        if (file.getName().endsWith(".java") && file.getPath().contains(GroovycStubGenerator.GROOVY_STUBS)) {
+          final PsiClass psiClass = GroovycStubGenerator.findClassByStub(myProject, file);
+          if (psiClass != null) {
+            final FileEditorManager fileEditorManager = FileEditorManager.getInstance(myProject);
+            final FileEditor[] editors = fileEditorManager.getEditors(file);
+            if (editors.length != 0) {
+              decorateStubFile(file, fileEditorManager, editors[0]);
+            }
+            
+          }
+        }
+      }
+    });
+  }
+
+  private void decorateStubFile(final VirtualFile file, FileEditorManager fileEditorManager, FileEditor editor) {
+    final EditorNotificationPanel panel = new EditorNotificationPanel();
+    panel.setText("This stub is generated for Groovy class to make Groovy-Java cross-compilation possible");
+    panel.createActionLabel("Go to the Groovy class", new Runnable() {
+      @Override
+      public void run() {
+        final PsiClass original = GroovycStubGenerator.findClassByStub(myProject, file);
+        if (original != null) {
+          original.navigate(true);
+        }
+      }
+    });
+    panel.createActionLabel("Exclude from stub generation", new Runnable() {
+      @Override
+      public void run() {
+        final PsiClass psiClass = GroovycStubGenerator.findClassByStub(myProject, file);
+        if (psiClass != null) {
+          ExcludeFromStubGenerationAction.doExcludeFromStubGeneration(psiClass.getContainingFile());
+        }
+      }
+    });
+    fileEditorManager.addTopComponent(editor, panel);
   }
 
   @NotNull
index 919e1431f0e8bd35e3f9daf7a8344134138bd518..8c00ad89a52d01274dea92f29d2dc4e0311ba3bc 100644 (file)
@@ -15,6 +15,7 @@
  */
 package org.jetbrains.plugins.groovy.compiler.generator;
 
+import com.intellij.codeInsight.generation.OverrideImplementUtil;
 import com.intellij.compiler.CompilerConfiguration;
 import com.intellij.openapi.application.ApplicationManager;
 import com.intellij.openapi.compiler.CompileContext;
@@ -33,7 +34,9 @@ import com.intellij.openapi.vfs.VirtualFile;
 import com.intellij.psi.*;
 import com.intellij.psi.impl.light.LightMethodBuilder;
 import com.intellij.psi.util.MethodSignature;
+import com.intellij.psi.util.MethodSignatureBackedByPsiMethod;
 import com.intellij.psi.util.MethodSignatureUtil;
+import com.intellij.psi.util.TypeConversionUtil;
 import com.intellij.util.ArrayUtil;
 import com.intellij.util.containers.CollectionFactory;
 import com.intellij.util.containers.ContainerUtil;
@@ -43,6 +46,7 @@ import org.jetbrains.annotations.NotNull;
 import org.jetbrains.annotations.Nullable;
 import org.jetbrains.plugins.groovy.GroovyFileType;
 import org.jetbrains.plugins.groovy.compiler.GroovyCompilerConfiguration;
+import org.jetbrains.plugins.groovy.lang.psi.GrClassSubstitutor;
 import org.jetbrains.plugins.groovy.lang.psi.GroovyFile;
 import org.jetbrains.plugins.groovy.lang.psi.GroovyFileBase;
 import org.jetbrains.plugins.groovy.lang.psi.api.GroovyResolveResult;
@@ -269,7 +273,7 @@ public class GroovyToJavaGenerator {
     }
 
     for (final GrTypeDefinition typeDefinition : file.getTypeDefinitions()) {
-      generatedItemsRelativePaths.add(createJavaSourceFile(outputRootDirectory, typeDefinition, packageDefinition));
+      generatedItemsRelativePaths.add(createJavaSourceFile(outputRootDirectory, GrClassSubstitutor.getSubstitutedClass(typeDefinition), packageDefinition));
     }
 
     return generatedItemsRelativePaths;
@@ -351,20 +355,16 @@ public class GroovyToJavaGenerator {
 
     writePackageStatement(text, packageDefinition);
 
-    GrMembersDeclaration[] membersDeclarations = typeDefinition instanceof GrTypeDefinition
-                                                 ? ((GrTypeDefinition)typeDefinition).getMemberDeclarations()
-                                                 : GrMembersDeclaration.EMPTY_ARRAY; //todo
-
-    boolean isClassDef = typeDefinition instanceof GrClassDefinition;
-    boolean isInterface = typeDefinition instanceof GrInterfaceDefinition;
-    boolean isEnum = typeDefinition instanceof GrEnumTypeDefinition;
-    boolean isAtInterface = typeDefinition instanceof GrAnnotationTypeDefinition;
+    boolean isEnum = typeDefinition.isEnum();
+    boolean isAnnotationType = typeDefinition.isAnnotationType();
+    boolean isInterface = !isAnnotationType && typeDefinition.isInterface();
+    boolean isClassDef = !isInterface && !isEnum && !isAnnotationType && !isScript;
 
     writeClassModifiers(text, typeDefinition.getModifierList(), typeDefinition.isInterface(), toplevel);
 
     if (isInterface) text.append("interface");
     else if (isEnum) text.append("enum");
-    else if (isAtInterface) text.append("@interface");
+    else if (isAnnotationType) text.append("@interface");
     else text.append("class");
 
     text.append(" ").append(typeDefinition.getName());
@@ -376,7 +376,7 @@ public class GroovyToJavaGenerator {
     if (isScript) {
       text.append("extends groovy.lang.Script ");
     }
-    else if (!isEnum && !isAtInterface) {
+    else if (!isEnum && !isAnnotationType) {
       final PsiClassType[] extendsClassesTypes = typeDefinition.getExtendsListTypes();
 
       if (extendsClassesTypes.length > 0) {
@@ -401,28 +401,32 @@ public class GroovyToJavaGenerator {
       writeEnumConstants(text, (GrEnumTypeDefinition)typeDefinition);
     }
 
-    Set<MethodSignature> methodSignatures = new HashSet<MethodSignature>();
-
+    writeAllMethods(text, collectMethods(typeDefinition, isClassDef), typeDefinition);
 
-    List<PsiMethod> methods = new ArrayList<PsiMethod>();
-    ContainerUtil.addAll(methods, typeDefinition.getMethods());
-    if (isClassDef) {
-      final PsiElementFactory factory = JavaPsiFacade.getInstance(myProject).getElementFactory();
-      methods.add(factory.createMethodFromText("public groovy.lang.MetaClass getMetaClass() {}", null));
-      methods.add(factory.createMethodFromText("public void setMetaClass(groovy.lang.MetaClass mc) {}", null));
-      methods.add(factory.createMethodFromText("public Object invokeMethod(String name, Object args) {}", null));
-      methods.add(factory.createMethodFromText("public Object getProperty(String propertyName) {}", null));
-      methods.add(factory.createMethodFromText("public void setProperty(String propertyName, Object newValue) {}", null));
+    if (typeDefinition instanceof GrTypeDefinition) {
+      for (GrMembersDeclaration declaration : ((GrTypeDefinition)typeDefinition).getMemberDeclarations()) {
+        if (declaration instanceof GrVariableDeclaration) {
+          writeVariableDeclarations(text, (GrVariableDeclaration)declaration);
+        }
+      }
+    }
+    for (PsiClass inner : typeDefinition.getInnerClasses()) {
+      writeTypeDefinition(text, inner, null, false);
+      text.append("\n");
     }
 
+    text.append("}");
+  }
 
+  private static void writeAllMethods(StringBuffer text, List<PsiMethod> methods, PsiClass aClass) {
+    Set<MethodSignature> methodSignatures = new HashSet<MethodSignature>();
     for (PsiMethod method : methods) {
       if (LightMethodBuilder.isLightMethod(method, GrClassImplUtil.SYNTHETIC_METHOD_IMPLEMENTATION)) {
         continue;
       }
 
       if (method instanceof GrConstructor) {
-        writeConstructor(text, (GrConstructor)method, isEnum);
+        writeConstructor(text, (GrConstructor)method, aClass.isEnum());
         continue;
       }
 
@@ -455,18 +459,51 @@ public class GroovyToJavaGenerator {
         }
       }
     }
+  }
 
-    for (GrMembersDeclaration declaration : membersDeclarations) {
-      if (declaration instanceof GrVariableDeclaration) {
-        writeVariableDeclarations(text, (GrVariableDeclaration)declaration);
+  private List<PsiMethod> collectMethods(PsiClass typeDefinition, boolean classDef) {
+    List<PsiMethod> methods = new ArrayList<PsiMethod>();
+    ContainerUtil.addAll(methods, typeDefinition.getMethods());
+    if (classDef) {
+      final Collection<MethodSignature> toOverride = OverrideImplementUtil.getMethodSignaturesToOverride(typeDefinition);
+      for (MethodSignature signature : toOverride) {
+        if (signature instanceof MethodSignatureBackedByPsiMethod) {
+          final PsiMethod method = ((MethodSignatureBackedByPsiMethod)signature).getMethod();
+          final PsiClass baseClass = method.getContainingClass();
+          if (isAbstractInJava(method) && baseClass != null && typeDefinition.isInheritor(baseClass, true)) {
+            final LightMethodBuilder builder = new LightMethodBuilder(method.getManager(), method.getName());
+            final PsiSubstitutor substitutor = TypeConversionUtil.getSuperClassSubstitutor(baseClass, typeDefinition, PsiSubstitutor.EMPTY);
+            for (PsiParameter parameter : method.getParameterList().getParameters()) {
+              builder.addParameter(parameter.getName(), substitutor.substitute(parameter.getType()));
+            }
+            builder.setReturnType(substitutor.substitute(method.getReturnType()));
+            for (String modifier : JAVA_MODIFIERS) {
+              if (method.hasModifierProperty(modifier)) {
+                builder.addModifier(modifier);
+              }
+            }
+            methods.add(builder);
+          }
+        }
       }
+
+      final PsiElementFactory factory = JavaPsiFacade.getInstance(myProject).getElementFactory();
+      methods.add(factory.createMethodFromText("public groovy.lang.MetaClass getMetaClass() {}", null));
+      methods.add(factory.createMethodFromText("public void setMetaClass(groovy.lang.MetaClass mc) {}", null));
+      methods.add(factory.createMethodFromText("public Object invokeMethod(String name, Object args) {}", null));
+      methods.add(factory.createMethodFromText("public Object getProperty(String propertyName) {}", null));
+      methods.add(factory.createMethodFromText("public void setProperty(String propertyName, Object newValue) {}", null));
     }
-    for (PsiClass inner : typeDefinition.getInnerClasses()) {
-      writeTypeDefinition(text, inner, null, false);
-      text.append("\n");
+    return methods;
+  }
+
+  private static boolean isAbstractInJava(PsiMethod method) {
+    if (method.hasModifierProperty(PsiModifier.ABSTRACT)) {
+      return true;
     }
 
-    text.append("}");
+    final PsiClass psiClass = method.getContainingClass();
+    return psiClass != null && GrClassSubstitutor.getSubstitutedClass(psiClass).isInterface();
   }
 
   private static void appendTypeParameters(StringBuffer text, PsiTypeParameterListOwner typeParameterListOwner) {
@@ -670,7 +707,7 @@ public class GroovyToJavaGenerator {
     if (!JavaPsiFacade.getInstance(method.getProject()).getNameHelper().isIdentifier(name))
       return; //does not have a java image
 
-    boolean isAbstract = method.hasModifierProperty(PsiModifier.ABSTRACT);
+    boolean isAbstract = isAbstractInJava(method);
 
     PsiModifierList modifierList = method.getModifierList();
 
index 610e901318511586ad89bb63c38ac1f1c1a76a73..b0c87fa0078c50991d450fbc65d7fb0dd34f521c 100644 (file)
@@ -26,13 +26,19 @@ import com.intellij.openapi.compiler.ex.CompileContextEx;
 import com.intellij.openapi.compiler.options.ExcludedEntriesConfiguration;
 import com.intellij.openapi.fileTypes.StdFileTypes;
 import com.intellij.openapi.module.Module;
+import com.intellij.openapi.module.ModuleManager;
 import com.intellij.openapi.module.ModuleUtil;
 import com.intellij.openapi.project.Project;
+import com.intellij.openapi.util.text.StringUtil;
 import com.intellij.openapi.vfs.LocalFileSystem;
 import com.intellij.openapi.vfs.VfsUtil;
 import com.intellij.openapi.vfs.VirtualFile;
+import com.intellij.psi.JavaPsiFacade;
+import com.intellij.psi.PsiClass;
+import com.intellij.psi.search.GlobalSearchScope;
 import com.intellij.util.Chunk;
 import org.jetbrains.annotations.NotNull;
+import org.jetbrains.annotations.Nullable;
 import org.jetbrains.plugins.groovy.GroovyFileType;
 import org.jetbrains.plugins.groovy.compiler.GroovyCompilerBase;
 import org.jetbrains.plugins.groovy.compiler.GroovyCompilerConfiguration;
@@ -40,6 +46,7 @@ import org.jetbrains.plugins.groovy.compiler.GroovyCompilerConfiguration;
 import java.io.File;
 import java.io.IOException;
 import java.util.ArrayList;
+import java.util.Arrays;
 import java.util.List;
 
 /**
@@ -47,6 +54,8 @@ import java.util.List;
  */
 public class GroovycStubGenerator extends GroovyCompilerBase {
 
+  public static final String GROOVY_STUBS = "groovyStubs";
+
   public GroovycStubGenerator(Project project) {
     super(project);
   }
@@ -93,8 +102,7 @@ public class GroovycStubGenerator extends GroovyCompilerBase {
   @Override
   protected void compileFiles(CompileContext compileContext, Module module,
                               final List<VirtualFile> toCompile, OutputSink sink, boolean tests) {
-    final String rootPath = CompilerPaths.getGeneratedDataDirectory(myProject) + "/groovyStubs/";
-    final File outDir = new File(rootPath + myProject.getLocationHash() + "/" + module.getName() + "/" + (tests ? "tests" : "production") + "/");
+    final File outDir = getStubOutput(module, tests);
     outDir.mkdirs();
 
     final VirtualFile tempOutput = LocalFileSystem.getInstance().refreshAndFindFileByIoFile(outDir);
@@ -119,6 +127,26 @@ public class GroovycStubGenerator extends GroovyCompilerBase {
     }
   }
 
+  private static File getStubOutput(Module module, boolean tests) {
+    final Project project = module.getProject();
+    final String rootPath = CompilerPaths.getGeneratedDataDirectory(project).getPath() + "/" + GROOVY_STUBS + "/";
+    return new File(rootPath + project.getLocationHash() + "/" + module.getName() + "/" + (tests ? "tests" : "production") + "/");
+  }
+
+  @Nullable
+  public static PsiClass findClassByStub(Project project, VirtualFile stubFile) {
+    final String[] components = StringUtil.trimEnd(stubFile.getPath(), ".java").split("[\\\\/]");
+    final int stubs = Arrays.asList(components).indexOf(GROOVY_STUBS);
+    if (stubs < 0 || stubs >= components.length - 4) return null;
+
+    final String moduleName = components[stubs + 2];
+    final Module module = ModuleManager.getInstance(project).findModuleByName(moduleName);
+    if (module == null) return null;
+
+    final String fqn = StringUtil.join(Arrays.asList(components).subList(stubs + 4, components.length), ".");
+    return JavaPsiFacade.getInstance(project).findClass(fqn, GlobalSearchScope.moduleScope(module));
+  }
+
   private void cleanDirectory(final VirtualFile dir) {
     new WriteCommandAction(myProject) {
       protected void run(Result result) throws Throwable {
similarity index 87%
rename from plugins/groovy/groovypp/src/org/jetbrains/plugins/groovy/gpp/GppTypeConverter.java
rename to plugins/groovy/src/org/jetbrains/plugins/groovy/gpp/GppTypeConverter.java
index 0ebb8448b4db0626ed6055aaa5a0099cc5786cbd..64ba6c939cada461583c10483a25654e444db773 100644 (file)
@@ -44,18 +44,17 @@ public class GppTypeConverter extends GrTypeConverter {
   @Override
   public Boolean isConvertible(@NotNull PsiType lType, @NotNull PsiType rType, @NotNull GroovyPsiElement context) {
     if (rType instanceof GrTupleType) {
-      final PsiType type = PsiUtil.extractIterableTypeParameter(lType, false);
-      if (type == null || TypesUtil.isAssignable(type, ((GrTupleType)rType).getParameters()[0], context)) {
-        final PsiType[] componentTypes = ((GrTupleType)rType).getComponentTypes();
-
-        final PsiType expectedComponent = PsiUtil.extractIterableTypeParameter(lType, false);
-        if (expectedComponent != null && hasDefaultConstructor(lType)) {
-          return true;
-        }
-
-        if (lType instanceof PsiClassType && hasConstructor((PsiClassType)lType, componentTypes, context)) {
-          return true;
-        }
+      final GrTupleType tupleType = (GrTupleType)rType;
+
+      final PsiType expectedComponent = PsiUtil.extractIterableTypeParameter(lType, false);
+      if (expectedComponent != null &&
+          isMethodCallConversion(context) && TypesUtil.isAssignable(expectedComponent, tupleType.getParameters()[0], context) && 
+          hasDefaultConstructor(lType)) {
+        return true;
+      }
+
+      if (lType instanceof PsiClassType && hasConstructor((PsiClassType)lType, tupleType.getComponentTypes(), context)) {
+        return true;
       }
     }
     else if (rType instanceof GrMapType) {
index 6b32b8c7ac69fee69ba011feca643689e222b9d9..639b59d79656c3e2fc69b303a77bc731eaa01f2b 100644 (file)
@@ -261,7 +261,7 @@ public class GroovyCompletionContributor extends CompletionContributor {
         }
         else if (call instanceof GrCallExpression) {
           GrCallExpression constructorCall = (GrCallExpression)call;
-          ContainerUtil.addAll(results, constructorCall.getMethodVariants());
+          ContainerUtil.addAll(results, constructorCall.getMethodVariants(null));
           final PsiType type = ((GrCallExpression)call).getType();
           if (type instanceof PsiClassType) {
             final PsiClass psiClass = ((PsiClassType)type).resolve();
index 3fdc0239b076b771c9303632ff05dc707e6d07ae..4f3b20e1ed4f93624ce849aa7db99ea4116bd8c1 100644 (file)
@@ -5,6 +5,7 @@ import com.intellij.psi.PsiElement;
 import com.intellij.psi.PsiType;
 import org.jetbrains.annotations.NotNull;
 import org.jetbrains.annotations.Nullable;
+import org.jetbrains.plugins.groovy.lang.psi.api.statements.expressions.GrMethodCall;
 
 /**
  * @author peter
@@ -12,7 +13,11 @@ import org.jetbrains.annotations.Nullable;
 public abstract class GrTypeConverter {
   public static final ExtensionPointName<GrTypeConverter> EP_NAME = ExtensionPointName.create("org.intellij.groovy.typeConverter");
 
+  protected static boolean isMethodCallConversion(GroovyPsiElement context) {
+    return context.getParent() instanceof GrMethodCall;
+  }
+
   @Nullable
   public abstract Boolean isConvertible(@NotNull PsiType lType, @NotNull PsiType rType, @NotNull GroovyPsiElement context);
 
-}
\ No newline at end of file
+}
index 84cf9d13c5497a2cabe4af55774f8a0f90df7eaf..48aeb07117d59f893a81aedb5c5cbc3bb8906994 100644 (file)
@@ -43,7 +43,7 @@ public interface GrCallExpression extends GrExpression, GrCall {
   PsiMethod resolveMethod();
 
   @NotNull
-  GroovyResolveResult[] getMethodVariants();
+  GroovyResolveResult[] getMethodVariants(@Nullable GrExpression upToArgument);
 
   //PsiElement addNamedArgument(GrNamedArgument argument);
 }
index a382c23d87e6687507b9a2c8290c60f44ebe3c4f..a37a96beddbd70593275994d53297dec5d487f6a 100644 (file)
@@ -127,7 +127,7 @@ public class GroovyExpectedTypesProvider {
       final int closureIndex = closureArgs.indexOf(myExpression);
       if (closureIndex >= 0) {
         List<TypeConstraint> constraints = new ArrayList<TypeConstraint>();
-        for (GroovyResolveResult variant : methodCall.getMethodVariants()) {
+        for (GroovyResolveResult variant : ResolveUtil.getMethodVariants(myExpression)) {
           PsiParameter[] parameters = getCallParameters(variant);
           if (parameters == null || parameters.length == 0) continue;
 
index 2fd193c1203ac0163407c58a3b9118062f831823..a243ff54012b0250bd5aedd5c4dcabcad9937071 100644 (file)
@@ -32,6 +32,10 @@ import org.jetbrains.plugins.groovy.lang.psi.impl.statements.expressions.TypesUt
 public class GrContainerTypeConverter extends GrTypeConverter {
   @Override
   public Boolean isConvertible(@NotNull PsiType lType, @NotNull PsiType rType, @NotNull GroovyPsiElement context) {
+    if (isMethodCallConversion(context)) {
+      return null;
+    }
+
     if (!isCollectionOrArray(lType) || !isCollectionOrArray(rType)) return null;
 
     final PsiType lComponentType = extractComponentType(lType);
index 7f0c4391bbf41f06c909e011ab091ef57b3a1b6c..2a45e985ae61948ffc0c7777230cf7aea6d59f58 100644 (file)
@@ -115,7 +115,9 @@ public class GrMapType extends GrLiteralClassType {
     for (Pair<PsiType, PsiType> entry : myOtherEntries) {
       components.add(getInternalCanonicalText(entry.first) + ":" + getInternalCanonicalText(entry.second));
     }
-    return "[" + StringUtil.join(components, ", ") + "]";
+    boolean tooMany = components.size() > 2;
+    final List<String> theFirst = components.subList(0, Math.min(2, components.size()));
+    return "[" + StringUtil.join(theFirst, ", ") + (tooMany ? ",..." : "") + "]";
   }
 
   public boolean isValid() {
index 13fc908f461e19ad8c83d538b69a847698b31d4a..8dd75907f1ad11d908eb74f41327cbff229d9e9d 100644 (file)
@@ -59,6 +59,11 @@ public class GrTupleType extends GrLiteralClassType {
     StringBuilder builder = new StringBuilder();
     builder.append("[");
     for (int i = 0; i < myComponentTypes.length; i++) {
+      if (i >= 2) {
+        builder.append(",...");
+        break;
+      }
+
       if (i > 0) builder.append(", ");
       builder.append(getInternalCanonicalText(myComponentTypes[i]));
     }
index d3726e2b107720184600e7a4899198462a396df8..b79ecbde06684176421888093fbb72fa52fb4ce5 100644 (file)
@@ -42,7 +42,6 @@ import org.jetbrains.plugins.groovy.lang.psi.util.PsiUtil;
 import org.jetbrains.plugins.groovy.lang.resolve.ResolveUtil;
 
 import java.util.ArrayList;
-import java.util.Arrays;
 import java.util.List;
 
 /**
@@ -183,7 +182,7 @@ public class GrNewExpressionImpl extends GrCallExpressionImpl implements GrNewEx
   }
 
   @NotNull
-  public GroovyResolveResult[] getMethodVariants() {
+  public GroovyResolveResult[] getMethodVariants(@Nullable GrExpression upToArgument) {
     final GrCodeReferenceElement referenceElement = getReferenceElement();
     if (referenceElement == null) return GroovyResolveResult.EMPTY_ARRAY;
     final GroovyResolveResult[] classResults = referenceElement.multiResolve(false);
index b62e74f3c2af8815f2149f63173a7a18a713d7e4..16311308b982e02728f9e5ad9ce0e2d583931f6c 100644 (file)
@@ -28,7 +28,10 @@ import com.intellij.psi.tree.IElementType;
 import com.intellij.psi.util.PropertyUtil;
 import com.intellij.psi.util.PsiTreeUtil;
 import com.intellij.psi.util.TypeConversionUtil;
-import com.intellij.util.*;
+import com.intellij.util.ArrayUtil;
+import com.intellij.util.Consumer;
+import com.intellij.util.Function;
+import com.intellij.util.IncorrectOperationException;
 import com.intellij.util.containers.ContainerUtil;
 import org.jetbrains.annotations.NonNls;
 import org.jetbrains.annotations.NotNull;
@@ -61,7 +64,6 @@ import org.jetbrains.plugins.groovy.lang.resolve.ResolveUtil;
 import org.jetbrains.plugins.groovy.lang.resolve.processors.*;
 
 import java.util.ArrayList;
-import java.util.Arrays;
 import java.util.EnumSet;
 import java.util.List;
 
@@ -413,7 +415,7 @@ public class GrReferenceExpressionImpl extends GrReferenceElementImpl implements
       Kind kind = refExpr.getKind();
       if (incompleteCode) {
         ResolverProcessor processor = CompletionProcessor.createRefSameNameProcessor(refExpr, name);
-        resolveImpl(refExpr, processor);
+        refExpr.resolveImpl(processor);
         GroovyResolveResult[] propertyCandidates = processor.getCandidates();
         if (propertyCandidates.length > 0) return propertyCandidates;
       }
@@ -436,7 +438,7 @@ public class GrReferenceExpressionImpl extends GrReferenceElementImpl implements
       GroovyResolveResult[] classCandidates = GroovyResolveResult.EMPTY_ARRAY;
       if (!hasAt) {
         ResolverProcessor classProcessor = new ClassResolverProcessor(refExpr.getReferenceName(), refExpr, kinds);
-        resolveImpl(refExpr, classProcessor);
+        refExpr.resolveImpl(classProcessor);
         classCandidates = classProcessor.getCandidates();
         for (GroovyResolveResult classCandidate : classCandidates) {
           final PsiElement element = classCandidate.getElement();
@@ -447,7 +449,7 @@ public class GrReferenceExpressionImpl extends GrReferenceElementImpl implements
       }
 
       ResolverProcessor processor = new PropertyResolverProcessor(name, refExpr);
-      resolveImpl(refExpr, processor);
+      refExpr.resolveImpl(processor);
       final GroovyResolveResult[] fieldCandidates = processor.getCandidates();
 
       if (refExpr.hasAt()) {
@@ -471,7 +473,7 @@ public class GrReferenceExpressionImpl extends GrReferenceElementImpl implements
       List<GroovyResolveResult> accessorResults = new ArrayList<GroovyResolveResult>();
       for (String getterName : names) {
         AccessorResolverProcessor accessorResolver = new AccessorResolverProcessor(getterName, refExpr, !isLValue);
-        resolveImpl(refExpr, accessorResolver);
+        refExpr.resolveImpl(accessorResolver);
         final GroovyResolveResult[] candidates = accessorResolver.getCandidates(); //can be only one candidate
         if (candidates.length == 1 && candidates[0].isStaticsOK()) {
           return candidates;
@@ -488,18 +490,15 @@ public class GrReferenceExpressionImpl extends GrReferenceElementImpl implements
 
     private static GroovyResolveResult[] resolveMethodOrProperty(GrReferenceExpressionImpl refExpr, String name) {
       final PsiType[] argTypes = PsiUtil.getArgumentTypes(refExpr, false);
-      PsiType thisType = getThisType(refExpr);
-
-      MethodResolverProcessor methodResolver =
-        new MethodResolverProcessor(name, refExpr, false, thisType, argTypes, refExpr.getTypeArguments());
-      resolveImpl(refExpr, methodResolver);
+      MethodResolverProcessor methodResolver = refExpr.runMethodResolverProcessor(argTypes, false);
+      assert methodResolver != null;
       if (methodResolver.hasApplicableCandidates()) return methodResolver.getCandidates();
 
       final String[] names = GroovyPropertyUtils.suggestGettersName(name);
       List<GroovyResolveResult> list = new ArrayList<GroovyResolveResult>();
       for (String getterName : names) {
         AccessorResolverProcessor getterResolver = new AccessorResolverProcessor(getterName, refExpr, true);
-        resolveImpl(refExpr, getterResolver);
+        refExpr.resolveImpl(getterResolver);
         final GroovyResolveResult[] candidates = getterResolver.getCandidates(); //can be only one candidate
         if (candidates.length == 1 && candidates[0].isStaticsOK()) {
           refExpr.putUserData(IS_RESOLVED_TO_GETTER, true);
@@ -511,7 +510,7 @@ public class GrReferenceExpressionImpl extends GrReferenceElementImpl implements
       }
 
       PropertyResolverProcessor propertyResolver = new PropertyResolverProcessor(name, refExpr);
-      resolveImpl(refExpr, propertyResolver);
+      refExpr.resolveImpl(propertyResolver);
       if (propertyResolver.hasCandidates()) return propertyResolver.getCandidates();
 
       if (methodResolver.hasCandidates()) {
@@ -525,144 +524,158 @@ public class GrReferenceExpressionImpl extends GrReferenceElementImpl implements
       return GroovyResolveResult.EMPTY_ARRAY;
     }
 
+  }
 
-    private static void resolveImpl(GrReferenceExpressionImpl refExpr, ResolverProcessor processor) {
-      GrExpression qualifier = refExpr.getQualifierExpression();
-      if (qualifier == null) {
-        ResolveUtil.treeWalkUp(refExpr, processor, true);
-        if (!processor.hasCandidates()) {
-          qualifier = PsiImplUtil.getRuntimeQualifier(refExpr);
-          if (qualifier != null) {
-            processQualifier(refExpr, processor, qualifier);
-          }
+  private void resolveImpl(ResolverProcessor processor) {
+    GrExpression qualifier = getQualifierExpression();
+    if (qualifier == null) {
+      ResolveUtil.treeWalkUp(this, processor, true);
+      if (!processor.hasCandidates()) {
+        qualifier = PsiImplUtil.getRuntimeQualifier(this);
+        if (qualifier != null) {
+          processQualifier(processor, qualifier);
         }
+      }
+    } else {
+      if (getDotTokenType() != GroovyTokenTypes.mSPREAD_DOT) {
+        processQualifier(processor, qualifier);
       } else {
-        if (refExpr.getDotTokenType() != GroovyTokenTypes.mSPREAD_DOT) {
-          processQualifier(refExpr, processor, qualifier);
-        } else {
-          processQualifierForSpreadDot(refExpr, processor, qualifier);
-        }
+        processQualifierForSpreadDot(processor, qualifier);
+      }
 
-        if (qualifier instanceof GrReferenceExpression && "class".equals(((GrReferenceExpression)qualifier).getReferenceName())) {
-          processIfJavaLangClass(refExpr, processor, qualifier.getType());
-        } else if (qualifier instanceof GrThisReferenceExpression) {
-          processIfJavaLangClass(refExpr, processor, qualifier.getType());
-        }
+      if (qualifier instanceof GrReferenceExpression && "class".equals(((GrReferenceExpression)qualifier).getReferenceName())) {
+        processIfJavaLangClass(processor, qualifier.getType());
+      } else if (qualifier instanceof GrThisReferenceExpression) {
+        processIfJavaLangClass(processor, qualifier.getType());
       }
     }
+  }
 
-    private static void processIfJavaLangClass(GrReferenceExpressionImpl refExpr, ResolverProcessor processor, PsiType type) {
-      if (type instanceof PsiClassType) {
-        final PsiClass psiClass = ((PsiClassType)type).resolve();
-        if (psiClass != null && CommonClassNames.JAVA_LANG_CLASS.equals(psiClass.getQualifiedName())) {
-          final PsiType[] params = ((PsiClassType)type).getParameters();
-          if (params.length == 1) {
-            processClassQualifierType(refExpr, processor, params[0]);
-          }
+  private void processIfJavaLangClass(ResolverProcessor processor, PsiType type) {
+    if (type instanceof PsiClassType) {
+      final PsiClass psiClass = ((PsiClassType)type).resolve();
+      if (psiClass != null && CommonClassNames.JAVA_LANG_CLASS.equals(psiClass.getQualifiedName())) {
+        final PsiType[] params = ((PsiClassType)type).getParameters();
+        if (params.length == 1) {
+          processClassQualifierType(processor, params[0]);
         }
       }
     }
+  }
 
-    private static void processQualifierForSpreadDot(GrReferenceExpressionImpl refExpr, ResolverProcessor processor, GrExpression qualifier) {
-      PsiType qualifierType = qualifier.getType();
-      if (qualifierType instanceof PsiClassType) {
-        PsiClassType.ClassResolveResult result = ((PsiClassType) qualifierType).resolveGenerics();
-        PsiClass clazz = result.getElement();
-        if (clazz != null) {
-          PsiClass listClass = ResolveUtil.findListClass(refExpr.getManager(), refExpr.getResolveScope());
-          if (listClass != null && listClass.getTypeParameters().length == 1) {
-            PsiSubstitutor substitutor = TypeConversionUtil.getClassSubstitutor(listClass, clazz, result.getSubstitutor());
-            if (substitutor != null) {
-              PsiType componentType = substitutor.substitute(listClass.getTypeParameters()[0]);
-              if (componentType != null) {
-                processClassQualifierType(refExpr, processor, componentType);
-              }
+  private void processQualifierForSpreadDot(ResolverProcessor processor, GrExpression qualifier) {
+    PsiType qualifierType = qualifier.getType();
+    if (qualifierType instanceof PsiClassType) {
+      PsiClassType.ClassResolveResult result = ((PsiClassType) qualifierType).resolveGenerics();
+      PsiClass clazz = result.getElement();
+      if (clazz != null) {
+        PsiClass listClass = ResolveUtil.findListClass(getManager(), getResolveScope());
+        if (listClass != null && listClass.getTypeParameters().length == 1) {
+          PsiSubstitutor substitutor = TypeConversionUtil.getClassSubstitutor(listClass, clazz, result.getSubstitutor());
+          if (substitutor != null) {
+            PsiType componentType = substitutor.substitute(listClass.getTypeParameters()[0]);
+            if (componentType != null) {
+              processClassQualifierType(processor, componentType);
             }
           }
         }
-      } else if (qualifierType instanceof PsiArrayType) {
-        processClassQualifierType(refExpr, processor, ((PsiArrayType) qualifierType).getComponentType());
       }
+    } else if (qualifierType instanceof PsiArrayType) {
+      processClassQualifierType(processor, ((PsiArrayType) qualifierType).getComponentType());
     }
+  }
 
-    private static void processQualifier(GrReferenceExpressionImpl refExpr, ResolverProcessor processor, GrExpression qualifier) {
-      PsiType qualifierType = qualifier.getType();
-      if (qualifierType == null) {
-        if (qualifier instanceof GrReferenceExpression) {
-          PsiElement resolved = ((GrReferenceExpression) qualifier).resolve();
-          if (resolved instanceof PsiPackage) {
-            if (!resolved.processDeclarations(processor, ResolveState.initial(), null, refExpr)) //noinspection UnnecessaryReturnStatement
-              return;
-          }
-          else {
-            qualifierType = JavaPsiFacade.getInstance(refExpr.getProject()).getElementFactory()
-              .createTypeByFQClassName(CommonClassNames.JAVA_LANG_OBJECT, refExpr.getResolveScope());
-            processClassQualifierType(refExpr, processor, qualifierType);
-          }
+  private void processQualifier(ResolverProcessor processor, GrExpression qualifier) {
+    PsiType qualifierType = qualifier.getType();
+    if (qualifierType == null) {
+      if (qualifier instanceof GrReferenceExpression) {
+        PsiElement resolved = ((GrReferenceExpression) qualifier).resolve();
+        if (resolved instanceof PsiPackage) {
+          if (!resolved.processDeclarations(processor, ResolveState.initial(), null, this)) //noinspection UnnecessaryReturnStatement
+            return;
+        }
+        else {
+          qualifierType = JavaPsiFacade.getInstance(getProject()).getElementFactory()
+            .createTypeByFQClassName(CommonClassNames.JAVA_LANG_OBJECT, getResolveScope());
+          processClassQualifierType(processor, qualifierType);
+        }
+      }
+    } else {
+      if (qualifierType instanceof PsiIntersectionType) {
+        for (PsiType conjunct : ((PsiIntersectionType) qualifierType).getConjuncts()) {
+          processClassQualifierType(processor, conjunct);
         }
       } else {
-        if (qualifierType instanceof PsiIntersectionType) {
-          for (PsiType conjunct : ((PsiIntersectionType) qualifierType).getConjuncts()) {
-            processClassQualifierType(refExpr, processor, conjunct);
-          }
-        } else {
-          processClassQualifierType(refExpr, processor, qualifierType);
-          if (qualifier instanceof GrReferenceExpression) {
-            PsiElement resolved = ((GrReferenceExpression) qualifier).resolve();
-            if (resolved instanceof PsiClass) { //omitted .class
-              PsiClass javaLangClass = PsiUtil.getJavaLangClass(resolved, refExpr.getResolveScope());
-              if (javaLangClass != null) {
-                ResolveState state = ResolveState.initial();
-                PsiTypeParameter[] typeParameters = javaLangClass.getTypeParameters();
-                PsiSubstitutor substitutor = state.get(PsiSubstitutor.KEY);
-                if (substitutor == null) substitutor = PsiSubstitutor.EMPTY;
-                if (typeParameters.length == 1) {
-                  substitutor = substitutor.put(typeParameters[0], qualifierType);
-                  state = state.put(PsiSubstitutor.KEY, substitutor);
-                }
-                if (!javaLangClass.processDeclarations(processor, state, null, refExpr)) return;
-                PsiType javaLangClassType = JavaPsiFacade.getInstance(refExpr.getProject()).getElementFactory().createType(javaLangClass, substitutor);
-                ResolveUtil.processNonCodeMethods(javaLangClassType, processor, refExpr, false);
+        processClassQualifierType(processor, qualifierType);
+        if (qualifier instanceof GrReferenceExpression) {
+          PsiElement resolved = ((GrReferenceExpression) qualifier).resolve();
+          if (resolved instanceof PsiClass) { //omitted .class
+            PsiClass javaLangClass = PsiUtil.getJavaLangClass(resolved, getResolveScope());
+            if (javaLangClass != null) {
+              ResolveState state = ResolveState.initial();
+              PsiTypeParameter[] typeParameters = javaLangClass.getTypeParameters();
+              PsiSubstitutor substitutor = state.get(PsiSubstitutor.KEY);
+              if (substitutor == null) substitutor = PsiSubstitutor.EMPTY;
+              if (typeParameters.length == 1) {
+                substitutor = substitutor.put(typeParameters[0], qualifierType);
+                state = state.put(PsiSubstitutor.KEY, substitutor);
               }
+              if (!javaLangClass.processDeclarations(processor, state, null, this)) return;
+              PsiType javaLangClassType = JavaPsiFacade.getInstance(getProject()).getElementFactory().createType(javaLangClass, substitutor);
+              ResolveUtil.processNonCodeMethods(javaLangClassType, processor, this, false);
             }
           }
         }
       }
     }
+  }
 
-    private static void processClassQualifierType(GrReferenceExpressionImpl refExpr, ResolverProcessor processor, PsiType qualifierType) {
-      Project project = refExpr.getProject();
-      if (qualifierType instanceof PsiClassType) {
-        PsiClassType.ClassResolveResult qualifierResult = ((PsiClassType) qualifierType).resolveGenerics();
-        PsiClass qualifierClass = qualifierResult.getElement();
-        if (qualifierClass != null) {
-          if (!qualifierClass.processDeclarations(processor,
-                  ResolveState.initial().put(PsiSubstitutor.KEY, qualifierResult.getSubstitutor()), null, refExpr))
-            return;
-        }
-        if (!ResolveUtil.processCategoryMembers(refExpr, processor)) return;
-      } else if (qualifierType instanceof PsiArrayType) {
-        final GrTypeDefinition arrayClass = GroovyPsiManager.getInstance(project).getArrayClass();
-        if (!arrayClass.processDeclarations(processor, ResolveState.initial(), null, refExpr)) return;
-      } else if (qualifierType instanceof PsiIntersectionType) {
-        for (PsiType conjunct : ((PsiIntersectionType) qualifierType).getConjuncts()) {
-          processClassQualifierType(refExpr, processor, conjunct);
-        }
-        return;
+  private void processClassQualifierType(ResolverProcessor processor, PsiType qualifierType) {
+    Project project = getProject();
+    if (qualifierType instanceof PsiClassType) {
+      PsiClassType.ClassResolveResult qualifierResult = ((PsiClassType) qualifierType).resolveGenerics();
+      PsiClass qualifierClass = qualifierResult.getElement();
+      if (qualifierClass != null) {
+        if (!qualifierClass.processDeclarations(processor,
+                                                ResolveState.initial().put(PsiSubstitutor.KEY, qualifierResult.getSubstitutor()), null, this))
+          return;
+      }
+      if (!ResolveUtil.processCategoryMembers(this, processor)) return;
+    } else if (qualifierType instanceof PsiArrayType) {
+      final GrTypeDefinition arrayClass = GroovyPsiManager.getInstance(project).getArrayClass();
+      if (!arrayClass.processDeclarations(processor, ResolveState.initial(), null, this)) return;
+    } else if (qualifierType instanceof PsiIntersectionType) {
+      for (PsiType conjunct : ((PsiIntersectionType) qualifierType).getConjuncts()) {
+        processClassQualifierType(processor, conjunct);
       }
+      return;
+    }
 
-      ResolveUtil.processNonCodeMethods(qualifierType, processor, refExpr, false);
+    ResolveUtil.processNonCodeMethods(qualifierType, processor, this, false);
+  }
+
+  @Nullable
+  public MethodResolverProcessor runMethodResolverProcessor(PsiType[] argTypes, final boolean allVariants) {
+    final String name = getReferenceName();
+    if (name == null) {
+      return null;
     }
+
+    PsiType thisType = getThisType();
+
+    MethodResolverProcessor methodResolver = new MethodResolverProcessor(name, this, false, thisType, argTypes, getTypeArguments(), allVariants);
+    resolveImpl(methodResolver);
+    return methodResolver;
   }
 
-  private static PsiType getThisType(GrReferenceExpression refExpr) {
-    GrExpression qualifier = refExpr.getQualifierExpression();
+  private PsiType getThisType() {
+    GrExpression qualifier = getQualifierExpression();
     if (qualifier != null) {
       PsiType qType = qualifier.getType();
       if (qType != null) return qType;
     }
 
-    return TypesUtil.getJavaLangObject(refExpr);
+    return TypesUtil.getJavaLangObject(this);
   }
 
 
index f3d736fb87bc100710c88847e5a0d1a6934aa7a5..26a0d6868e645c4f0f0ed9b0bae1f8ef63d10a77 100644 (file)
@@ -233,6 +233,23 @@ public class TypesUtil {
   }
 
   public static boolean isAssignable(PsiType lType, PsiType rType, GroovyPsiElement context, boolean allowConversion) {
+    if (rType instanceof PsiIntersectionType) {
+      for (PsiType child : ((PsiIntersectionType)rType).getConjuncts()) {
+        if (isAssignable(lType, child, context, allowConversion)) {
+          return true;
+        }
+      }
+      return false;
+    }
+    if (lType instanceof PsiIntersectionType) {
+      for (PsiType child : ((PsiIntersectionType)lType).getConjuncts()) {
+        if (!isAssignable(child, rType, context, allowConversion)) {
+          return false;
+        }
+      }
+      return true;
+    }
+
     if (allowConversion && lType != null && rType != null) {
       for (GrTypeConverter converter : GrTypeConverter.EP_NAME.getExtensions()) {
         final Boolean result = converter.isConvertible(lType, rType, context);
@@ -267,7 +284,20 @@ public class TypesUtil {
   }
 
   public static boolean isAssignableByMethodCallConversion(PsiType lType, PsiType rType, GroovyPsiElement context) {
-    return isAssignableByMethodCallConversion(lType, rType, context.getManager(), context.getResolveScope());
+    if (lType == null || rType == null) return false;
+
+    if (isAssignableByMethodCallConversion(lType, rType, context.getManager(), context.getResolveScope())) {
+      return true;
+    }
+
+    for (GrTypeConverter converter : GrTypeConverter.EP_NAME.getExtensions()) {
+      final Boolean result = converter.isConvertible(lType, rType, context);
+      if (result != null) {
+        return result;
+      }
+    }
+
+    return false;
   }
 
   public static boolean isAssignableByMethodCallConversion(PsiType lType, PsiType rType, PsiManager manager, GlobalSearchScope scope) {
index 720b0dcc0cd06943d8922a011ec34a18dc3258ec..5a7033e7aefcc194c2cc0b496003056a59fce33c 100644 (file)
@@ -41,9 +41,9 @@ import org.jetbrains.plugins.groovy.lang.psi.impl.statements.expressions.GrRefer
 import org.jetbrains.plugins.groovy.lang.psi.impl.statements.expressions.TypesUtil;
 import org.jetbrains.plugins.groovy.lang.psi.util.PsiUtil;
 import org.jetbrains.plugins.groovy.lang.resolve.ResolveUtil;
+import org.jetbrains.plugins.groovy.lang.resolve.processors.MethodResolverProcessor;
 
 import java.util.ArrayList;
-import java.util.Arrays;
 
 /**
  * @author ilyas
@@ -187,21 +187,17 @@ public class GrMethodCallExpressionImpl extends GrCallExpressionImpl implements
   }
 
   @NotNull
-  public GroovyResolveResult[] getMethodVariants() {
+  public GroovyResolveResult[] getMethodVariants(@Nullable GrExpression upToArgument) {
     final GrExpression invoked = getInvokedExpression();
-    if (!(invoked instanceof GrReferenceExpression)) return GroovyResolveResult.EMPTY_ARRAY;
-    final ArrayList<GroovyResolveResult> res = new ArrayList<GroovyResolveResult>();
-
-    for (PsiReference ref : invoked.getReferences()) {
-      if (ref instanceof PsiPolyVariantReference) {
-        for (ResolveResult result : ((PsiPolyVariantReference)ref).multiResolve(true)) {
-          if (result instanceof GroovyResolveResult) {
-            res.add((GroovyResolveResult)result);
-          }
-        }
-      }
+    if (!(invoked instanceof GrReferenceExpressionImpl)) return GroovyResolveResult.EMPTY_ARRAY;
+
+    final PsiType[] partialArgs = PsiUtil.getArgumentTypes(invoked, false, upToArgument);
+    final MethodResolverProcessor processor = ((GrReferenceExpressionImpl)invoked).runMethodResolverProcessor(partialArgs, true);
+    if (processor != null) {
+      return processor.getCandidates();
     }
-    return res.toArray(new GroovyResolveResult[res.size()]);
+
+    return GroovyResolveResult.EMPTY_ARRAY;
   }
 
 }
index 2f6af4b020c7e56176fe566136dcdffb730aa3b7..67b76bf82b5bbb9c00c9f10f5dac6c7e00baf85d 100644 (file)
@@ -42,7 +42,7 @@ public class GroovyExpressionPattern<T extends GrExpression, Self extends Groovy
   public GroovyMethodCallPattern methodCall(final ElementPattern<? extends PsiMethod> method) {
     return new GroovyMethodCallPattern().and(this).with(new PatternCondition<GrCallExpression>("methodCall") {
       public boolean accepts(@NotNull GrCallExpression callExpression, ProcessingContext context) {
-        final GroovyResolveResult[] results = callExpression.getMethodVariants();
+        final GroovyResolveResult[] results = callExpression.getMethodVariants(null);
         for (GroovyResolveResult result : results) {
           if (method.getCondition().accepts(result.getElement(), context)) {
             return true;
@@ -72,4 +72,4 @@ public class GroovyExpressionPattern<T extends GrExpression, Self extends Groovy
     }
 
   }
-}
\ No newline at end of file
+}
index 62d7b3f89f7e658026f7ced43d8ebcd01472b9c9..71266e9338324cc98d50fcb40acd027f9f32d751 100644 (file)
@@ -175,6 +175,10 @@ public class PsiUtil {
 
   @Nullable
   public static PsiType[] getArgumentTypes(PsiElement place, boolean nullAsBottom) {
+    return getArgumentTypes(place, nullAsBottom, null);
+  }
+  @Nullable
+  public static PsiType[] getArgumentTypes(PsiElement place, boolean nullAsBottom, @Nullable GrExpression stopAt) {
     PsiElement parent = place.getParent();
     if (parent instanceof GrCallExpression) {
       List<PsiType> result = new ArrayList<PsiType>();
@@ -193,6 +197,9 @@ public class PsiUtil {
         } else {
           result.add(type);
         }
+        if (stopAt == expression) {
+          return result.toArray(new PsiType[result.size()]);
+        }
       }
 
       GrClosableBlock[] closures = call.getClosureArguments();
@@ -201,6 +208,9 @@ public class PsiUtil {
         if (closureType != null) {
           result.add(closureType);
         }
+        if (stopAt == closure) {
+          break;
+        }
       }
 
       return result.toArray(new PsiType[result.size()]);
@@ -224,6 +234,9 @@ public class PsiUtil {
         } else {
           result.add(type);
         }
+        if (stopAt == expression) {
+          break;
+        }
       }
 
       return result.toArray(new PsiType[result.size()]);
@@ -245,6 +258,10 @@ public class PsiUtil {
         else {
           result.add(argType);
         }
+        if (stopAt == arg) {
+          break;
+        }
+
       }
       return result.toArray(new PsiType[result.size()]);
     } else if (parent instanceof GrConstructorInvocation || parent instanceof GrEnumConstant) {
@@ -264,6 +281,10 @@ public class PsiUtil {
         } else {
           result.add(type);
         }
+        if (stopAt == expression) {
+          break;
+        }
+
       }
 
       return result.toArray(new PsiType[result.size()]);
@@ -603,7 +624,7 @@ public class PsiUtil {
   }
 
   public static boolean isRawMethodCall(GrMethodCallExpression call) {
-    final GroovyResolveResult[] resolveResults = call.getMethodVariants();
+    final GroovyResolveResult[] resolveResults = call.getMethodVariants(null);
     if (resolveResults.length == 0) return false;
     final PsiElement element = resolveResults[0].getElement();
     if (element instanceof PsiMethod) {
index 080c3de1fe9fcb3f4e6f475b6f7f071211a942d8..49a3ed5858e73cc13194ac5bbf403131924dcefb 100644 (file)
@@ -444,7 +444,7 @@ public class ResolveUtil {
     final PsiElement parent = place.getParent();
     GroovyResolveResult[] variants = GroovyResolveResult.EMPTY_ARRAY;
     if (parent instanceof GrCallExpression) {
-      variants = ((GrCallExpression) parent).getMethodVariants();
+      variants = ((GrCallExpression) parent).getMethodVariants(place instanceof GrExpression ? (GrExpression)place : null);
     } else if (parent instanceof GrConstructorInvocation) {
       final PsiClass clazz = ((GrConstructorInvocation) parent).getDelegatedClass();
       if (clazz != null) {
index 901e599a4eef23f52139b1943f82415ee311e6f6..3e225918b13654165b622e934bc3415168a06f65 100644 (file)
@@ -50,6 +50,7 @@ public class MethodResolverProcessor extends ResolverProcessor {
   @Nullable
   private final PsiType[] myArgumentTypes;
   private final PsiType[] myTypeArguments;
+  private final boolean myAllVariants;
 
   private final Set<GroovyResolveResult> myInapplicableCandidates = new LinkedHashSet<GroovyResolveResult>();
   private final boolean myIsConstructor;
@@ -57,11 +58,15 @@ public class MethodResolverProcessor extends ResolverProcessor {
   private boolean myStopExecuting = false;
 
   public MethodResolverProcessor(String name, GroovyPsiElement place, boolean isConstructor, PsiType thisType, @Nullable PsiType[] argumentTypes, PsiType[] typeArguments) {
+    this(name, place, isConstructor, thisType, argumentTypes, typeArguments, false);
+  }
+  public MethodResolverProcessor(String name, GroovyPsiElement place, boolean isConstructor, PsiType thisType, @Nullable PsiType[] argumentTypes, PsiType[] typeArguments, boolean allVariants) {
     super(name, EnumSet.of(ResolveKind.METHOD, ResolveKind.PROPERTY), place, PsiType.EMPTY_ARRAY);
     myIsConstructor = isConstructor;
     myThisType = thisType;
     myArgumentTypes = argumentTypes;
     myTypeArguments = typeArguments;
+    myAllVariants = allVariants;
   }
 
   public boolean execute(PsiElement element, ResolveState state) {
@@ -78,7 +83,7 @@ public class MethodResolverProcessor extends ResolverProcessor {
       boolean isAccessible = isAccessible(method);
       GroovyPsiElement fileResolveContext = state.get(RESOLVE_CONTEXT);
       boolean isStaticsOK = isStaticsOK(method, fileResolveContext);
-      if (PsiUtil.isApplicable(myArgumentTypes, method, substitutor, fileResolveContext instanceof GrMethodCallExpression, (GroovyPsiElement)myPlace) && isStaticsOK) {
+      if (!myAllVariants && PsiUtil.isApplicable(myArgumentTypes, method, substitutor, fileResolveContext instanceof GrMethodCallExpression, (GroovyPsiElement)myPlace) && isStaticsOK) {
         myCandidates.add(new GroovyResolveResultImpl(method, fileResolveContext, substitutor, isAccessible, isStaticsOK));
       } else {
         myInapplicableCandidates.add(new GroovyResolveResultImpl(method, fileResolveContext, substitutor, isAccessible, isStaticsOK));
@@ -213,6 +218,10 @@ public class MethodResolverProcessor extends ResolverProcessor {
 
   @NotNull
   public GroovyResolveResult[] getCandidates() {
+    if (myAllVariants) {
+      return myInapplicableCandidates.toArray(new GroovyResolveResult[myInapplicableCandidates.size()]);
+    }
+
     if (!myCandidates.isEmpty()) {
       return filterCandidates();
     }
diff --git a/plugins/groovy/test/org/jetbrains/plugins/groovy/compiler/GppCompilerTest.groovy b/plugins/groovy/test/org/jetbrains/plugins/groovy/compiler/GppCompilerTest.groovy
new file mode 100644 (file)
index 0000000..3de2fac
--- /dev/null
@@ -0,0 +1,61 @@
+/*
+ * 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.compiler;
+
+
+import com.intellij.testFramework.PsiTestUtil
+import org.jetbrains.plugins.groovy.util.TestUtils
+
+/**
+ * @author peter
+ */
+public class GppCompilerTest extends GroovyCompilerTestCase {
+  @Override protected void setUp() {
+    super.setUp();
+    PsiTestUtil.addLibrary myFixture.module, "gpp", TestUtils.absoluteTestDataPath + "/realGroovypp/", "groovypp-all-0.2.13.jar"
+  }
+
+  public void testTraitStubs() throws Throwable {
+    myFixture.addFileToProject("A.groovy", """
+@Trait
+abstract class SomeTrait {
+  abstract def some()
+  def concrete() {}
+}
+
+@Trait
+abstract class AnotherTrait extends SomeTrait {
+  abstract def another()
+}
+
+class Goo implements SomeTrait {
+  def some() {}
+}
+class Bar implements AnotherTrait {
+  def some() {}
+  def another() {}
+}
+""");
+    myFixture.addClass("""
+class Foo implements SomeTrait {
+  public Object some() { return null; }
+  public Object concrete() { return null; }
+}""")
+    assertEmpty(make());
+  }
+
+}
index a1165622bdaa22f776c6fa44f33a35c90ea4d84e..5fa105608aee72be237d6acf2ced10fb3c59feaa 100644 (file)
@@ -27,6 +27,10 @@ import junit.framework.AssertionFailedError
  * @author peter
  */
 public class GroovyCompilerTest extends GroovyCompilerTestCase {
+  @Override protected void setUp() {
+    super.setUp();
+    addGroovyLibrary(myModule, getName().contains("1_7"));
+  }
 
   public void testPlainGroovy() throws Throwable {
     myFixture.addFileToProject("A.groovy", "println '239'");
index 1ed0cf0d6444b2b45bb1bed0e4cfedf89257a8cd..2f695bf97438a52830c15862171ff75a42bc4827 100644 (file)
@@ -71,8 +71,6 @@ public abstract class GroovyCompilerTestCase extends JavaCodeInsightFixtureTestC
         CompilerProjectExtension.getInstance(getProject()).setCompilerOutputUrl(myMainOutput.findOrCreateDir("out").getUrl());
       }
     }.execute();
-
-    addGroovyLibrary(myModule, getName().contains("1_7"));
   }
 
   @Override
index 6c26a5010bc44b53ad4bd88812a3fa81cf433fd5..345efb7e3450e34f9ebad20f4e068ae54ae38bbf 100644 (file)
@@ -36,17 +36,17 @@ class GppFunctionalTest extends LightCodeInsightFixtureTestCase {
     super.setUp()
   }
 
-  public void _testCastListToIterable() throws Exception {
+  public void testCastListToIterable() throws Exception {
     myFixture.addClass("class X extends java.util.ArrayList<Integer> {}")
     testAssignability """
 X ints = [239, 4.2d]
 """
   }
 
-  public void _testCastListToAnything() throws Exception {
+  public void testCastListToAnything() throws Exception {
     testAssignability """
 File f1 = ['path']
-File f2 = <warning descr="Cannot assign 'List' to 'File'">['path', 2, true, 42]</warning>
+File f2 = <warning descr="Cannot assign 'List<Serializable>' to 'File'">['path', 2, true, 42]</warning>
 """
   }
 
@@ -323,7 +323,7 @@ class BarImpl extends Bar {}
     return myFixture.file.findReferenceAt(myFixture.editor.caretModel.offset).resolve()
   }
 
-  public void _testMethodTypeParameterInference() throws Exception {
+  public void testMethodTypeParameterInference() throws Exception {
     configureScript """
 @Typed package aaa
 
@@ -334,7 +334,7 @@ r.apply { it.intV<caret>i }
     assertSameElements myFixture.getLookupElementStrings(), "intValue"
   }
 
-  public void _testMethodTypeParameterInference2() throws Exception {
+  public void testMethodTypeParameterInference2() throws Exception {
     configureScript """
 @Typed package aaa
 
@@ -385,4 +385,4 @@ class GppProjectDescriptor extends DefaultLightProjectDescriptor {
     modifiableModel.addRoot(JarFileSystem.instance.refreshAndFindFileByPath(TestUtils.mockGroovy1_7LibraryName + "!/"), OrderRootType.CLASSES);
     modifiableModel.commit();
   }
-}
\ No newline at end of file
+}
index be1878b6974db58a6a09bfaef3cf0155a813cd03..f0b8f175ba66dee9ff40cc65150ec0b23853861e 100644 (file)
@@ -1,3 +1,3 @@
 def foo(int... i) {}
 def list = [1, 2, 3]
-foo<warning descr="'foo' in 'SignatureIsNotApplicableToList' cannot be applied to '([java.lang.Integer, java.lang.Integer, java.lang.Integer])'">(list)</warning>
\ No newline at end of file
+foo<warning descr="'foo' in 'SignatureIsNotApplicableToList' cannot be applied to '([java.lang.Integer, java.lang.Integer,...])'">(list)</warning>
\ No newline at end of file
diff --git a/plugins/groovy/testdata/realGroovypp/groovypp-all-0.2.13.jar b/plugins/groovy/testdata/realGroovypp/groovypp-all-0.2.13.jar
new file mode 100644 (file)
index 0000000..38fb41b
Binary files /dev/null and b/plugins/groovy/testdata/realGroovypp/groovypp-all-0.2.13.jar differ
index 23c63070a133225bd2eb873d925f873081aa4cbe..5e545c5270c5896660232f55b04e4dcde9276a10 100644 (file)
@@ -30,6 +30,7 @@
     <testFramework implementation="com.intellij.execution.junit.JUnit3Framework"/>
     <testFramework implementation="com.intellij.execution.junit.JUnit4Framework"/>
     <configurationType implementation="com.intellij.execution.junit.JUnitConfigurationType"/>
+    <stacktrace.fold substring="at org.junit.internal.runners."/>
   </extensions>
 
   <extensionPoints>
index ae57f1e7d8e04ff30af7eca2548f9db02ba66466..590e9f2ba0b161ace07ee92e3dfbf7be9a038df5 100644 (file)
@@ -80,6 +80,8 @@ public class JUnitUnusedCodeExtension extends UnusedCodeExtension {
   }
 
   public void writeExternal(Element element) throws WriteExternalException {
-    DefaultJDOMExternalizer.writeExternal(this, element);
+    if (!ADD_JUNIT_TO_ENTRIES) {
+      DefaultJDOMExternalizer.writeExternal(this, element);
+    }
   }
 }
\ No newline at end of file
similarity index 98%
rename from plugins/relaxng/test/org/intellij/plugins/relaxNG/XmlHighlightingTest.java
rename to plugins/relaxng/test/org/intellij/plugins/relaxNG/RngXmlHighlightingTest.java
index c15b098bed82dd2136cf1790a39f6b9f980e652d..2b215902d373b4c31b9a214dcac1edb29848966e 100644 (file)
@@ -26,7 +26,7 @@ import org.intellij.plugins.testUtil.CopyFile;
  * User: sweinreuter
  * Date: 25.07.2007
  */
-public class XmlHighlightingTest extends HighlightingTestBase {
+public class RngXmlHighlightingTest extends HighlightingTestBase {
 
   public String getTestDataPath() {
     return "highlighting";
similarity index 97%
rename from plugins/relaxng/test/org/intellij/plugins/relaxNG/XmlValidationTest.java
rename to plugins/relaxng/test/org/intellij/plugins/relaxNG/RngXmlValidationTest.java
index 6834b6ea27f99cff1e4aabcd2cb7b0b1a4c0e9f8..5d8e5249caf337458552d640a5736955dfe3dcd6 100644 (file)
@@ -27,7 +27,7 @@ import java.io.File;
  * User: sweinreuter
  * Date: 25.07.2007
  */
-public class XmlValidationTest extends HighlightingTestBase {
+public class RngXmlValidationTest extends HighlightingTestBase {
 
   public void testValidDocument() throws Throwable {
     doTest("xslt.rng");
index b10c1633dd8b6a62a0c7e45d489e864e3b331336..51423d3f32bbdf44ca8f34ea922bbcd2a33d6b7e 100644 (file)
@@ -68,7 +68,9 @@ public class TestNGUnusedCodeExtension extends UnusedCodeExtension {
   }
 
   public void writeExternal(Element element) throws WriteExternalException {
-    DefaultJDOMExternalizer.writeExternal(this, element);
+    if (!ADD_TESTNG_TO_ENTRIES) {
+      DefaultJDOMExternalizer.writeExternal(this, element);
+    }
   }
 
   @Nullable
index ab8b909e8998d565af6329744f1f965c1fdff3dc..d524eb2c95bd31e6e7b60799ab2cadb84418971d 100644 (file)
@@ -86,7 +86,10 @@ public class ConvertSchemaPrefixToDefaultIntention extends PsiElementBaseIntenti
       protected void run(Result result) throws Throwable {
         final int index = ns.length() + 1;
         for (XmlTag tag : tags) {
-          tag.setName(tag.getName().substring(index));
+          final String s = tag.getName().substring(index);
+          if (s.length() > 0) {
+            tag.setName(s);
+          }
         }
         for (XmlAttribute attr : attrs) {
           attr.setValue(attr.getValue().substring(index));
index 5bfa8d865263e2fb74f3dccf3f037f089bef533d..46b6c916ec76a12eadf78ddd1d441551cebf1021 100644 (file)
@@ -94,7 +94,7 @@ public abstract class ZenCodingTemplate implements CustomLiveTemplate {
         }
         else if (c == '\'') inApostrophes = false;
       }
-      else if (i == n - 1 || (i < n - 2 && DELIMS.indexOf(c) >= 0)) {
+      else if (i == n - 1 || (i < n - 2 && DELIMS.indexOf(c) >= 0) || c == ')') {
         String key = templateKeyBuilder.toString();
         templateKeyBuilder = new StringBuilder();
         int num = parseNonNegativeInt(key);
@@ -103,8 +103,9 @@ public abstract class ZenCodingTemplate implements CustomLiveTemplate {
         }
         else {
           TemplateToken token = parseTemplateKey(key, callback);
-          if (token == null) return null;
-          result.add(token);
+          if (token != null) {
+            result.add(token);
+          }
         }
         if (i == n - 1) {
           result.add(new MarkerToken());
index 3e734d337b04dff517c8968a0ce48376f146f4d0..6c9e1c44478244cd72d892484840982fe786fdea 100644 (file)
 
 package com.intellij.psi.impl.source.resolve.reference.impl.manipulators;
 
+import com.intellij.openapi.util.Comparing;
 import com.intellij.openapi.util.TextRange;
 import com.intellij.psi.AbstractElementManipulator;
+import com.intellij.psi.PsiElement;
 import com.intellij.psi.xml.XmlText;
 import com.intellij.util.IncorrectOperationException;
 
@@ -27,14 +29,27 @@ import com.intellij.util.IncorrectOperationException;
 public class XmlTextManipulator extends AbstractElementManipulator<XmlText> {
 
   public XmlText handleContentChange(XmlText text, TextRange range, String newContent) throws IncorrectOperationException {
-
-    final StringBuilder replacement = new StringBuilder(text.getValue());
-    replacement.replace(
-      range.getStartOffset(),
-      range.getEndOffset(),
-      newContent
-    );
-    text.setValue(replacement.toString());
+    final String newValue;
+    final String value = text.getValue();
+    if (range.equals(getRangeInElement(text))) {
+      newValue = newContent;
+    }
+    else {
+      final StringBuilder replacement = new StringBuilder(value);
+      replacement.replace(
+        range.getStartOffset(),
+        range.getEndOffset(),
+        newContent
+      );
+      newValue = replacement.toString();
+    }
+    if (Comparing.equal(value, newValue)) return text;
+    if (newValue.length() > 0) {
+      text.setValue(newValue);
+    }
+    else {
+      text.deleteChildRange(text.getFirstChild(), text.getLastChild());
+    }
     return text;
   }