queue = new ArrayList<>();
-}
\ No newline at end of file
+}
+
+class DD {
+ P1> l = new L() {
+ @Override
+ void f() {
+ }
+ };
+
+ P1> l1 = new L<>();
+
+ P1
> foo() {
+ return new L<>();
+ }
+
+ String s = "";
+}
+
+class L extends P1> {
+ void f() {
+ }
+}
+
+class P1 extends P {
+}
+
+class P {
+}
+
+
+class Test1 {
+ void bar() {
+ foo(new FF<>());
+ }
+
+ void foo(F> p) {}
+}
+
+class FF extends F{}
+class F {}
\ No newline at end of file
diff --git a/java/java-tests/testData/codeInsight/daemonCodeAnalyzer/quickFix/orderEntry/A/src/x/DoTest4junit.java b/java/java-tests/testData/codeInsight/daemonCodeAnalyzer/quickFix/orderEntry/A/src/x/DoTest4junit.java
new file mode 100644
index 000000000000..8a776a67fffd
--- /dev/null
+++ b/java/java-tests/testData/codeInsight/daemonCodeAnalyzer/quickFix/orderEntry/A/src/x/DoTest4junit.java
@@ -0,0 +1,9 @@
+// "Add 'junit.jar' to classpath" "true"
+package x;
+
+public class DoTest4junit {
+ @org.junit.Test
+ void f() {
+
+ }
+}
\ No newline at end of file
diff --git a/java/java-tests/testData/codeInsight/daemonCodeAnalyzer/quickFix/renameWrongReference/before2.java b/java/java-tests/testData/codeInsight/daemonCodeAnalyzer/quickFix/renameWrongReference/before2.java
new file mode 100644
index 000000000000..478c0299f91d
--- /dev/null
+++ b/java/java-tests/testData/codeInsight/daemonCodeAnalyzer/quickFix/renameWrongReference/before2.java
@@ -0,0 +1,11 @@
+// "Rename Reference" "true"
+class c {
+ void foo(boolean b) {
+ if (b) {
+ int i = 0;
+ i++;
+ } else {
+ i++;
+ }
+ }
+}
\ No newline at end of file
diff --git a/java/java-tests/testData/codeInsight/splitIfAction/beforeOrAndMixed.java b/java/java-tests/testData/codeInsight/splitIfAction/beforeOrAndMixed.java
new file mode 100644
index 000000000000..c8a7d088f3c8
--- /dev/null
+++ b/java/java-tests/testData/codeInsight/splitIfAction/beforeOrAndMixed.java
@@ -0,0 +1,7 @@
+class C {
+ void foo() {
+ if (a || b && c) {
+ call();
+ }
+ }
+}
\ No newline at end of file
diff --git a/java/java-tests/testSrc/com/intellij/codeInsight/completion/NormalCompletionTest.groovy b/java/java-tests/testSrc/com/intellij/codeInsight/completion/NormalCompletionTest.groovy
index 246d8de10efa..f50cbfb891f7 100644
--- a/java/java-tests/testSrc/com/intellij/codeInsight/completion/NormalCompletionTest.groovy
+++ b/java/java-tests/testSrc/com/intellij/codeInsight/completion/NormalCompletionTest.groovy
@@ -888,6 +888,8 @@ public class NormalCompletionTest extends LightFixtureCompletionTestCase {
public void testNoDotOverwrite() throws Exception { doTest('.') }
+ public void testStaticInnerExtendingOuter() throws Exception { doTest() }
+
public void testNoMethodsInParameterType() {
configure()
assertOrderedEquals myFixture.lookupElementStrings, "final", "float"
diff --git a/java/java-tests/testSrc/com/intellij/codeInsight/daemon/quickFix/OrderEntryTest.java b/java/java-tests/testSrc/com/intellij/codeInsight/daemon/quickFix/OrderEntryTest.java
index 91f8ce59997f..3428eb839642 100644
--- a/java/java-tests/testSrc/com/intellij/codeInsight/daemon/quickFix/OrderEntryTest.java
+++ b/java/java-tests/testSrc/com/intellij/codeInsight/daemon/quickFix/OrderEntryTest.java
@@ -133,6 +133,10 @@ public class OrderEntryTest extends DaemonAnalyzerTestCase {
doTest("A/src/x/DoTest4.java");
}
+ public void testAddJunit4inJunit() throws Exception {
+ doTest("A/src/x/DoTest4junit.java");
+ }
+
public void testExistingJunit() throws Exception {
doTest("B/src/y/AddExistingJunit.java");
}
diff --git a/java/java-tests/testSrc/com/intellij/codeInsight/intention/SplitIfActionTest.java b/java/java-tests/testSrc/com/intellij/codeInsight/intention/SplitIfActionTest.java
index ba7002cdc621..f48054ce6a06 100644
--- a/java/java-tests/testSrc/com/intellij/codeInsight/intention/SplitIfActionTest.java
+++ b/java/java-tests/testSrc/com/intellij/codeInsight/intention/SplitIfActionTest.java
@@ -51,6 +51,12 @@ public class SplitIfActionTest extends LightCodeInsightTestCase {
checkResultByFile("/codeInsight/splitIfAction/afterOrParenthesis.java");
}
+ public void test8() throws Exception {
+ configureByFile("/codeInsight/splitIfAction/beforeOrAndMixed.java");
+ SplitIfAction action = new SplitIfAction();
+ assertFalse(action.isAvailable(getProject(), getEditor(), getFile()));
+ }
+
private void perform() throws Exception {
diff --git a/java/java-tests/testSrc/com/intellij/psi/formatter/java/JavaFormatterWrapTest.java b/java/java-tests/testSrc/com/intellij/psi/formatter/java/JavaFormatterWrapTest.java
index 493ddd23ab85..23c2dfd2167f 100644
--- a/java/java-tests/testSrc/com/intellij/psi/formatter/java/JavaFormatterWrapTest.java
+++ b/java/java-tests/testSrc/com/intellij/psi/formatter/java/JavaFormatterWrapTest.java
@@ -239,4 +239,21 @@ public class JavaFormatterWrapTest extends AbstractJavaFormatterTest {
"\n}"
);
}
+
+ public void testMultipleExpressionInSameLine() throws Exception {
+ // Inspired by IDEA-64975.
+
+ getSettings().KEEP_MULTIPLE_EXPRESSIONS_IN_ONE_LINE = true;
+ doMethodTest(
+ "int i = 1; int j = 2;",
+ "int i = 1; int j = 2;"
+ );
+
+ getSettings().KEEP_MULTIPLE_EXPRESSIONS_IN_ONE_LINE = false;
+ doMethodTest(
+ "int i = 1; int j = 2;",
+ "int i = 1;\n" +
+ "int j = 2;"
+ );
+ }
}
diff --git a/java/openapi/src/com/intellij/codeInsight/NullableNotNullManager.java b/java/openapi/src/com/intellij/codeInsight/NullableNotNullManager.java
index 004d5b7861c1..b1c5b0eb553a 100644
--- a/java/openapi/src/com/intellij/codeInsight/NullableNotNullManager.java
+++ b/java/openapi/src/com/intellij/codeInsight/NullableNotNullManager.java
@@ -48,6 +48,8 @@ public class NullableNotNullManager implements PersistentStateComponent
public static final String[] DEFAULT_NULLABLES = {AnnotationUtil.NULLABLE, "javax.annotation.Nullable", "edu.umd.cs.findbugs.annotations.Nullable"};
public static final String[] DEFAULT_NOT_NULLS = {AnnotationUtil.NOT_NULL, "javax.annotation.Nonnull", "edu.umd.cs.findbugs.annotations.NonNull"};
+ private static final Object LOCK = new Object();
+
public static NullableNotNullManager getInstance(Project project) {
return ServiceManager.getService(project, NullableNotNullManager.class);
}
@@ -90,13 +92,6 @@ public class NullableNotNullManager implements PersistentStateComponent
myDefaultNotNull = defaultNotNull;
}
- public List getNullables() {
- if (myNullables.isEmpty()) {
- Collections.addAll(myNullables, DEFAULT_NULLABLES);
- }
- return myNullables;
- }
-
public boolean isNullable(PsiModifierListOwner owner, boolean checkBases) {
return AnnotationUtil.isAnnotated(owner, getNullables(), checkBases);
}
@@ -105,9 +100,24 @@ public class NullableNotNullManager implements PersistentStateComponent
return AnnotationUtil.isAnnotated(owner, getNotNulls(), checkBases);
}
+ public List getNullables() {
+ if (myNullables.isEmpty()) {
+ synchronized (LOCK) {
+ if (myNullables.isEmpty()) {
+ Collections.addAll(myNullables, DEFAULT_NULLABLES);
+ }
+ }
+ }
+ return myNullables;
+ }
+
public List getNotNulls() {
if (myNotNulls.isEmpty()) {
- Collections.addAll(myNotNulls, DEFAULT_NOT_NULLS);
+ synchronized (LOCK) {
+ if (myNotNulls.isEmpty()) {
+ Collections.addAll(myNotNulls, DEFAULT_NOT_NULLS);
+ }
+ }
}
return myNotNulls;
}
diff --git a/java/openapi/src/com/intellij/psi/PsiDiamondType.java b/java/openapi/src/com/intellij/psi/PsiDiamondType.java
index c19564505700..926fbd99ef6b 100644
--- a/java/openapi/src/com/intellij/psi/PsiDiamondType.java
+++ b/java/openapi/src/com/intellij/psi/PsiDiamondType.java
@@ -130,14 +130,30 @@ public class PsiDiamondType extends PsiType {
}
} else if (parent instanceof PsiVariable) {
return getComponentTypes((PsiVariable)parent);
+ } else if (parent instanceof PsiReturnStatement) {
+ final PsiMethod containingMethod = PsiTreeUtil.getParentOfType(parent, PsiMethod.class);
+ if (containingMethod != null) {
+ final PsiType returnType = containingMethod.getReturnType();
+ if (returnType != null) {
+ final PsiExpression returnValue = ((PsiReturnStatement)parent).getReturnValue();
+ if (returnValue instanceof PsiNewExpression) {
+ return getComponentTypes(returnType, returnValue);
+ }
+ return getComponentTypes(returnType);
+ }
+ }
}
}
return NULL_TYPES;
}
private static PsiType[] getComponentTypes(PsiVariable declaredElement) {
- PsiType lType = declaredElement.getType();
+ final PsiType lType = declaredElement.getType();
final PsiExpression initializer = declaredElement.getInitializer();
+ return getComponentTypes(lType, initializer);
+ }
+
+ private static PsiType[] getComponentTypes(PsiType lType, PsiExpression initializer) {
if (initializer instanceof PsiNewExpression) {
final PsiNewExpression newExpression = (PsiNewExpression)initializer;
final PsiJavaCodeReferenceElement classReference = newExpression.getClassOrAnonymousClassReference();
@@ -145,7 +161,7 @@ public class PsiDiamondType extends PsiType {
final String text = classReference.getReferenceName();
if (text != null) {
final PsiClass psiClass =
- JavaPsiFacade.getInstance(declaredElement.getProject()).getResolveHelper().resolveReferencedClass(text, initializer);
+ JavaPsiFacade.getInstance(initializer.getProject()).getResolveHelper().resolveReferencedClass(text, initializer);
final PsiType substitute = substitute(psiClass, lType);
if (substitute != null) {
lType = substitute;
diff --git a/plugins/tasks/tasks-core/lib/commons-httpclient-3.1.jar b/lib/commons-httpclient-3.1-patched.jar
similarity index 91%
rename from plugins/tasks/tasks-core/lib/commons-httpclient-3.1.jar
rename to lib/commons-httpclient-3.1-patched.jar
index e9b947017405..b6a056d1ddf0 100644
Binary files a/plugins/tasks/tasks-core/lib/commons-httpclient-3.1.jar and b/lib/commons-httpclient-3.1-patched.jar differ
diff --git a/plugins/maven/facade-impl/lib/commons-logging-1.1.1.jar b/lib/commons-logging-1.1.1.jar
similarity index 100%
rename from plugins/maven/facade-impl/lib/commons-logging-1.1.1.jar
rename to lib/commons-logging-1.1.1.jar
diff --git a/lib/required_for_dist.txt b/lib/required_for_dist.txt
index add69795500e..24d54ee64caa 100644
--- a/lib/required_for_dist.txt
+++ b/lib/required_for_dist.txt
@@ -10,7 +10,9 @@ coverage-report.jar
coverage-report-idea.jar
commons-codec-1.3.jar
commons-collections.jar
+commons-httpclient-3.1-patched.jar
commons-lang-2.4.jar
+commons-logging-1.1.1.jar
emma.jar
freemarker.jar
jdom.jar
diff --git a/plugins/tasks/tasks-core/lib/commons-httpclient-3.1-src.zip b/lib/src/commons-httpclient-3.1-src-patched.zip
similarity index 99%
rename from plugins/tasks/tasks-core/lib/commons-httpclient-3.1-src.zip
rename to lib/src/commons-httpclient-3.1-src-patched.zip
index 0532af3f96fa..a08a59ba0109 100644
Binary files a/plugins/tasks/tasks-core/lib/commons-httpclient-3.1-src.zip and b/lib/src/commons-httpclient-3.1-src-patched.zip differ
diff --git a/lib/src/commons-lang-2.4-sources.jar b/lib/src/commons-lang-2.4-sources.jar
new file mode 100644
index 000000000000..7d54d0d197d7
Binary files /dev/null and b/lib/src/commons-lang-2.4-sources.jar differ
diff --git a/lib/src/commons-logging-1.1.1-src.zip b/lib/src/commons-logging-1.1.1-src.zip
new file mode 100644
index 000000000000..885f130d0ea6
Binary files /dev/null and b/lib/src/commons-logging-1.1.1-src.zip differ
diff --git a/platform/icons/src/ide/lookupAlphanumeric.png b/platform/icons/src/ide/lookupAlphanumeric.png
index 55222644f54a..12ace9cae967 100644
Binary files a/platform/icons/src/ide/lookupAlphanumeric.png and b/platform/icons/src/ide/lookupAlphanumeric.png differ
diff --git a/platform/icons/src/ide/lookupRelevance.png b/platform/icons/src/ide/lookupRelevance.png
index f04f37a0c9e9..825af769c9a9 100644
Binary files a/platform/icons/src/ide/lookupRelevance.png and b/platform/icons/src/ide/lookupRelevance.png differ
diff --git a/platform/lang-api/src/com/intellij/find/FindManager.java b/platform/lang-api/src/com/intellij/find/FindManager.java
index f4e85c0496a6..c2866ebe6d94 100644
--- a/platform/lang-api/src/com/intellij/find/FindManager.java
+++ b/platform/lang-api/src/com/intellij/find/FindManager.java
@@ -108,6 +108,16 @@ public abstract class FindManager {
public abstract FindResult findString(@NotNull CharSequence text, int offset, @NotNull FindModel model,
@Nullable VirtualFile findContextFile);
+ public static class MalformedReplacementStringException extends Exception {
+ public MalformedReplacementStringException(String s) {
+ super(s); //To change body of overridden methods use File | Settings | File Templates.
+ }
+
+ public MalformedReplacementStringException(String s, Throwable throwable) {
+ super(s, throwable); //To change body of overridden methods use File | Settings | File Templates.
+ }
+ }
+
/**
* Gets the string to replace with, given the specified found string and find/replace
* settings. Supports case-preserving and regular expression replaces.
@@ -116,8 +126,9 @@ public abstract class FindManager {
* @param model the search and replace settings, including the replace string.
* @return the string to replace the specified found string.
*/
- public abstract String getStringToReplace(@NotNull String foundString, @NotNull FindModel model);
- public abstract String getStringToReplace(@NotNull String foundString, @NotNull FindModel model, int startOffset, @NotNull String documentText);
+ public abstract String getStringToReplace(@NotNull String foundString, @NotNull FindModel model) throws MalformedReplacementStringException;
+ public abstract String getStringToReplace(@NotNull String foundString, @NotNull FindModel model,
+ int startOffset, @NotNull String documentText) throws MalformedReplacementStringException;
/**
* Gets the flag indicating whether the "Find Next" and "Find Previous" actions are
diff --git a/platform/lang-api/src/com/intellij/openapi/roots/libraries/Library.java b/platform/lang-api/src/com/intellij/openapi/roots/libraries/Library.java
index ee342b92fa66..4a2f6ae8310f 100644
--- a/platform/lang-api/src/com/intellij/openapi/roots/libraries/Library.java
+++ b/platform/lang-api/src/com/intellij/openapi/roots/libraries/Library.java
@@ -36,7 +36,7 @@ public interface Library extends JDOMExternalizable, Disposable {
@NotNull VirtualFile[] getFiles(@NotNull OrderRootType rootType);
/**
- * As soon as you obtaining modifiable model you will have to commit it or call Disposer.dispose(model)!
+ * As soon as you obtaining modifiable model you will have to commit it or call Disposer.dispose(model)!
*/
@NotNull ModifiableModel getModifiableModel();
@@ -45,9 +45,11 @@ public interface Library extends JDOMExternalizable, Disposable {
@NotNull RootProvider getRootProvider();
boolean isJarDirectory(@NotNull String url);
-
+
+ boolean isJarDirectory(@NotNull String url, @NotNull OrderRootType rootType);
+
boolean isValid(@NotNull String url, @NotNull OrderRootType rootType);
-
+
interface ModifiableModel extends Disposable {
@NotNull String[] getUrls(@NotNull OrderRootType rootType);
@@ -56,13 +58,17 @@ public interface Library extends JDOMExternalizable, Disposable {
String getName();
void addRoot(@NonNls @NotNull String url, @NotNull OrderRootType rootType);
-
+
void addJarDirectory(@NotNull String url, boolean recursive);
+ void addJarDirectory(@NotNull String url, boolean recursive, @NotNull OrderRootType rootType);
+
void addRoot(@NotNull VirtualFile file, @NotNull OrderRootType rootType);
-
+
void addJarDirectory(@NotNull VirtualFile file, boolean recursive);
+ void addJarDirectory(@NotNull VirtualFile file, boolean recursive, @NotNull OrderRootType rootType);
+
void moveRootUp(@NotNull String url, @NotNull OrderRootType rootType);
void moveRootDown(@NotNull String url, @NotNull OrderRootType rootType);
@@ -74,9 +80,11 @@ public interface Library extends JDOMExternalizable, Disposable {
@NotNull VirtualFile[] getFiles(@NotNull OrderRootType rootType);
boolean isChanged();
-
+
boolean isJarDirectory(@NotNull String url);
-
+
+ boolean isJarDirectory(@NotNull String url, @NotNull OrderRootType rootType);
+
boolean isValid(@NotNull String url, @NotNull OrderRootType rootType);
}
}
diff --git a/platform/lang-api/src/com/intellij/psi/codeStyle/CommonCodeStyleSettings.java b/platform/lang-api/src/com/intellij/psi/codeStyle/CommonCodeStyleSettings.java
index 44b1baa91379..5ac8f5bd2a22 100644
--- a/platform/lang-api/src/com/intellij/psi/codeStyle/CommonCodeStyleSettings.java
+++ b/platform/lang-api/src/com/intellij/psi/codeStyle/CommonCodeStyleSettings.java
@@ -654,6 +654,7 @@ public class CommonCodeStyleSettings {
public boolean KEEP_SIMPLE_BLOCKS_IN_ONE_LINE = false;
public boolean KEEP_SIMPLE_METHODS_IN_ONE_LINE = false;
+ public boolean KEEP_MULTIPLE_EXPRESSIONS_IN_ONE_LINE = false;
public int FOR_STATEMENT_WRAP = DO_NOT_WRAP;
public boolean FOR_STATEMENT_LPAREN_ON_NEXT_LINE = false;
diff --git a/platform/lang-api/src/com/intellij/psi/meta/MetaDataRegistrar.java b/platform/lang-api/src/com/intellij/psi/meta/MetaDataRegistrar.java
index d86356d4376f..45956f2a929e 100644
--- a/platform/lang-api/src/com/intellij/psi/meta/MetaDataRegistrar.java
+++ b/platform/lang-api/src/com/intellij/psi/meta/MetaDataRegistrar.java
@@ -22,6 +22,7 @@ import com.intellij.psi.filters.ElementFilter;
/**
* Provides association for elements matching given filter with metadata class.
+ * @see MetaDataContributor
*/
public abstract class MetaDataRegistrar {
/**
diff --git a/platform/lang-api/src/com/intellij/psi/stubs/SerializationManagerImpl.java b/platform/lang-api/src/com/intellij/psi/stubs/SerializationManagerImpl.java
index e90ab4138623..eb627af84818 100644
--- a/platform/lang-api/src/com/intellij/psi/stubs/SerializationManagerImpl.java
+++ b/platform/lang-api/src/com/intellij/psi/stubs/SerializationManagerImpl.java
@@ -13,14 +13,11 @@
* See the License for the specific language governing permissions and
* limitations under the License.
*/
-
-/*
- * @author max
- */
package com.intellij.psi.stubs;
import com.intellij.openapi.application.PathManager;
import com.intellij.openapi.components.ApplicationComponent;
+import com.intellij.openapi.diagnostic.LogUtil;
import com.intellij.openapi.diagnostic.Logger;
import com.intellij.openapi.extensions.Extensions;
import com.intellij.openapi.util.io.FileUtil;
@@ -40,6 +37,9 @@ import java.util.List;
import java.util.Map;
import java.util.concurrent.atomic.AtomicBoolean;
+/*
+ * @author max
+ */
public class SerializationManagerImpl extends SerializationManager implements ApplicationComponent {
private static final Logger LOG = Logger.getInstance("#com.intellij.psi.stubs.SerializationManagerImpl");
@@ -213,7 +213,7 @@ public class SerializationManagerImpl extends SerializationManager implements Ap
private int getClassId(final StubSerializer serializer) {
final Integer idValue = mySerializerToId.get(serializer);
- assert idValue != null: "No ID found for serializer " + serializer;
+ assert idValue != null: "No ID found for serializer " + LogUtil.objectAndClass(serializer);
return idValue.intValue();
}
@@ -238,4 +238,3 @@ public class SerializationManagerImpl extends SerializationManager implements Ap
}
}
}
-
diff --git a/platform/lang-api/src/com/intellij/psi/stubs/StubSerializer.java b/platform/lang-api/src/com/intellij/psi/stubs/StubSerializer.java
index a254367c4ff1..d39204ee5010 100644
--- a/platform/lang-api/src/com/intellij/psi/stubs/StubSerializer.java
+++ b/platform/lang-api/src/com/intellij/psi/stubs/StubSerializer.java
@@ -13,16 +13,15 @@
* See the License for the specific language governing permissions and
* limitations under the License.
*/
-
-/*
- * @author max
- */
package com.intellij.psi.stubs;
import org.jetbrains.annotations.NonNls;
import java.io.IOException;
+/*
+ * @author max
+ */
public interface StubSerializer {
@NonNls
String getExternalId();
diff --git a/platform/lang-api/src/com/intellij/refactoring/rename/RenameHandler.java b/platform/lang-api/src/com/intellij/refactoring/rename/RenameHandler.java
index 4ffe0a97d2ba..06995b47fea8 100644
--- a/platform/lang-api/src/com/intellij/refactoring/rename/RenameHandler.java
+++ b/platform/lang-api/src/com/intellij/refactoring/rename/RenameHandler.java
@@ -28,6 +28,6 @@ public interface RenameHandler extends RefactoringActionHandler {
// called during rename action update. should not perform any user interactions
boolean isAvailableOnDataContext(DataContext dataContext);
- // called on rename actionPeformed. Can obtain additional info from user
+ // called on rename actionPerformed. Can obtain additional info from user
boolean isRenaming(DataContext dataContext);
}
diff --git a/platform/lang-impl/src/com/intellij/application/options/codeStyle/WrappingAndBracesPanel.java b/platform/lang-impl/src/com/intellij/application/options/codeStyle/WrappingAndBracesPanel.java
index 038e7608b7c5..f71cb326b960 100644
--- a/platform/lang-impl/src/com/intellij/application/options/codeStyle/WrappingAndBracesPanel.java
+++ b/platform/lang-impl/src/com/intellij/application/options/codeStyle/WrappingAndBracesPanel.java
@@ -36,7 +36,7 @@ public class WrappingAndBracesPanel extends OptionTableWithPreviewPanel {
addOption("KEEP_CONTROL_STATEMENT_IN_ONE_LINE", ApplicationBundle.message("checkbox.keep.when.reformatting.control.statement.in.one.line"),
WRAPPING_KEEP);
addOption("KEEP_SIMPLE_BLOCKS_IN_ONE_LINE", ApplicationBundle.message("wrapping.keep.simple.blocks.in.one.line"), WRAPPING_KEEP);
- addOption("KEEP_SIMPLE_METHODS_IN_ONE_LINE", ApplicationBundle.message("wrapping.keep.simple.methods.in.one.line"), WRAPPING_KEEP);
+ addOption("KEEP_MULTIPLE_EXPRESSIONS_IN_ONE_LINE", ApplicationBundle.message("wrapping.keep.multiple.expressions.in.one.line"), WRAPPING_KEEP);
addOption("CLASS_BRACE_STYLE", ApplicationBundle.message("wrapping.brace.placement.class.declaration"), WRAPPING_BRACES, BRACE_PLACEMENT_OPTIONS, BRACE_PLACEMENT_VALUES);
addOption("METHOD_BRACE_STYLE", ApplicationBundle.message("wrapping.brace.placement.method.declaration"), WRAPPING_BRACES, BRACE_PLACEMENT_OPTIONS, BRACE_PLACEMENT_VALUES);
diff --git a/platform/lang-impl/src/com/intellij/codeInsight/AutoPopupController.java b/platform/lang-impl/src/com/intellij/codeInsight/AutoPopupController.java
index b7fa21d6f424..d058ddc4c223 100644
--- a/platform/lang-impl/src/com/intellij/codeInsight/AutoPopupController.java
+++ b/platform/lang-impl/src/com/intellij/codeInsight/AutoPopupController.java
@@ -110,7 +110,7 @@ public class AutoPopupController implements Disposable {
}
public void invokeAutoPopupRunnable(final Runnable request, final int delay) {
- if (ApplicationManager.getApplication().isUnitTestMode()) return;
+ if (ApplicationManager.getApplication().isUnitTestMode() && !CompletionAutoPopupHandler.ourTestingAutopopup) return;
final CompletionProgressIndicator currentCompletion = CompletionServiceImpl.getCompletionService().getCurrentCompletion();
if (currentCompletion != null) {
currentCompletion.closeAndFinish(true);
diff --git a/platform/lang-impl/src/com/intellij/codeInsight/CodeInsightSettings.java b/platform/lang-impl/src/com/intellij/codeInsight/CodeInsightSettings.java
index 23fcdf2cb11a..d08d346ce5f8 100644
--- a/platform/lang-impl/src/com/intellij/codeInsight/CodeInsightSettings.java
+++ b/platform/lang-impl/src/com/intellij/codeInsight/CodeInsightSettings.java
@@ -103,6 +103,7 @@ public class CodeInsightSettings implements PersistentStateComponent, C
public boolean INSERT_SCRIPTLET_END_ON_ENTER = true;
public boolean JAVADOC_STUB_ON_ENTER = true;
public boolean SMART_END_ACTION = true;
+ public boolean JAVADOC_GENERATE_CLOSING_TAG = true;
public boolean SURROUND_SELECTION_ON_QUOTE_TYPED = false;
diff --git a/platform/lang-impl/src/com/intellij/codeInsight/completion/CompletionProgressIndicator.java b/platform/lang-impl/src/com/intellij/codeInsight/completion/CompletionProgressIndicator.java
index 4990fa38d95f..b268d6ef78d1 100644
--- a/platform/lang-impl/src/com/intellij/codeInsight/completion/CompletionProgressIndicator.java
+++ b/platform/lang-impl/src/com/intellij/codeInsight/completion/CompletionProgressIndicator.java
@@ -181,7 +181,10 @@ public class CompletionProgressIndicator extends ProgressIndicatorBase implement
public void setFocusLookupWhenDone(boolean focusLookup) {
LOG.assertTrue(isAutopopupCompletion());
if (focusLookup) {
- ((CompletionPhase.BgCalculation)CompletionServiceImpl.getCompletionPhase()).focusLookupWhenDone = true;
+ final CompletionPhase phase = CompletionServiceImpl.getCompletionPhase();
+ if (!(phase instanceof CompletionPhase.Restarted)) {
+ ((CompletionPhase.BgCalculation)phase).focusLookupWhenDone = true;
+ }
} else {
myLookup.setAdvertisementText("Press " +
CompletionContributor.getActionShortcut(IdeActions.ACTION_CHOOSE_LOOKUP_ITEM_REPLACE) +
@@ -378,10 +381,11 @@ public class CompletionProgressIndicator extends ProgressIndicatorBase implement
}
public void closeAndFinish(boolean hideLookup) {
- LOG.assertTrue(this == CompletionServiceImpl.getCompletionService().getCurrentCompletion());
+ final CompletionProgressIndicator current = CompletionServiceImpl.getCompletionService().getCurrentCompletion();
+ LOG.assertTrue(this == current, current);
Lookup lookup = LookupManager.getActiveLookup(myEditor);
- LOG.assertTrue(lookup == myLookup);
+ LOG.assertTrue(lookup == myLookup, lookup);
myLookup.removeLookupListener(myLookupListener);
finishCompletionProcess();
CompletionServiceImpl.assertPhase(CompletionPhase.NoCompletion.getClass());
@@ -410,6 +414,9 @@ public class CompletionProgressIndicator extends ProgressIndicatorBase implement
CompletionProgressIndicator currentCompletion = CompletionServiceImpl.getCompletionService().getCurrentCompletion();
if (currentCompletion != null) {
currentCompletion.finishCompletionProcess();
+ CompletionServiceImpl.assertPhase(CompletionPhase.NoCompletion.getClass());
+ } else {
+ CompletionServiceImpl.setCompletionPhase(CompletionPhase.NoCompletion);
}
}
diff --git a/platform/lang-impl/src/com/intellij/codeInsight/daemon/impl/LocalInspectionsPass.java b/platform/lang-impl/src/com/intellij/codeInsight/daemon/impl/LocalInspectionsPass.java
index afa233863370..503cd00a3c53 100644
--- a/platform/lang-impl/src/com/intellij/codeInsight/daemon/impl/LocalInspectionsPass.java
+++ b/platform/lang-impl/src/com/intellij/codeInsight/daemon/impl/LocalInspectionsPass.java
@@ -55,6 +55,7 @@ import com.intellij.profile.codeInspection.SeverityProvider;
import com.intellij.psi.*;
import com.intellij.psi.impl.source.tree.injected.InjectedLanguageUtil;
import com.intellij.util.ConcurrencyUtil;
+import com.intellij.util.Function;
import com.intellij.util.Processor;
import com.intellij.util.containers.ConcurrentHashMap;
import com.intellij.util.ui.UIUtil;
@@ -75,6 +76,7 @@ import java.util.concurrent.atomic.AtomicBoolean;
*/
public class LocalInspectionsPass extends ProgressableTextEditorHighlightingPass implements DumbAware {
private static final Logger LOG = Logger.getInstance("#com.intellij.codeInsight.daemon.impl.LocalInspectionsPass");
+ private static final int NUM_ELEMENTS_PER_CHECK_CANCELLED = 5;
private final int myStartOffset;
private final int myEndOffset;
private final TextRange myPriorityRange;
@@ -104,8 +106,15 @@ public class LocalInspectionsPass extends ProgressableTextEditorHighlightingPass
else {
myShortcutText = "";
}
- InspectionProfileWrapper customProfile = file.getUserData(InspectionProfileWrapper.KEY);
- myProfileWrapper = customProfile == null ? InspectionProjectProfileManager.getInstance(myProject).getProfileWrapper() : customProfile;
+ InspectionProfileWrapper profileToUse = InspectionProjectProfileManager.getInstance(myProject).getProfileWrapper();
+
+ Function customizationStrategy
+ = file.getUserData(InspectionProfileWrapper.CUSTOMIZATION_KEY);
+ if (customizationStrategy != null) {
+ profileToUse = customizationStrategy.fun(profileToUse);
+ }
+
+ myProfileWrapper = profileToUse;
mySeverityRegistrar = ((SeverityProvider)myProfileWrapper.getInspectionProfile().getProfileManager()).getSeverityRegistrar();
LOG.assertTrue(mySeverityRegistrar != null);
@@ -304,9 +313,10 @@ public class LocalInspectionsPass extends ProgressableTextEditorHighlightingPass
: "The visitor returned from LocalInspectionTool.buildVisitor() must not be recursive. "+tool;
tool.inspectionStarted(session);
- for (PsiElement element : elements) {
- indicator.checkCanceled();
- element.accept(visitor);
+ int size = elements.size();
+ for (int i = 0; i < size; ++i) {
+ elements.get(i).accept(visitor);
+ if (i % NUM_ELEMENTS_PER_CHECK_CANCELLED == 0) indicator.checkCanceled();
}
return visitor;
}
@@ -331,9 +341,8 @@ public class LocalInspectionsPass extends ProgressableTextEditorHighlightingPass
ProblemsHolder holder = trinity.second;
PsiElementVisitor elementVisitor = trinity.third;
for (int i = 0, elementsSize = elements.size(); i < elementsSize; i++) {
- PsiElement element = elements.get(i);
- indicator.checkCanceled();
- element.accept(elementVisitor);
+ elements.get(i).accept(elementVisitor);
+ if (i % NUM_ELEMENTS_PER_CHECK_CANCELLED == 0) indicator.checkCanceled();
}
advanceProgress(1);
diff --git a/platform/lang-impl/src/com/intellij/codeInsight/documentation/DocumentationComponent.java b/platform/lang-impl/src/com/intellij/codeInsight/documentation/DocumentationComponent.java
index 6501a6a282fd..57db3560c001 100644
--- a/platform/lang-impl/src/com/intellij/codeInsight/documentation/DocumentationComponent.java
+++ b/platform/lang-impl/src/com/intellij/codeInsight/documentation/DocumentationComponent.java
@@ -241,8 +241,9 @@ public class DocumentationComponent extends JPanel implements Disposable {
component.setBounds(0, 0, r.width, r.height);
}
else {
+ int insets = 2;
Dimension d = component.getPreferredSize();
- component.setBounds(r.width - d.width, 2, d.width, d.height);
+ component.setBounds(r.width - d.width - insets, insets, d.width, d.height);
}
}
}
diff --git a/platform/lang-impl/src/com/intellij/codeInsight/documentation/DocumentationManager.java b/platform/lang-impl/src/com/intellij/codeInsight/documentation/DocumentationManager.java
index 7863233390b4..9e2dd837d3d8 100644
--- a/platform/lang-impl/src/com/intellij/codeInsight/documentation/DocumentationManager.java
+++ b/platform/lang-impl/src/com/intellij/codeInsight/documentation/DocumentationManager.java
@@ -886,7 +886,7 @@ public class DocumentationManager {
void showHint(final JBPopup hint) {
final Lookup lookup = LookupManager.getActiveLookup(myEditor);
- if (lookup != null) {
+ if (lookup != null && lookup.getCurrentItem() != null) {
lookup.showItemPopup(hint);
return;
}
diff --git a/platform/lang-impl/src/com/intellij/codeInsight/editorActions/CompletionAutoPopupHandler.java b/platform/lang-impl/src/com/intellij/codeInsight/editorActions/CompletionAutoPopupHandler.java
index 0e8591c8a1da..5c4b2a9c575e 100644
--- a/platform/lang-impl/src/com/intellij/codeInsight/editorActions/CompletionAutoPopupHandler.java
+++ b/platform/lang-impl/src/com/intellij/codeInsight/editorActions/CompletionAutoPopupHandler.java
@@ -86,6 +86,11 @@ public class CompletionAutoPopupHandler extends TypedHandlerDelegate {
return Result.CONTINUE;
}
+ if (!CompletionServiceImpl.isPhase(CompletionPhase.AutoPopupAlarm.class, CompletionPhase.NoCompletion.getClass())) {
+ return Result.CONTINUE;
+ }
+
+
final CharSequence text = editor.getDocument().getCharsSequence();
final int offset = editor.getSelectionModel().hasSelection() ? editor.getSelectionModel().getSelectionEnd() : editor.getCaretModel().getOffset();
if (text.length() > offset && Character.isUnicodeIdentifierPart(text.charAt(offset))) {
@@ -134,11 +139,7 @@ public class CompletionAutoPopupHandler extends TypedHandlerDelegate {
}
}
};
- if (ourTestingAutopopup) {
- ApplicationManager.getApplication().invokeLater(request);
- } else {
- AutoPopupController.getInstance(project).invokeAutoPopupRunnable(request, CodeInsightSettings.getInstance().AUTO_LOOKUP_DELAY);
- }
+ AutoPopupController.getInstance(project).invokeAutoPopupRunnable(request, CodeInsightSettings.getInstance().AUTO_LOOKUP_DELAY);
return Result.STOP;
}
diff --git a/platform/lang-impl/src/com/intellij/codeInsight/editorActions/EnterHandler.java b/platform/lang-impl/src/com/intellij/codeInsight/editorActions/EnterHandler.java
index 15d369fbdceb..904372541275 100644
--- a/platform/lang-impl/src/com/intellij/codeInsight/editorActions/EnterHandler.java
+++ b/platform/lang-impl/src/com/intellij/codeInsight/editorActions/EnterHandler.java
@@ -339,7 +339,7 @@ public class EnterHandler extends BaseEnterHandler {
myOffset = codeStyleManager.adjustLineIndent(myFile, myOffset);
PsiDocumentManager.getInstance(getProject()).commitAllDocuments();
- if (!StringUtil.isEmpty(indentInsideJavadoc)) {
+ if (!StringUtil.isEmpty(indentInsideJavadoc) && myOffset < myDocument.getTextLength()) {
myDocument.insertString(myOffset + 1, indentInsideJavadoc);
myOffset += indentInsideJavadoc.length();
docIndentApplied = true;
@@ -347,7 +347,6 @@ public class EnterHandler extends BaseEnterHandler {
if (myForceIndent && indentInsideJavadoc != null) {
int indentSize = CodeStyleSettingsManager.getSettings(myProject).getIndentSize(myFile.getFileType());
- //TODO den check tabs
myDocument.insertString(myOffset + 1, StringUtil.repeatSymbol(' ', indentSize));
myCaretAdvance += indentSize;
}
diff --git a/platform/lang-impl/src/com/intellij/codeInsight/editorActions/enter/EnterAfterJavadocTagHandler.java b/platform/lang-impl/src/com/intellij/codeInsight/editorActions/enter/EnterAfterJavadocTagHandler.java
index 17792d644ce1..e59da238cd1b 100644
--- a/platform/lang-impl/src/com/intellij/codeInsight/editorActions/enter/EnterAfterJavadocTagHandler.java
+++ b/platform/lang-impl/src/com/intellij/codeInsight/editorActions/enter/EnterAfterJavadocTagHandler.java
@@ -135,8 +135,12 @@ public class EnterAfterJavadocTagHandler implements EnterHandlerDelegate {
continue;
}
- if (c == '>') {
- if (startTagEndOffset < 0) {
+ if (c == '>' && (startTagEndOffset < 0)) {
+ if (i > startOffset && text.charAt(i - 1) == '/') {
+ // Handle situation like '[offset]'
+ break;
+ }
+ else {
startTagEndOffset = i;
continue;
}
diff --git a/platform/lang-impl/src/com/intellij/codeInsight/editorActions/enter/EnterAfterUnmatchedBraceHandler.java b/platform/lang-impl/src/com/intellij/codeInsight/editorActions/enter/EnterAfterUnmatchedBraceHandler.java
index 4e1468e01aec..227d36de4395 100644
--- a/platform/lang-impl/src/com/intellij/codeInsight/editorActions/enter/EnterAfterUnmatchedBraceHandler.java
+++ b/platform/lang-impl/src/com/intellij/codeInsight/editorActions/enter/EnterAfterUnmatchedBraceHandler.java
@@ -33,6 +33,7 @@ import com.intellij.openapi.fileTypes.FileType;
import com.intellij.openapi.project.Project;
import com.intellij.openapi.util.Ref;
import com.intellij.openapi.util.TextRange;
+import com.intellij.openapi.util.text.StringUtil;
import com.intellij.psi.PsiDocumentManager;
import com.intellij.psi.PsiElement;
import com.intellij.psi.PsiFile;
@@ -52,7 +53,8 @@ public class EnterAfterUnmatchedBraceHandler implements EnterHandlerDelegate {
CharSequence text = document.getCharsSequence();
Project project = file.getProject();
int caretOffset = caretOffsetRef.get().intValue();
- if (!CodeInsightSettings.getInstance().INSERT_BRACE_ON_ENTER || !isAfterUnmatchedLBrace(editor, caretOffset, file.getFileType())) {
+ int unmatchedLBracesNumber = getUnmatchedLBracesNumberBefore(editor, caretOffset, file.getFileType());
+ if (!CodeInsightSettings.getInstance().INSERT_BRACE_ON_ENTER || unmatchedLBracesNumber <= 0) {
return Result.Continue;
}
@@ -81,7 +83,21 @@ public class EnterAfterUnmatchedBraceHandler implements EnterHandlerDelegate {
// That is formatted incorrectly because line feed between 'else' and 'if' is not inserted yet (whole 'if' block is indent anchor
// to 'if' code block('{}')). So, we insert temporary line feed between 'if' and 'else', correct indent and remove that temporary
// line feed.
- document.insertString(offset, "\n}");
+ int bracesToInsert = 0;
+ outer:
+ for (int i = caretOffset - 1; unmatchedLBracesNumber > 0 && i >= 0 && bracesToInsert < unmatchedLBracesNumber; i--) {
+ char c = text.charAt(i);
+ switch (c) {
+ case ' ':
+ case '\n':
+ case '\t':
+ continue;
+ case '{': bracesToInsert++; break;
+ default: break outer;
+ }
+ }
+ bracesToInsert = Math.max(bracesToInsert, 1);
+ document.insertString(offset, "\n" + StringUtil.repeatSymbol('}', bracesToInsert));
document.insertString(caretOffset, "\n");
PsiDocumentManager.getInstance(project).commitDocument(document);
long stamp = document.getModificationStamp();
@@ -175,37 +191,69 @@ public class EnterAfterUnmatchedBraceHandler implements EnterHandlerDelegate {
}
public static boolean isAfterUnmatchedLBrace(Editor editor, int offset, FileType fileType) {
- if (offset == 0) return false;
+ return getUnmatchedLBracesNumberBefore(editor, offset, fileType) > 0;
+ }
+
+ /**
+ * Calculates number of unmatched left braces before the given offset.
+ *
+ * @param editor target editor
+ * @param offset target offset
+ * @param fileType target file type
+ * @return number of unmatched braces before the given offset;
+ * negative value if it's not possible to perform the calculation or if there are no unmatched left braces before
+ * the given offset
+ */
+ private static int getUnmatchedLBracesNumberBefore(Editor editor, int offset, FileType fileType) {
+ if (offset == 0) {
+ return -1;
+ }
CharSequence chars = editor.getDocument().getCharsSequence();
- if (chars.charAt(offset - 1) != '{') return false;
+ if (chars.charAt(offset - 1) != '{') {
+ return -1;
+ }
EditorHighlighter highlighter = ((EditorEx)editor).getHighlighter();
HighlighterIterator iterator = highlighter.createIterator(offset - 1);
BraceMatcher braceMatcher = BraceMatchingUtil.getBraceMatcher(fileType, iterator);
- if (!braceMatcher.isLBraceToken(iterator, chars, fileType) ||
- !braceMatcher.isStructuralBrace(iterator, chars, fileType)
- ) {
- return false;
+ if (!braceMatcher.isLBraceToken(iterator, chars, fileType) || !braceMatcher.isStructuralBrace(iterator, chars, fileType)) {
+ return -1;
}
Language language = iterator.getTokenType().getLanguage();
iterator = highlighter.createIterator(0);
- int balance = 0;
- while (!iterator.atEnd()) {
+ int lBracesBeforeOffset = 0;
+ int lBracesAfterOffset = 0;
+ int rBracesBeforeOffset = 0;
+ int rBracesAfterOffset = 0;
+ for (; !iterator.atEnd(); iterator.advance()) {
IElementType tokenType = iterator.getTokenType();
- if (tokenType.getLanguage().equals(language)) {
- if (braceMatcher.isStructuralBrace(iterator, chars, fileType)) {
- if (braceMatcher.isLBraceToken(iterator, chars, fileType)) {
- balance++;
- } else if (braceMatcher.isRBraceToken(iterator, chars, fileType)) {
- balance--;
- }
+ if (!tokenType.getLanguage().equals(language) || !braceMatcher.isStructuralBrace(iterator, chars, fileType)) {
+ continue;
+ }
+
+ boolean beforeOffset = iterator.getStart() < offset;
+
+ if (braceMatcher.isLBraceToken(iterator, chars, fileType)) {
+ if (beforeOffset) {
+ lBracesBeforeOffset++;
+ }
+ else {
+ lBracesAfterOffset++;
+ }
+ }
+ else if (braceMatcher.isRBraceToken(iterator, chars, fileType)) {
+ if (beforeOffset) {
+ rBracesBeforeOffset++;
+ }
+ else {
+ rBracesAfterOffset++;
}
}
- iterator.advance();
}
- return balance > 0;
+
+ return lBracesBeforeOffset - rBracesBeforeOffset - (rBracesAfterOffset - lBracesAfterOffset);
}
}
diff --git a/platform/lang-impl/src/com/intellij/codeInsight/lookup/impl/LookupImpl.java b/platform/lang-impl/src/com/intellij/codeInsight/lookup/impl/LookupImpl.java
index 7a3540cfaf7e..bec42fbd1224 100644
--- a/platform/lang-impl/src/com/intellij/codeInsight/lookup/impl/LookupImpl.java
+++ b/platform/lang-impl/src/com/intellij/codeInsight/lookup/impl/LookupImpl.java
@@ -146,7 +146,7 @@ public class LookupImpl extends LightweightHint implements Lookup, Disposable {
getComponent().add(myScrollPane, BorderLayout.NORTH);
myScrollPane.setBorder(null);
- myAdComponent = HintUtil.createAdComponent(null);
+ myAdComponent = HintUtil.createAdComponent(null, new EmptyBorder(1, 2, 1, 2 + relevanceSortIcon.getIconWidth()));
getComponent().add(myAdComponent, BorderLayout.SOUTH);
getComponent().setBorder(new BegPopupMenuBorder());
@@ -162,7 +162,7 @@ public class LookupImpl extends LightweightHint implements Lookup, Disposable {
addListeners();
mySortingLabel = new JLabel();
- mySortingLabel.setBorder(new LineBorder(Color.DARK_GRAY));
+ mySortingLabel.setBorder(new LineBorder(Color.LIGHT_GRAY));
mySortingLabel.setOpaque(true);
mySortingLabel.addMouseListener(new MouseAdapter() {
@Override
@@ -531,7 +531,7 @@ public class LookupImpl extends LightweightHint implements Lookup, Disposable {
}
private LookupArranger getActualArranger() {
- if (UISettings.getInstance().SORT_LOOKUP_ELEMENTS_LEXICOGRAPHICALLY) {
+ if (isCompletion() && UISettings.getInstance().SORT_LOOKUP_ELEMENTS_LEXICOGRAPHICALLY) {
return LookupArranger.LEXICOGRAPHIC;
}
return myCustomArranger;
@@ -1112,19 +1112,20 @@ public class LookupImpl extends LightweightHint implements Lookup, Disposable {
private void layoutStatusIcons() {
final JLayeredPane layeredPane = getComponent().getRootPane().getLayeredPane();
- final int width = layeredPane.getWidth();
- final int height = layeredPane.getHeight();
final Dimension iconSize = myProcessIcon.getPreferredSize();
- myIconPanel.setBounds(width - iconSize.width, 0, iconSize.width, iconSize.height);
+ myIconPanel.setBounds(layeredPane.getWidth() - iconSize.width, 0, iconSize.width, iconSize.height);
final Dimension sortSize = mySortingLabel.getPreferredSize();
- mySortingLabel.setBounds(width - sortSize.width, height - sortSize.height, sortSize.width, sortSize.height);
+ final Point sbLocation = SwingUtilities.convertPoint(myScrollPane.getVerticalScrollBar(), 0, 0, layeredPane);
+
+ final int sortHeight = (StringUtil.isNotEmpty(myAdText) ? myAdComponent : mySortingLabel).getPreferredSize().height;
+ mySortingLabel.setBounds(sbLocation.x, layeredPane.getHeight() - sortHeight, sortSize.width, sortHeight);
}
private void updateScrollbarVisibility() {
- boolean showSorting = getList().getModel().getSize() >= 3;
+ boolean showSorting = isCompletion() && getList().getModel().getSize() >= 3;
mySortingLabel.setVisible(showSorting);
myScrollPane.setVerticalScrollBarPolicy(showSorting ? ScrollPaneConstants.VERTICAL_SCROLLBAR_ALWAYS : ScrollPaneConstants.VERTICAL_SCROLLBAR_AS_NEEDED);
}
diff --git a/platform/lang-impl/src/com/intellij/codeInspection/ex/InspectionProfileWrapper.java b/platform/lang-impl/src/com/intellij/codeInspection/ex/InspectionProfileWrapper.java
index 81d41211d4b7..729f62de1aa1 100644
--- a/platform/lang-impl/src/com/intellij/codeInspection/ex/InspectionProfileWrapper.java
+++ b/platform/lang-impl/src/com/intellij/codeInspection/ex/InspectionProfileWrapper.java
@@ -23,6 +23,7 @@ import com.intellij.openapi.diagnostic.Logger;
import com.intellij.openapi.project.Project;
import com.intellij.openapi.util.Key;
import com.intellij.psi.PsiElement;
+import com.intellij.util.Function;
import gnu.trove.THashSet;
import java.util.ArrayList;
@@ -37,10 +38,13 @@ public class InspectionProfileWrapper {
private static final Logger LOG = Logger.getInstance("#com.intellij.codeInspection.ex.InspectionProfileWrapper");
/**
- * Generic-purpose key object that is intended to be used for customizing inspection profile wrapper retrieval
- * via {@link com.intellij.openapi.util.UserDataHolder} API.
+ * Key that is assumed to hold strategy that customizes {@link InspectionProfileWrapper} object to use.
+ *
+ * I.e. given strategy (if any) receives {@link InspectionProfileWrapper} object that is going to be used so far and returns
+ * {@link InspectionProfileWrapper} object that should be used later.
*/
- public static final Key KEY = Key.create("Inspection Profile Wrapper");
+ public static final Key> CUSTOMIZATION_KEY
+ = Key.create("Inspection Profile Wrapper Customization");
private final InspectionProfileImpl myProfile;
public InspectionProfileWrapper(final InspectionProfile profile) {
diff --git a/platform/lang-impl/src/com/intellij/execution/impl/ConsoleViewImpl.java b/platform/lang-impl/src/com/intellij/execution/impl/ConsoleViewImpl.java
index a8ea47a85711..b2df5569aaf8 100644
--- a/platform/lang-impl/src/com/intellij/execution/impl/ConsoleViewImpl.java
+++ b/platform/lang-impl/src/com/intellij/execution/impl/ConsoleViewImpl.java
@@ -570,7 +570,7 @@ public class ConsoleViewImpl extends JPanel implements ConsoleView, ObservableCo
flushDeferredUserInput();
}
}
- if (myFlushAlarm.getActiveRequestCount() == 0 && myEditor != null) {
+ if (myFlushAlarm.getActiveRequestCount() == 0 && myEditor != null && !myFlushAlarm.isDisposed()) {
final boolean shouldFlushNow = USE_CYCLIC_BUFFER && myDeferredOutputLength > CYCLIC_BUFFER_SIZE;
myFlushAlarm.addRequest(myFlushDeferredRunnable, shouldFlushNow ? 0 : FLUSH_DELAY, getStateForUpdate());
}
diff --git a/platform/lang-impl/src/com/intellij/extapi/psi/StubBasedPsiElementBase.java b/platform/lang-impl/src/com/intellij/extapi/psi/StubBasedPsiElementBase.java
index 6fe0c326741a..383a1204608c 100644
--- a/platform/lang-impl/src/com/intellij/extapi/psi/StubBasedPsiElementBase.java
+++ b/platform/lang-impl/src/com/intellij/extapi/psi/StubBasedPsiElementBase.java
@@ -184,6 +184,9 @@ public class StubBasedPsiElementBase extends ASTDelegateP
@NotNull
public IStubElementType getElementType() {
+ if (!(myElementType instanceof IStubElementType)) {
+ throw new AssertionError("Not a stub type: " + myElementType + " in " + getClass());
+ }
return (IStubElementType)myElementType;
}
diff --git a/platform/lang-impl/src/com/intellij/find/FindUtil.java b/platform/lang-impl/src/com/intellij/find/FindUtil.java
index 9cb56e56b840..2a3108a8ace5 100644
--- a/platform/lang-impl/src/com/intellij/find/FindUtil.java
+++ b/platform/lang-impl/src/com/intellij/find/FindUtil.java
@@ -46,6 +46,7 @@ import com.intellij.openapi.fileEditor.TextEditor;
import com.intellij.openapi.fileEditor.ex.IdeDocumentHistory;
import com.intellij.openapi.keymap.KeymapUtil;
import com.intellij.openapi.project.Project;
+import com.intellij.openapi.ui.Messages;
import com.intellij.openapi.util.Key;
import com.intellij.openapi.util.Pair;
import com.intellij.openapi.util.TextRange;
@@ -440,6 +441,21 @@ public class FindUtil {
}
int startResultOffset = result.getStartOffset();
model.setFromCursor(true);
+
+ int startOffset = result.getStartOffset();
+ int endOffset = result.getEndOffset();
+ String foundString = document.getCharsSequence().subSequence(startOffset, endOffset).toString();
+ String toReplace;
+ try {
+ toReplace = findManager.getStringToReplace(foundString, model, startOffset, document.getText());
+ }
+ catch (FindManager.MalformedReplacementStringException e) {
+ if (!ApplicationManager.getApplication().isUnitTestMode()) {
+ Messages.showErrorDialog(project, e.getMessage(), FindBundle.message("find.replace.invalid.replacement.string.title"));
+ }
+ break;
+ }
+
if (toPrompt) {
int promptResult = findManager.showPromptDialog(model, FindBundle.message("find.replace.dialog.title"));
if (promptResult == FindManager.PromptResult.SKIP) {
@@ -455,12 +471,6 @@ public class FindUtil {
}
}
- int startOffset = result.getStartOffset();
- int endOffset = result.getEndOffset();
- String foundString = document.getCharsSequence().subSequence(startOffset, endOffset).toString();
- String toReplace = findManager.getStringToReplace(foundString, model, startOffset, document.getText());
- if (toReplace == null) break;
-
boolean reallyReplace = toPrompt;
TextRange textRange = doReplace(project, document, model, result, toReplace, reallyReplace, rangesToChange);
diff --git a/platform/lang-impl/src/com/intellij/find/findUsages/FindUsagesManager.java b/platform/lang-impl/src/com/intellij/find/findUsages/FindUsagesManager.java
index a5b608a04925..914bc3ee467d 100644
--- a/platform/lang-impl/src/com/intellij/find/findUsages/FindUsagesManager.java
+++ b/platform/lang-impl/src/com/intellij/find/findUsages/FindUsagesManager.java
@@ -118,6 +118,10 @@ public class FindUsagesManager implements JDOMExternalizable {
myAnotherManager = anotherManager;
}
+ /**
+ * @deprecated
+ * @see FindUsagesHandlerFactory#EP_NAME
+ */
public void registerFindUsagesHandler(FindUsagesHandlerFactory handler) {
myHandlers.add(0, handler);
}
diff --git a/platform/lang-impl/src/com/intellij/find/impl/FindDialog.java b/platform/lang-impl/src/com/intellij/find/impl/FindDialog.java
index 9c5b0286cfed..2bcee259eec9 100644
--- a/platform/lang-impl/src/com/intellij/find/impl/FindDialog.java
+++ b/platform/lang-impl/src/com/intellij/find/impl/FindDialog.java
@@ -19,6 +19,7 @@ package com.intellij.find.impl;
import com.intellij.CommonBundle;
import com.intellij.find.FindBundle;
+import com.intellij.find.FindManager;
import com.intellij.find.FindModel;
import com.intellij.find.FindSettings;
import com.intellij.ide.util.scopeChooser.ScopeChooserCombo;
diff --git a/platform/lang-impl/src/com/intellij/find/impl/FindManagerImpl.java b/platform/lang-impl/src/com/intellij/find/impl/FindManagerImpl.java
index e264af03df3c..e2234b3194c0 100644
--- a/platform/lang-impl/src/com/intellij/find/impl/FindManagerImpl.java
+++ b/platform/lang-impl/src/com/intellij/find/impl/FindManagerImpl.java
@@ -50,7 +50,6 @@ import com.intellij.openapi.fileTypes.SyntaxHighlighterFactory;
import com.intellij.openapi.keymap.KeymapUtil;
import com.intellij.openapi.project.Project;
import com.intellij.openapi.project.ProjectManager;
-import com.intellij.openapi.ui.Messages;
import com.intellij.openapi.util.*;
import com.intellij.openapi.util.text.StringUtil;
import com.intellij.openapi.vfs.VirtualFile;
@@ -512,7 +511,7 @@ public class FindManagerImpl extends FindManager implements PersistentStateCompo
return pattern == null ? null : pattern.matcher(text);
}
- public String getStringToReplace(@NotNull String foundString, @NotNull FindModel model) {
+ public String getStringToReplace(@NotNull String foundString, @NotNull FindModel model) throws MalformedReplacementStringException {
String toReplace = model.getStringToReplace();
if (model.isRegularExpressions()) {
return getStringToReplaceByRegexp0(foundString, model);
@@ -524,7 +523,8 @@ public class FindManagerImpl extends FindManager implements PersistentStateCompo
}
@Override
- public String getStringToReplace(@NotNull String foundString, @NotNull FindModel model, int startOffset, @NotNull String documentText) {
+ public String getStringToReplace(@NotNull String foundString, @NotNull FindModel model,
+ int startOffset, @NotNull String documentText) throws MalformedReplacementStringException{
String toReplace = model.getStringToReplace();
if (model.isRegularExpressions()) {
return getStringToReplaceByRegexp(model, documentText, startOffset);
@@ -535,7 +535,7 @@ public class FindManagerImpl extends FindManager implements PersistentStateCompo
return toReplace;
}
- private String getStringToReplaceByRegexp(@NotNull final FindModel model, @NotNull String text, int startOffset) {
+ private String getStringToReplaceByRegexp(@NotNull final FindModel model, @NotNull String text, int startOffset) throws MalformedReplacementStringException{
Matcher matcher = compileRegExp(model, text);
if (model.isForward()){
@@ -563,17 +563,11 @@ public class FindManagerImpl extends FindManager implements PersistentStateCompo
return replaced.substring(matcher.start());
}
catch (Exception e) {
- ApplicationManager.getApplication().invokeLater(new Runnable() {
- public void run() {
- Messages.showErrorDialog(myProject, FindBundle.message("find.replace.invalid.replacement.string", model.getStringToReplace()),
- FindBundle.message("find.replace.invalid.replacement.string.title"));
- }
- });
- return null;
+ throw new MalformedReplacementStringException(FindBundle.message("find.replace.invalid.replacement.string", model.getStringToReplace()), e);
}
}
- private String getStringToReplaceByRegexp0(String foundString, final FindModel model) {
+ private String getStringToReplaceByRegexp0(String foundString, final FindModel model) throws MalformedReplacementStringException{
String toFind = model.getStringToFind();
String toReplace = model.getStringToReplace();
Pattern pattern;
@@ -594,13 +588,7 @@ public class FindManagerImpl extends FindManager implements PersistentStateCompo
return matcher.replaceAll(StringUtil.unescapeStringCharacters(toReplace));
}
catch (Exception e) {
- ApplicationManager.getApplication().invokeLater(new Runnable() {
- public void run() {
- Messages.showErrorDialog(myProject, FindBundle.message("find.replace.invalid.replacement.string", model.getStringToReplace()),
- FindBundle.message("find.replace.invalid.replacement.string.title"));
- }
- });
- return null;
+ throw new MalformedReplacementStringException(FindBundle.message("find.replace.invalid.replacement.string", model.getStringToReplace()), e);
}
}
else {
diff --git a/platform/lang-impl/src/com/intellij/find/impl/LivePreviewController.java b/platform/lang-impl/src/com/intellij/find/impl/LivePreviewController.java
index b8d787f19919..755d6424f69c 100644
--- a/platform/lang-impl/src/com/intellij/find/impl/LivePreviewController.java
+++ b/platform/lang-impl/src/com/intellij/find/impl/LivePreviewController.java
@@ -113,8 +113,13 @@ public class LivePreviewController implements LivePreview.Delegate, UserActivity
if (currentModel != null) {
if (currentModel.isReplaceState()) {
FindManager findManager = FindManager.getInstance(editor.getProject());
- stringToReplace = findManager.getStringToReplace(foundString, currentModel,
- liveOccurrence.getPrimaryRange().getStartOffset(), documentText);
+ try {
+ stringToReplace = findManager.getStringToReplace(foundString, currentModel,
+ liveOccurrence.getPrimaryRange().getStartOffset(), documentText);
+ }
+ catch (FindManager.MalformedReplacementStringException e) {
+ return null;
+ }
if (stringToReplace != null && stringToReplace.isEmpty()) {
stringToReplace = EMPTY_STRING_DISPLAY_TEXT;
}
diff --git a/platform/lang-impl/src/com/intellij/find/replaceInProject/ReplaceInProjectManager.java b/platform/lang-impl/src/com/intellij/find/replaceInProject/ReplaceInProjectManager.java
index d031a7dc5964..08fe256dfad2 100644
--- a/platform/lang-impl/src/com/intellij/find/replaceInProject/ReplaceInProjectManager.java
+++ b/platform/lang-impl/src/com/intellij/find/replaceInProject/ReplaceInProjectManager.java
@@ -341,8 +341,14 @@ public class ReplaceInProjectManager {
if (!findResult.isStringFound()) {
return;
}
- String stringToReplace =
- findManager.getStringToReplace(foundString.toString(), replaceContext.getFindModel(), textOffset, document.getText());
+ String stringToReplace = null;
+ try {
+ stringToReplace =
+ findManager.getStringToReplace(foundString.toString(), replaceContext.getFindModel(), textOffset, document.getText());
+ }
+ catch (FindManager.MalformedReplacementStringException e) {
+ Messages.showErrorDialog(myProject, e.getMessage(), FindBundle.message("find.replace.invalid.replacement.string.title"));
+ }
if (stringToReplace != null) {
document.replaceString(textOffset, textEndOffset, stringToReplace);
}
diff --git a/platform/lang-impl/src/com/intellij/formatting/FormatProcessor.java b/platform/lang-impl/src/com/intellij/formatting/FormatProcessor.java
index 452adacfeabf..72421e87eefb 100644
--- a/platform/lang-impl/src/com/intellij/formatting/FormatProcessor.java
+++ b/platform/lang-impl/src/com/intellij/formatting/FormatProcessor.java
@@ -1128,8 +1128,9 @@ class FormatProcessor {
}
private static int getNewChildPosition(final AbstractBlockWrapper parent, final int offset) {
- if (!(parent instanceof CompositeBlockWrapper)) return 0;
- final List subBlocks = ((CompositeBlockWrapper)parent).getChildren();
+ AbstractBlockWrapper parentBlockToUse = getLastNestedCompositeBlockForSameRange(parent);
+ if (!(parentBlockToUse instanceof CompositeBlockWrapper)) return 0;
+ final List subBlocks = ((CompositeBlockWrapper)parentBlockToUse).getChildren();
//noinspection ConstantConditions
if (subBlocks != null) {
for (int i = 0; i < subBlocks.size(); i++) {
@@ -1159,7 +1160,7 @@ class FormatProcessor {
private AbstractBlockWrapper getParentFor(final int offset, LeafBlockWrapper block) {
AbstractBlockWrapper previous = getPreviousIncompleteBlock(block, offset);
if (previous != null) {
- return previous;
+ return getLastNestedCompositeBlockForSameRange(previous);
}
else {
return getParentFor(offset, (AbstractBlockWrapper)block);
@@ -1215,12 +1216,47 @@ class FormatProcessor {
@Nullable
private static AbstractBlockWrapper getLastChildOf(final AbstractBlockWrapper currentResult) {
- if (!(currentResult instanceof CompositeBlockWrapper)) return null;
- final List subBlocks = ((CompositeBlockWrapper)currentResult).getChildren();
+ AbstractBlockWrapper parentBlockToUse = getLastNestedCompositeBlockForSameRange(currentResult);
+ if (!(parentBlockToUse instanceof CompositeBlockWrapper)) return null;
+ final List subBlocks = ((CompositeBlockWrapper)parentBlockToUse).getChildren();
if (subBlocks.isEmpty()) return null;
return subBlocks.get(subBlocks.size() - 1);
}
+ /**
+ * There is a possible case that particular block is a composite block that contains number of nested composite blocks
+ * that all target the same text range. This method allows to derive the most nested block that shares the same range (if any).
+ *
+ * @param block block to check
+ * @return the most nested block of the given one that shares the same text range if any; given block otherwise
+ */
+ @NotNull
+ private static AbstractBlockWrapper getLastNestedCompositeBlockForSameRange(@NotNull final AbstractBlockWrapper block) {
+ if (!(block instanceof CompositeBlockWrapper)) {
+ return block;
+ }
+
+ AbstractBlockWrapper result = block;
+ AbstractBlockWrapper candidate = block;
+ while (true) {
+ List subBlocks = ((CompositeBlockWrapper)candidate).getChildren();
+ if (subBlocks == null || subBlocks.size() != 1) {
+ break;
+ }
+
+ candidate = subBlocks.get(0);
+ if (candidate.getStartOffset() == block.getStartOffset() && candidate.getEndOffset() == block.getEndOffset()
+ && candidate instanceof CompositeBlockWrapper)
+ {
+ result = candidate;
+ }
+ else {
+ break;
+ }
+ }
+ return result;
+ }
+
private void processBlocksBefore(final int offset) {
while (true) {
myAlignAgain.clear();
diff --git a/platform/lang-impl/src/com/intellij/formatting/FormatTextRanges.java b/platform/lang-impl/src/com/intellij/formatting/FormatTextRanges.java
index e0f17cc45708..bbf35dcd2a2b 100644
--- a/platform/lang-impl/src/com/intellij/formatting/FormatTextRanges.java
+++ b/platform/lang-impl/src/com/intellij/formatting/FormatTextRanges.java
@@ -20,7 +20,6 @@ import com.intellij.openapi.extensions.Extensions;
import com.intellij.openapi.util.TextRange;
import com.intellij.openapi.util.text.StringUtil;
import com.intellij.psi.impl.source.codeStyle.PreFormatProcessor;
-import com.intellij.util.Function;
import java.util.ArrayList;
import java.util.List;
@@ -93,7 +92,7 @@ public class FormatTextRanges {
* false otherwise
*/
public boolean isReadOnly(TextRange range, boolean rootIsRightBlock) {
- if (myRange.getStartOffset() >= range.getEndOffset() && rootIsRightBlock) {
+ if (myRange == null || myRange.getStartOffset() >= range.getEndOffset() && rootIsRightBlock) {
return false;
}
diff --git a/platform/lang-impl/src/com/intellij/ide/actions/WeighingNewActionGroup.java b/platform/lang-impl/src/com/intellij/ide/actions/WeighingNewActionGroup.java
index b07cf016cb66..37822668bee0 100644
--- a/platform/lang-impl/src/com/intellij/ide/actions/WeighingNewActionGroup.java
+++ b/platform/lang-impl/src/com/intellij/ide/actions/WeighingNewActionGroup.java
@@ -32,6 +32,11 @@ public class WeighingNewActionGroup extends WeighingActionGroup {
return myDelegate;
}
+ @Override
+ public boolean isDumbAware() {
+ return true;
+ }
+
@Override
public void update(AnActionEvent e) {
super.update(e);
diff --git a/platform/lang-impl/src/com/intellij/ide/projectView/impl/DirectoryUrl.java b/platform/lang-impl/src/com/intellij/ide/projectView/impl/DirectoryUrl.java
index dcb4703e03f3..27c6f18f0a1d 100644
--- a/platform/lang-impl/src/com/intellij/ide/projectView/impl/DirectoryUrl.java
+++ b/platform/lang-impl/src/com/intellij/ide/projectView/impl/DirectoryUrl.java
@@ -16,15 +16,18 @@
package com.intellij.ide.projectView.impl;
+import com.intellij.openapi.application.ApplicationManager;
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.Computable;
import com.intellij.openapi.vfs.VirtualFile;
import com.intellij.openapi.vfs.VirtualFileManager;
import com.intellij.psi.PsiDirectory;
import com.intellij.psi.PsiManager;
import org.jetbrains.annotations.NonNls;
+import org.jetbrains.annotations.Nullable;
/**
* @author cdr
@@ -42,16 +45,27 @@ public class DirectoryUrl extends AbstractUrl {
return new DirectoryUrl(virtualFile.getUrl(), module != null ? module.getName() : null);
}
- public Object[] createPath(Project project) {
+ public Object[] createPath(final Project project) {
if (moduleName != null) {
-
- final Module module = ModuleManager.getInstance(project).findModuleByName(moduleName);
+ final Module module = ApplicationManager.getApplication().runReadAction(new Computable() {
+ @Nullable
+ @Override
+ public Module compute() {
+ return ModuleManager.getInstance(project).findModuleByName(moduleName);
+ }
+ });
if (module == null) return null;
}
final VirtualFileManager virtualFileManager = VirtualFileManager.getInstance();
- VirtualFile file = virtualFileManager.findFileByUrl(url);
+ final VirtualFile file = virtualFileManager.findFileByUrl(url);
if (file == null) return null;
- final PsiDirectory directory = PsiManager.getInstance(project).findDirectory(file);
+ final PsiDirectory directory = ApplicationManager.getApplication().runReadAction(new Computable() {
+ @Nullable
+ @Override
+ public PsiDirectory compute() {
+ return PsiManager.getInstance(project).findDirectory(file);
+ }
+ });
if (directory == null) return null;
return new Object[]{directory};
}
diff --git a/platform/lang-impl/src/com/intellij/ide/scopeView/ScopeTreeViewPanel.java b/platform/lang-impl/src/com/intellij/ide/scopeView/ScopeTreeViewPanel.java
index fa901642487f..00ec308ae838 100644
--- a/platform/lang-impl/src/com/intellij/ide/scopeView/ScopeTreeViewPanel.java
+++ b/platform/lang-impl/src/com/intellij/ide/scopeView/ScopeTreeViewPanel.java
@@ -314,6 +314,15 @@ public class ScopeTreeViewPanel extends JPanel implements JDOMExternalizable, Di
}
return myDeletePSIElementProvider;
}
+ if (LangDataKeys.PASTE_TARGET_PSI_ELEMENT.is(dataId)) {
+ final TreePath selectionPath = myTree.getSelectionPath();
+ if (selectionPath != null) {
+ final Object pathComponent = selectionPath.getLastPathComponent();
+ if (pathComponent instanceof DirectoryNode) {
+ return ((DirectoryNode)pathComponent).getTargetDirectory();
+ }
+ }
+ }
return null;
}
diff --git a/platform/lang-impl/src/com/intellij/ide/scriptingContext/ScriptingLibraryMappings.java b/platform/lang-impl/src/com/intellij/ide/scriptingContext/ScriptingLibraryMappings.java
index 9706e690f911..6b243e37e894 100644
--- a/platform/lang-impl/src/com/intellij/ide/scriptingContext/ScriptingLibraryMappings.java
+++ b/platform/lang-impl/src/com/intellij/ide/scriptingContext/ScriptingLibraryMappings.java
@@ -76,7 +76,9 @@ public class ScriptingLibraryMappings extends LanguagePerFileMappings map = getMappings();
- for (VirtualFile file : map.keySet()) {
+ myCompoundLibMap.clear();
+ myProjectLibs = new CompoundLibrary();
+ for (VirtualFile file : map.keySet().toArray(new VirtualFile[map.size()])) {
ScriptingLibraryTable.LibraryModel value = getImmediateMapping(file);
if (value instanceof CompoundLibrary) {
CompoundLibrary container = (CompoundLibrary) value;
@@ -91,6 +93,14 @@ public class ScriptingLibraryMappings extends LanguagePerFileMappings myFiles = new ArrayList();
+ private SortedList myFiles = new SortedList(new Comparator() {
+ @Override
+ public int compare(VirtualFile file1, VirtualFile file2) {
+ return file1.getName().compareTo(file2.getName());
+ }
+ });
private HashSet myCompactFiles = new HashSet();
- public void addFile(VirtualFile file) {
+ public int addFile(VirtualFile file) {
myFiles.add(file);
if (myProvider.isCompact(file)) {
myCompactFiles.add(file);
}
fireTableDataChanged();
+ return myFiles.indexOf(file);
}
public void setFiles(Set sourceFiles, Set compactFiles) {
diff --git a/platform/lang-impl/src/com/intellij/moduleDependencies/ModulesDependenciesPanel.java b/platform/lang-impl/src/com/intellij/moduleDependencies/ModulesDependenciesPanel.java
index 0458d111d1e1..6ff8ca6679b6 100644
--- a/platform/lang-impl/src/com/intellij/moduleDependencies/ModulesDependenciesPanel.java
+++ b/platform/lang-impl/src/com/intellij/moduleDependencies/ModulesDependenciesPanel.java
@@ -38,6 +38,7 @@ import com.intellij.openapi.ui.Splitter;
import com.intellij.openapi.util.IconLoader;
import com.intellij.openapi.util.text.StringUtil;
import com.intellij.pom.Navigatable;
+import com.intellij.pom.NavigatableWithText;
import com.intellij.ui.*;
import com.intellij.ui.content.Content;
import com.intellij.ui.treeStructure.Tree;
@@ -374,9 +375,12 @@ public class ModulesDependenciesPanel extends JPanel implements ModuleRootListen
group.add(actionManager.createExpandAllAction(treeExpander, tree));
}
group.add(actionManager.createCollapseAllAction(treeExpander, tree));
- group.add(ActionManager.getInstance().getAction(IdeActions.ACTION_EDIT_SOURCE));
- group.add(ActionManager.getInstance().getAction(IdeActions.MODULE_SETTINGS));
- appendDependenciesAction(group);
+ final ActionManager globalActionManager = ActionManager.getInstance();
+ group.add(globalActionManager.getAction(IdeActions.ACTION_EDIT_SOURCE));
+ group.add(Separator.getInstance());
+ group.add(globalActionManager.getAction(IdeActions.ACTION_ANALYZE_DEPENDENCIES));
+ group.add(globalActionManager.getAction(IdeActions.ACTION_ANALYZE_BACK_DEPENDENCIES));
+ group.add(globalActionManager.getAction(IdeActions.ACTION_ANALYZE_CYCLIC_DEPENDENCIES));
return group;
}
@@ -432,7 +436,7 @@ public class ModulesDependenciesPanel extends JPanel implements ModuleRootListen
TreeUtil.selectFirstNode(myLeftTree);
}
- private static class MyUserObject implements Navigatable{
+ private static class MyUserObject implements NavigatableWithText{
private boolean myInCycle;
private final Module myModule;
@@ -476,6 +480,11 @@ public class ModulesDependenciesPanel extends JPanel implements ModuleRootListen
public boolean canNavigateToSource() {
return false;
}
+
+ @Override
+ public String getNavigateActionText(boolean focusEditor) {
+ return "Open Module Settings";
+ }
}
private static class MyTreePanel extends JPanel implements DataProvider{
diff --git a/platform/lang-impl/src/com/intellij/openapi/roots/impl/libraries/JarDirectories.java b/platform/lang-impl/src/com/intellij/openapi/roots/impl/libraries/JarDirectories.java
new file mode 100644
index 000000000000..982136447b05
--- /dev/null
+++ b/platform/lang-impl/src/com/intellij/openapi/roots/impl/libraries/JarDirectories.java
@@ -0,0 +1,96 @@
+/*
+ * Copyright 2000-2011 JetBrains s.r.o.
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+package com.intellij.openapi.roots.impl.libraries;
+
+import com.intellij.openapi.roots.OrderRootType;
+import com.intellij.util.containers.MultiMap;
+
+import java.util.Collection;
+
+/**
+ * @author nik
+ */
+public class JarDirectories {
+ private MultiMap myDirectories = new MultiMap();
+ private MultiMap myRecursivelyIncluded = new MultiMap();
+
+ public void copyFrom(JarDirectories other) {
+ myDirectories.clear();
+ myDirectories.putAllValues(other.myDirectories);
+ myRecursivelyIncluded.clear();
+ myRecursivelyIncluded.putAllValues(other.myRecursivelyIncluded);
+ }
+
+ public boolean contains(OrderRootType rootType, String url) {
+ return myDirectories.get(rootType).contains(url);
+ }
+
+ public boolean isRecursive(OrderRootType rootType, String url) {
+ return myRecursivelyIncluded.get(rootType).contains(url);
+ }
+
+ public void add(OrderRootType rootType, String url, boolean recursively) {
+ myDirectories.putValue(rootType, url);
+ if (recursively) {
+ myRecursivelyIncluded.putValue(rootType, url);
+ }
+ }
+
+ public void remove(OrderRootType rootType, String url) {
+ myDirectories.removeValue(rootType, url);
+ myRecursivelyIncluded.removeValue(rootType, url);
+ }
+
+ public void clear() {
+ myDirectories.clear();
+ myRecursivelyIncluded.clear();
+ }
+
+ public Collection getRootTypes() {
+ return myDirectories.keySet();
+ }
+
+ public Collection getDirectories(OrderRootType rootType) {
+ return myDirectories.get(rootType);
+ }
+
+ public Collection extends String> getAllDirectories() {
+ return myDirectories.values();
+ }
+
+ public boolean isEmpty() {
+ return myDirectories.isEmpty();
+ }
+
+ @Override
+ public boolean equals(Object o) {
+ if (this == o) return true;
+ if (!(o instanceof JarDirectories)) return false;
+
+ JarDirectories that = (JarDirectories)o;
+ return myDirectories.equals(that.myDirectories) && myRecursivelyIncluded.equals(that.myRecursivelyIncluded);
+ }
+
+ @Override
+ public int hashCode() {
+ return 31 * myDirectories.hashCode() + myRecursivelyIncluded.hashCode();
+ }
+
+ @Override
+ public String toString() {
+ return "Jar dirs: " + myDirectories.values();
+ }
+}
diff --git a/platform/lang-impl/src/com/intellij/openapi/roots/impl/libraries/LibraryImpl.java b/platform/lang-impl/src/com/intellij/openapi/roots/impl/libraries/LibraryImpl.java
index cbabc68259f1..649f05317175 100644
--- a/platform/lang-impl/src/com/intellij/openapi/roots/impl/libraries/LibraryImpl.java
+++ b/platform/lang-impl/src/com/intellij/openapi/roots/impl/libraries/LibraryImpl.java
@@ -65,12 +65,14 @@ public class LibraryImpl implements LibraryEx.ModifiableModelEx, LibraryEx {
@NonNls private static final String JAR_DIRECTORY_ELEMENT = "jarDirectory";
@NonNls private static final String URL_ATTR = "url";
@NonNls private static final String RECURSIVE_ATTR = "recursive";
+ @NonNls private static final String ROOT_TYPE_ATTR = "type";
@NonNls private static final String PROPERTIES_ELEMENT = "properties";
+ private static final OrderRootType DEFAULT_JAR_DIRECTORY_TYPE = OrderRootType.CLASSES;
private static final SkipDefaultValuesSerializationFilters SERIALIZATION_FILTERS = new SkipDefaultValuesSerializationFilters();
private String myName;
private final LibraryTable myLibraryTable;
private final Map myRoots;
- private final Map myJarDirectories = new HashMap();
+ private final JarDirectories myJarDirectories = new JarDirectories();
private final List myWatchRequests = new ArrayList();
private final LibraryImpl mySource;
private LibraryType> myType;
@@ -106,7 +108,7 @@ public class LibraryImpl implements LibraryEx.ModifiableModelEx, LibraryEx {
myRoots = initRoots();
mySource = null;
}
-
+
private Set getAllRootTypes() {
Set rootTypes = new HashSet();
rootTypes.addAll(Arrays.asList(OrderRootType.getAllTypes()));
@@ -114,7 +116,7 @@ public class LibraryImpl implements LibraryEx.ModifiableModelEx, LibraryEx {
rootTypes.addAll(Arrays.asList(myType.getAdditionalRootTypes()));
}
return rootTypes;
- }
+ }
private LibraryImpl(LibraryImpl from, LibraryImpl newSource, ModifiableRootModel rootModel) {
assert !from.isDisposed();
@@ -134,7 +136,7 @@ public class LibraryImpl implements LibraryEx.ModifiableModelEx, LibraryEx {
final VirtualFilePointerContainer thatContainer = from.myRoots.get(rootType);
thisContainer.addAll(thatContainer);
}
- myJarDirectories.putAll(from.myJarDirectories);
+ myJarDirectories.copyFrom(from.myJarDirectories);
}
public void dispose() {
@@ -171,9 +173,8 @@ public class LibraryImpl implements LibraryEx.ModifiableModelEx, LibraryEx {
final List expanded = new ArrayList();
for (VirtualFile file : myRoots.get(rootType).getFiles()) {
if (file.isDirectory()) {
- final Boolean expandRecursively = myJarDirectories.get(file.getUrl());
- if (expandRecursively != null) {
- collectJarFiles(file, expanded, expandRecursively.booleanValue());
+ if (myJarDirectories.contains(rootType, file.getUrl())) {
+ collectJarFiles(file, expanded, myJarDirectories.isRecursive(rootType, file.getUrl()));
continue;
}
}
@@ -242,7 +243,7 @@ public class LibraryImpl implements LibraryEx.ModifiableModelEx, LibraryEx {
private Map initRoots() {
Disposer.register(this, myPointersDisposable);
-
+
Map result = new HashMap(5);
for (OrderRootType rootType : getAllRootTypes()) {
@@ -301,16 +302,25 @@ public class LibraryImpl implements LibraryEx.ModifiableModelEx, LibraryEx {
final Element jarDir = (Element)item;
final String url = jarDir.getAttributeValue(URL_ATTR);
final String recursive = jarDir.getAttributeValue(RECURSIVE_ATTR);
+ final OrderRootType rootType = getJarDirectoryRootType(jarDir.getAttributeValue(ROOT_TYPE_ATTR));
if (url != null) {
- myJarDirectories.put(url, Boolean.valueOf(Boolean.parseBoolean(recursive)));
+ myJarDirectories.add(rootType, url, Boolean.valueOf(Boolean.parseBoolean(recursive)));
}
}
}
-
- //TODO Remove the next two methods as a temporary solution. Sort in OrderRootType.
+ private static OrderRootType getJarDirectoryRootType(@Nullable String type) {
+ for (PersistentOrderRootType rootType : OrderRootType.getAllPersistentTypes()) {
+ if (rootType.name().equals(type)) {
+ return rootType;
+ }
+ }
+ return DEFAULT_JAR_DIRECTORY_TYPE;
+ }
+
+ //TODO Remove the next two methods as a temporary solution. Sort in OrderRootType.
//
- private static List sortRootTypes(List rootTypes) {
+ private static List sortRootTypes(Collection rootTypes) {
List allTypes = new ArrayList(rootTypes);
Collections.sort(allTypes, new Comparator() {
public int compare(final OrderRootType o1, final OrderRootType o2) {
@@ -319,7 +329,7 @@ public class LibraryImpl implements LibraryEx.ModifiableModelEx, LibraryEx {
});
return allTypes;
}
-
+
private static String getSortKey(OrderRootType orderRootType) {
if (orderRootType instanceof PersistentOrderRootType) {
return ((PersistentOrderRootType)orderRootType).getSdkRootName();
@@ -359,17 +369,19 @@ public class LibraryImpl implements LibraryEx.ModifiableModelEx, LibraryEx {
roots.writeExternal(rootTypeElement, ROOT_PATH_ELEMENT);
element.addContent(rootTypeElement);
}
- List urls = new ArrayList(myJarDirectories.keySet());
- Collections.sort(urls, new Comparator() {
- public int compare(final String url1, final String url2) {
- return url1.compareToIgnoreCase(url2);
+ final List rootTypes = sortRootTypes(myJarDirectories.getRootTypes());
+ for (OrderRootType rootType : rootTypes) {
+ final List urls = new ArrayList(myJarDirectories.getDirectories(rootType));
+ Collections.sort(urls, String.CASE_INSENSITIVE_ORDER);
+ for (String url : urls) {
+ final Element jarDirElement = new Element(JAR_DIRECTORY_ELEMENT);
+ jarDirElement.setAttribute(URL_ATTR, url);
+ jarDirElement.setAttribute(RECURSIVE_ATTR, Boolean.toString(myJarDirectories.isRecursive(rootType, url)));
+ if (!rootType.equals(DEFAULT_JAR_DIRECTORY_TYPE)) {
+ jarDirElement.setAttribute(ROOT_TYPE_ATTR, rootType.name());
+ }
+ element.addContent(jarDirElement);
}
- });
- for (String url : urls) {
- final Element jarDirElement = new Element(JAR_DIRECTORY_ELEMENT);
- jarDirElement.setAttribute(URL_ATTR, url);
- jarDirElement.setAttribute(RECURSIVE_ATTR, myJarDirectories.get(url).toString());
- element.addContent(jarDirElement);
}
rootElement.addContent(element);
}
@@ -405,23 +417,35 @@ public class LibraryImpl implements LibraryEx.ModifiableModelEx, LibraryEx {
}
public void addJarDirectory(@NotNull final String url, final boolean recursive) {
- assert !isDisposed();
- LOG.assertTrue(isWritable());
- final VirtualFilePointerContainer container = myRoots.get(OrderRootType.CLASSES);
- container.add(url);
- myJarDirectories.put(url, Boolean.valueOf(recursive));
+ addJarDirectory(url, recursive, DEFAULT_JAR_DIRECTORY_TYPE);
}
public void addJarDirectory(@NotNull final VirtualFile file, final boolean recursive) {
+ addJarDirectory(file, recursive, DEFAULT_JAR_DIRECTORY_TYPE);
+ }
+
+ public void addJarDirectory(@NotNull final String url, final boolean recursive, @NotNull OrderRootType rootType) {
assert !isDisposed();
LOG.assertTrue(isWritable());
- final VirtualFilePointerContainer container = myRoots.get(OrderRootType.CLASSES);
+ final VirtualFilePointerContainer container = myRoots.get(rootType);
+ container.add(url);
+ myJarDirectories.add(rootType, url, recursive);
+ }
+
+ public void addJarDirectory(@NotNull final VirtualFile file, final boolean recursive, @NotNull OrderRootType rootType) {
+ assert !isDisposed();
+ LOG.assertTrue(isWritable());
+ final VirtualFilePointerContainer container = myRoots.get(rootType);
container.add(file);
- myJarDirectories.put(file.getUrl(), Boolean.valueOf(recursive));
+ myJarDirectories.add(rootType, file.getUrl(), recursive);
}
public boolean isJarDirectory(@NotNull final String url) {
- return myJarDirectories.containsKey(url);
+ return isJarDirectory(url, DEFAULT_JAR_DIRECTORY_TYPE);
+ }
+
+ public boolean isJarDirectory(@NotNull final String url, @NotNull final OrderRootType rootType) {
+ return myJarDirectories.contains(rootType, url);
}
public boolean isValid(@NotNull final String url, @NotNull final OrderRootType rootType) {
@@ -437,7 +461,7 @@ public class LibraryImpl implements LibraryEx.ModifiableModelEx, LibraryEx {
final VirtualFilePointer byUrl = container.findByUrl(url);
if (byUrl != null) {
container.remove(byUrl);
- myJarDirectories.remove(url);
+ myJarDirectories.remove(rootType, url);
return true;
}
return false;
@@ -510,8 +534,7 @@ public class LibraryImpl implements LibraryEx.ModifiableModelEx, LibraryEx {
if (areRootsChanged(fromModel)) {
disposeMyPointers();
copyRootsFrom(fromModel);
- myJarDirectories.clear();
- myJarDirectories.putAll(fromModel.myJarDirectories);
+ myJarDirectories.copyFrom(fromModel.myJarDirectories);
updateWatchedRoots();
myRootProvider.fireRootSetChanged();
}
@@ -543,12 +566,13 @@ public class LibraryImpl implements LibraryEx.ModifiableModelEx, LibraryEx {
}
if (!myJarDirectories.isEmpty()) {
final VirtualFileManager fm = VirtualFileManager.getInstance();
- for (Map.Entry entry : myJarDirectories.entrySet()) {
- String url = entry.getKey();
- if (fm.getFileSystem(VirtualFileManager.extractProtocol(url)) instanceof LocalFileSystem) {
- final boolean watchRecursively = entry.getValue().booleanValue();
- final LocalFileSystem.WatchRequest request = fs.addRootToWatch(VirtualFileManager.extractPath(url), watchRecursively);
- myWatchRequests.add(request);
+ for (OrderRootType rootType : myJarDirectories.getRootTypes()) {
+ for (String url : myJarDirectories.getDirectories(rootType)) {
+ if (fm.getFileSystem(VirtualFileManager.extractProtocol(url)) instanceof LocalFileSystem) {
+ final boolean watchRecursively = myJarDirectories.isRecursive(rootType, url);
+ final LocalFileSystem.WatchRequest request = fs.addRootToWatch(VirtualFileManager.extractPath(url), watchRecursively);
+ myWatchRequests.add(request);
+ }
}
}
if (myBusConnection == null) {
@@ -599,7 +623,7 @@ public class LibraryImpl implements LibraryEx.ModifiableModelEx, LibraryEx {
}
private boolean isUnderJarDirectory(String url) {
- for (String rootUrl : myJarDirectories.keySet()) {
+ for (String rootUrl : myJarDirectories.getAllDirectories()) {
if (FileUtil.startsWith(url, rootUrl)) {
return true;
}
@@ -666,7 +690,7 @@ public class LibraryImpl implements LibraryEx.ModifiableModelEx, LibraryEx {
@Override
public String toString() {
- return "Library: name:" + myName + "; jars:" + myJarDirectories.keySet() + "; roots:" + myRoots.values();
+ return "Library: name:" + myName + "; jars:" + myJarDirectories + "; roots:" + myRoots.values();
}
@Nullable("will return non-null value only for module level libraries")
diff --git a/platform/lang-impl/src/com/intellij/openapi/roots/libraries/LibraryType.java b/platform/lang-impl/src/com/intellij/openapi/roots/libraries/LibraryType.java
index 96848323fa5f..8ff10be22b76 100644
--- a/platform/lang-impl/src/com/intellij/openapi/roots/libraries/LibraryType.java
+++ b/platform/lang-impl/src/com/intellij/openapi/roots/libraries/LibraryType.java
@@ -16,11 +16,12 @@
package com.intellij.openapi.roots.libraries;
import com.intellij.openapi.extensions.ExtensionPointName;
-import com.intellij.openapi.module.ModuleType;
+import com.intellij.openapi.module.Module;
import com.intellij.openapi.roots.OrderRootType;
import com.intellij.openapi.roots.libraries.ui.LibraryEditorComponent;
import com.intellij.openapi.roots.libraries.ui.LibraryPropertiesEditor;
import com.intellij.openapi.roots.libraries.ui.LibraryRootsComponentDescriptor;
+import com.intellij.openapi.roots.ui.configuration.FacetsProvider;
import com.intellij.openapi.vfs.VirtualFile;
import org.jetbrains.annotations.NotNull;
import org.jetbrains.annotations.Nullable;
@@ -55,9 +56,9 @@ public abstract class LibraryType extends LibraryPr
public abstract P createDefaultProperties();
/**
- * @return {@code true} if library of this type can be added as a dependency to a module of type {@code moduleType}
+ * @return {@code true} if library of this type can be added as a dependency to {@code module}
*/
- public boolean isSuitableModuleType(@NotNull ModuleType moduleType) {
+ public boolean isSuitableModule(@NotNull Module module, @NotNull FacetsProvider facetsProvider) {
return true;
}
diff --git a/platform/lang-impl/src/com/intellij/openapi/roots/ui/configuration/libraryEditor/LibraryEditor.java b/platform/lang-impl/src/com/intellij/openapi/roots/ui/configuration/libraryEditor/LibraryEditor.java
index fb963d9cc85f..3425a3752209 100644
--- a/platform/lang-impl/src/com/intellij/openapi/roots/ui/configuration/libraryEditor/LibraryEditor.java
+++ b/platform/lang-impl/src/com/intellij/openapi/roots/ui/configuration/libraryEditor/LibraryEditor.java
@@ -41,12 +41,18 @@ public interface LibraryEditor {
void addJarDirectory(String url, boolean recursive);
+ void addJarDirectory(VirtualFile file, boolean recursive, OrderRootType rootType);
+
+ void addJarDirectory(String url, boolean recursive, OrderRootType rootType);
+
void removeRoot(String url, OrderRootType rootType);
boolean hasChanges();
boolean isJarDirectory(String url);
+ boolean isJarDirectory(String url, OrderRootType rootType);
+
boolean isValid(String url, OrderRootType orderRootType);
LibraryProperties getProperties();
diff --git a/platform/lang-impl/src/com/intellij/packageDependencies/ui/DirectoryNode.java b/platform/lang-impl/src/com/intellij/packageDependencies/ui/DirectoryNode.java
index d61f0a354b0a..7548449f9da3 100644
--- a/platform/lang-impl/src/com/intellij/packageDependencies/ui/DirectoryNode.java
+++ b/platform/lang-impl/src/com/intellij/packageDependencies/ui/DirectoryNode.java
@@ -128,6 +128,16 @@ public class DirectoryNode extends PackageDependenciesNode {
return myDirectory;
}
+ public PsiDirectory getTargetDirectory() {
+ DirectoryNode dirNode = this;
+ while (dirNode.getCompactedDirNode() != null) {
+ dirNode = dirNode.getCompactedDirNode();
+ assert dirNode != null;
+ }
+
+ return dirNode.myDirectory;
+ }
+
public int getWeight() {
return 3;
}
diff --git a/platform/lang-impl/src/com/intellij/psi/impl/source/codeStyle/CodeFormatterFacade.java b/platform/lang-impl/src/com/intellij/psi/impl/source/codeStyle/CodeFormatterFacade.java
index b901ee55b317..41eba331b17b 100644
--- a/platform/lang-impl/src/com/intellij/psi/impl/source/codeStyle/CodeFormatterFacade.java
+++ b/platform/lang-impl/src/com/intellij/psi/impl/source/codeStyle/CodeFormatterFacade.java
@@ -24,6 +24,7 @@ import com.intellij.lang.LanguageFormatting;
import com.intellij.openapi.actionSystem.DataContext;
import com.intellij.openapi.actionSystem.IdeActions;
import com.intellij.openapi.application.ApplicationManager;
+import com.intellij.openapi.command.CommandProcessor;
import com.intellij.openapi.diagnostic.Logger;
import com.intellij.openapi.editor.*;
import com.intellij.openapi.editor.actionSystem.EditorActionManager;
@@ -52,6 +53,8 @@ import java.util.List;
public class CodeFormatterFacade {
private static final Logger LOG = Logger.getInstance("#com.intellij.psi.impl.source.codeStyle.CodeFormatterFacade");
+
+ private static final String WRAP_LINE_COMMAND_NAME = "AutoWrapLongLine";
/**
* This key is used as a flag that indicates if 'wrap long line during formatting' activity is performed now.
@@ -262,7 +265,7 @@ public class CodeFormatterFacade {
}
}
- private void doWrapLongLinesIfNecessary(@NotNull Editor editor, @NotNull Document document, int startOffset, int endOffset) {
+ private void doWrapLongLinesIfNecessary(@NotNull final Editor editor, @NotNull Document document, int startOffset, int endOffset) {
// Normalization.
int startOffsetToUse = Math.min(document.getTextLength(), Math.max(0, startOffset));
int endOffsetToUse = Math.min(document.getTextLength(), Math.max(0, endOffset));
@@ -365,7 +368,7 @@ public class CodeFormatterFacade {
text, Math.max(startLineOffset, startOffsetToUse), Math.min(endLineOffset, endOffsetToUse), preferredWrapPosition, false
);
editor.getCaretModel().moveToOffset(wrapOffset);
- DataContext dataContext = DataManager.getInstance().getDataContext(editor.getComponent());
+ final DataContext dataContext = DataManager.getInstance().getDataContext(editor.getComponent());
SelectionModel selectionModel = editor.getSelectionModel();
int startSelectionOffset = 0;
@@ -379,8 +382,20 @@ public class CodeFormatterFacade {
int textLengthBeforeWrap = document.getTextLength();
DataManager.getInstance().saveInDataContext(dataContext, WRAP_LONG_LINE_DURING_FORMATTING_IN_PROGRESS_KEY, true);
+ CommandProcessor commandProcessor = CommandProcessor.getInstance();
try {
- EditorActionManager.getInstance().getActionHandler(IdeActions.ACTION_EDITOR_ENTER).execute(editor, dataContext);
+ Runnable command = new Runnable() {
+ @Override
+ public void run() {
+ EditorActionManager.getInstance().getActionHandler(IdeActions.ACTION_EDITOR_ENTER).execute(editor, dataContext);
+ }
+ };
+ if (commandProcessor.getCurrentCommand() == null) {
+ commandProcessor.executeCommand(editor.getProject(), command, WRAP_LINE_COMMAND_NAME, null);
+ }
+ else {
+ command.run();
+ }
}
finally {
DataManager.getInstance().saveInDataContext(dataContext, WRAP_LONG_LINE_DURING_FORMATTING_IN_PROGRESS_KEY, null);
diff --git a/platform/lang-impl/src/com/intellij/psi/impl/source/resolve/reference/impl/PsiMultiReference.java b/platform/lang-impl/src/com/intellij/psi/impl/source/resolve/reference/impl/PsiMultiReference.java
index ebe658b34771..f5e6d6ddd1b2 100644
--- a/platform/lang-impl/src/com/intellij/psi/impl/source/resolve/reference/impl/PsiMultiReference.java
+++ b/platform/lang-impl/src/com/intellij/psi/impl/source/resolve/reference/impl/PsiMultiReference.java
@@ -147,7 +147,7 @@ public class PsiMultiReference implements PsiPolyVariantReference {
@NotNull
public ResolveResult[] multiResolve(final boolean incompleteCode) {
final PsiReference[] refs = getReferences();
- List result = new ArrayList(refs.length);
+ Collection result = new LinkedHashSet(refs.length);
PsiElementResolveResult selfReference = null;
for (PsiReference reference : refs) {
if (reference instanceof PsiPolyVariantReference) {
diff --git a/platform/lang-impl/src/com/intellij/psi/impl/source/text/BlockSupportImpl.java b/platform/lang-impl/src/com/intellij/psi/impl/source/text/BlockSupportImpl.java
index 2395578adf8a..8c49683d476b 100644
--- a/platform/lang-impl/src/com/intellij/psi/impl/source/text/BlockSupportImpl.java
+++ b/platform/lang-impl/src/com/intellij/psi/impl/source/text/BlockSupportImpl.java
@@ -168,6 +168,8 @@ public class BlockSupportImpl extends BlockSupport {
FileType fileType = viewProvider.getVirtualFile().getFileType();
final LightVirtualFile lightFile = new LightVirtualFile(fileImpl.getName(), fileType, newFileText, viewProvider.getVirtualFile().getCharset(),
fileImpl.getModificationStamp());
+ lightFile.setOriginalFile(viewProvider.getVirtualFile());
+
final FileViewProvider copy = viewProvider.createCopy(lightFile);
final PsiFileImpl newFile = (PsiFileImpl)copy.getPsi(fileImpl.getLanguage());
diff --git a/platform/lang-impl/src/com/intellij/psi/impl/source/tree/LazyParseableElement.java b/platform/lang-impl/src/com/intellij/psi/impl/source/tree/LazyParseableElement.java
index 61ff91733922..d1838797b7fc 100644
--- a/platform/lang-impl/src/com/intellij/psi/impl/source/tree/LazyParseableElement.java
+++ b/platform/lang-impl/src/com/intellij/psi/impl/source/tree/LazyParseableElement.java
@@ -22,6 +22,7 @@ package com.intellij.psi.impl.source.tree;
import com.intellij.lang.ASTNode;
import com.intellij.openapi.application.ApplicationManager;
import com.intellij.openapi.application.ex.ApplicationManagerEx;
+import com.intellij.openapi.diagnostic.LogUtil;
import com.intellij.openapi.diagnostic.Logger;
import com.intellij.psi.tree.IElementType;
import com.intellij.psi.tree.ILazyParseableElementType;
@@ -164,7 +165,7 @@ public class LazyParseableElement extends CompositeElement {
}
if (TreeUtil.getFileElement(this) == null) {
- LOG.error("Chameleons must not be parsed till they're in file tree");
+ LOG.error("Chameleons must not be parsed till they're in file tree: " + this);
}
ApplicationManager.getApplication().assertReadAccessAllowed();
@@ -174,9 +175,9 @@ public class LazyParseableElement extends CompositeElement {
if (parsedNode == null && myText.length() > 0) {
if (ApplicationManagerEx.getApplicationEx().isInternal() && !ApplicationManager.getApplication().isUnitTestMode()) {
- LOG.error("No parse for a non-empty string: " + myText + "; type=" + getElementType());
+ LOG.error("No parse for a non-empty string: " + myText + "; type=" + LogUtil.objectAndClass(type));
} else {
- LOG.error("No parse for a non-empty string: type=" + getElementType());
+ LOG.error("No parse for a non-empty string: type=" + LogUtil.objectAndClass(type));
}
}
diff --git a/platform/lang-impl/src/com/intellij/refactoring/extractSuperclass/ExtractSuperBaseDialog.java b/platform/lang-impl/src/com/intellij/refactoring/extractSuperclass/ExtractSuperBaseDialog.java
index 6a24a6e51baa..421f80b568a6 100644
--- a/platform/lang-impl/src/com/intellij/refactoring/extractSuperclass/ExtractSuperBaseDialog.java
+++ b/platform/lang-impl/src/com/intellij/refactoring/extractSuperclass/ExtractSuperBaseDialog.java
@@ -57,10 +57,10 @@ public abstract class ExtractSuperBaseDialog myPackageNameField;
+ protected ComponentWithBrowseButton myPackageNameField;
protected DocCommentPanel myDocCommentPanel;
- protected abstract ComponentWithBrowseButton createPackageNameField();
+ protected abstract ComponentWithBrowseButton createPackageNameField();
protected abstract JTextField createSourceClassField();
@@ -194,9 +194,7 @@ public abstract class ExtractSuperBaseDialog allRenames) {
@@ -65,7 +65,7 @@ public class RenameUtil {
RenamePsiElementProcessor processor = RenamePsiElementProcessor.forElement(element);
Collection refs = processor.findReferences(element);
- for (PsiReference ref : refs) {
+ for (final PsiReference ref : refs) {
if (ref == null) {
LOG.error("null reference from processor " + processor);
continue;
diff --git a/platform/lang-impl/src/com/intellij/ui/EditorTextFieldProviderImpl.java b/platform/lang-impl/src/com/intellij/ui/EditorTextFieldProviderImpl.java
index d7080ec7851d..9b2f16e0c263 100644
--- a/platform/lang-impl/src/com/intellij/ui/EditorTextFieldProviderImpl.java
+++ b/platform/lang-impl/src/com/intellij/ui/EditorTextFieldProviderImpl.java
@@ -71,27 +71,6 @@ public class EditorTextFieldProviderImpl implements EditorTextFieldProvider {
}
};
- @NotNull
- @Override
- public EditorTextField getEditorField(@NotNull Language language,
- @NotNull final Project project,
- @NotNull final EditorCustomization.Feature... features)
- {
- return new MyEditorTextField(language, project) {
- @Override
- protected void applyFeatures(@NotNull EditorCustomization[] customizations, @NotNull EditorEx editor) {
- for (EditorCustomization.Feature feature : features) {
- for (EditorCustomization customization : customizations) {
- if (customization.getSupportedFeatures().contains(feature)) {
- customization.addCustomization(editor, feature);
- break;
- }
- }
- }
- }
- };
- }
-
@NotNull
@Override
public EditorTextField getEditorField(@NotNull Language language,
diff --git a/platform/lang-impl/testSrc/com/intellij/codeInsight/editorActions/enter/EnterAfterJavadocTagHandlerTest.java b/platform/lang-impl/testSrc/com/intellij/codeInsight/editorActions/enter/EnterAfterJavadocTagHandlerTest.java
index 85af3f831cd6..f23e85569751 100644
--- a/platform/lang-impl/testSrc/com/intellij/codeInsight/editorActions/enter/EnterAfterJavadocTagHandlerTest.java
+++ b/platform/lang-impl/testSrc/com/intellij/codeInsight/editorActions/enter/EnterAfterJavadocTagHandlerTest.java
@@ -82,6 +82,12 @@ public class EnterAfterJavadocTagHandlerTest {
context = parse(text);
assertEmpty(context);
}
+
+ @Test
+ public void emptyTag() {
+ EnterAfterJavadocTagHandler.Context context = parse("* ");
+ assertEmpty(context);
+ }
private static EnterAfterJavadocTagHandler.Context parse(String text) {
return parse(text, text.length());
diff --git a/platform/platform-api/src/com/intellij/execution/process/OSProcessHandler.java b/platform/platform-api/src/com/intellij/execution/process/OSProcessHandler.java
index 67aa26bdafa2..20aaf77d4b90 100644
--- a/platform/platform-api/src/com/intellij/execution/process/OSProcessHandler.java
+++ b/platform/platform-api/src/com/intellij/execution/process/OSProcessHandler.java
@@ -247,7 +247,7 @@ public class OSProcessHandler extends ProcessHandler {
while (true) {
final int rc = readAvailable();
if (rc == DONE) break;
- Thread.sleep(rc == READ_SOME ? 1L : 50L);
+ Thread.sleep(rc == READ_SOME ? 1 : 5); // give other threads a chance
}
}
catch (InterruptedException ignore) {
diff --git a/platform/platform-api/src/com/intellij/openapi/actionSystem/IdeActions.java b/platform/platform-api/src/com/intellij/openapi/actionSystem/IdeActions.java
index cc7cd4e9b2de..084d92ab0af4 100644
--- a/platform/platform-api/src/com/intellij/openapi/actionSystem/IdeActions.java
+++ b/platform/platform-api/src/com/intellij/openapi/actionSystem/IdeActions.java
@@ -228,6 +228,8 @@ public interface IdeActions {
@NonNls String ACTION_RENAME = "RenameElement";
@NonNls String ACTION_ANALYZE_DEPENDENCIES = "ShowPackageDeps";
+ @NonNls String ACTION_ANALYZE_BACK_DEPENDENCIES = "ShowBackwardPackageDeps";
+ @NonNls String ACTION_ANALYZE_CYCLIC_DEPENDENCIES = "ShowPackageCycles";
@NonNls String GROUP_MOVE_MODULE_TO_GROUP = "MoveModuleToGroup";
@NonNls String ACTION_CLEAR_TEXT = "TextComponent.ClearAction";
@NonNls String ACTION_HIGHLIGHT_USAGES_IN_FILE = "HighlightUsagesInFile";
diff --git a/platform/platform-api/src/com/intellij/openapi/editor/markup/GutterDraggableObject.java b/platform/platform-api/src/com/intellij/openapi/editor/markup/GutterDraggableObject.java
index 2a7582caf75a..653a9fcdc736 100644
--- a/platform/platform-api/src/com/intellij/openapi/editor/markup/GutterDraggableObject.java
+++ b/platform/platform-api/src/com/intellij/openapi/editor/markup/GutterDraggableObject.java
@@ -15,6 +15,8 @@
*/
package com.intellij.openapi.editor.markup;
+import com.intellij.openapi.vfs.VirtualFile;
+
import java.awt.*;
/**
@@ -22,21 +24,20 @@ import java.awt.*;
* a gutter icon which can be dragged and dropped is the breakpoint icon.
*
* @author ven
+ * @author Konstantin Bulenkov
* @see GutterIconRenderer#getDraggableObject()
*/
public interface GutterDraggableObject {
- /**
- * Called when the drag and drop operation is successfully completed.
- */
- void removeSelf();
-
/**
* Called when the icon is dropped over the specified line.
*
+ *
* @param line the line over which the icon has been dropped.
+ * @param file the DnD target file
* @return true if the drag and drop operation has completed successfully, false otherwise.
+ * @since 10.0.3
*/
- boolean copy(int line);
+ boolean copy(int line, VirtualFile file);
/**
* Returns the cursor to show when the drag is over the specified line.
diff --git a/platform/platform-api/src/com/intellij/openapi/fileTypes/FileTypeManager.java b/platform/platform-api/src/com/intellij/openapi/fileTypes/FileTypeManager.java
index 71896c49bc52..a8a7818fd6f8 100644
--- a/platform/platform-api/src/com/intellij/openapi/fileTypes/FileTypeManager.java
+++ b/platform/platform-api/src/com/intellij/openapi/fileTypes/FileTypeManager.java
@@ -45,6 +45,9 @@ public abstract class FileTypeManager{
return ourInstance;
}
+ /**
+ * @deprecated use {@link com.intellij.openapi.fileTypes.FileTypeFactory} instead
+ */
public abstract void registerFileType(@NotNull FileType type, @NotNull List defaultAssociations);
/**
@@ -53,6 +56,7 @@ public abstract class FileTypeManager{
* @param type The file type to register.
* @param defaultAssociatedExtensions The list of extensions which cause the file to be
* treated as the specified file type. The extensions should not start with '.'.
+ * @deprecated use {@link com.intellij.openapi.fileTypes.FileTypeFactory} instead
*/
public final void registerFileType(@NotNull FileType type, @NonNls @Nullable String... defaultAssociatedExtensions) {
List matchers = new ArrayList();
diff --git a/platform/platform-api/src/com/intellij/openapi/ui/ComponentWithBrowseButton.java b/platform/platform-api/src/com/intellij/openapi/ui/ComponentWithBrowseButton.java
index 532c9c5886ac..b147e71dcd11 100644
--- a/platform/platform-api/src/com/intellij/openapi/ui/ComponentWithBrowseButton.java
+++ b/platform/platform-api/src/com/intellij/openapi/ui/ComponentWithBrowseButton.java
@@ -24,6 +24,7 @@ import com.intellij.openapi.application.ApplicationManager;
import com.intellij.openapi.fileChooser.FileChooser;
import com.intellij.openapi.fileChooser.FileChooserDescriptor;
import com.intellij.openapi.keymap.KeymapUtil;
+import com.intellij.openapi.project.DumbAwareAction;
import com.intellij.openapi.project.Project;
import com.intellij.openapi.util.Disposer;
import com.intellij.openapi.util.SystemInfo;
@@ -149,7 +150,7 @@ public class ComponentWithBrowseButton extends JPanel i
/**
* Do not use this class directly it is public just to hack other implementation of controls similar to TextFieldWithBrowseButton.
*/
- public static final class MyDoClickAction extends AnAction{
+ public static final class MyDoClickAction extends DumbAwareAction {
private final FixedSizeButton myBrowseButton;
public MyDoClickAction(FixedSizeButton browseButton) {
myBrowseButton = browseButton;
diff --git a/platform/platform-api/src/com/intellij/openapi/wm/ToolWindowFactory.java b/platform/platform-api/src/com/intellij/openapi/wm/ToolWindowFactory.java
index 47b2c63ccd8d..23279757b136 100644
--- a/platform/platform-api/src/com/intellij/openapi/wm/ToolWindowFactory.java
+++ b/platform/platform-api/src/com/intellij/openapi/wm/ToolWindowFactory.java
@@ -20,6 +20,7 @@ import com.intellij.openapi.project.Project;
/**
* @author yole
+ * @see ToolWindowEP
*/
public interface ToolWindowFactory {
void createToolWindowContent(Project project, ToolWindow toolWindow);
diff --git a/platform/platform-api/src/com/intellij/testFramework/LightVirtualFile.java b/platform/platform-api/src/com/intellij/testFramework/LightVirtualFile.java
index 59c97e83ba0e..ce6058e8228b 100644
--- a/platform/platform-api/src/com/intellij/testFramework/LightVirtualFile.java
+++ b/platform/platform-api/src/com/intellij/testFramework/LightVirtualFile.java
@@ -42,6 +42,7 @@ public class LightVirtualFile extends DeprecatedVirtualFile {
private boolean myIsWritable = true;
private boolean myValid = true;
private Language myLanguage;
+ private VirtualFile myOriginalFile;
public LightVirtualFile() {
this("");
@@ -111,6 +112,14 @@ public class LightVirtualFile extends DeprecatedVirtualFile {
myContent = content;
}
+ public VirtualFile getOriginalFile() {
+ return myOriginalFile;
+ }
+
+ public void setOriginalFile(VirtualFile originalFile) {
+ myOriginalFile = originalFile;
+ }
+
private static class MyVirtualFileSystem extends DeprecatedVirtualFileSystem {
@NonNls private static final String PROTOCOL = "mock";
diff --git a/platform/platform-api/src/com/intellij/util/IconUtil.java b/platform/platform-api/src/com/intellij/util/IconUtil.java
index 9b4c3a7b13f9..980cf86c3f11 100644
--- a/platform/platform-api/src/com/intellij/util/IconUtil.java
+++ b/platform/platform-api/src/com/intellij/util/IconUtil.java
@@ -28,9 +28,12 @@ import com.intellij.ui.IconDeferrer;
import com.intellij.ui.LayeredIcon;
import com.intellij.ui.RowIcon;
import com.intellij.util.ui.EmptyIcon;
+import org.jetbrains.annotations.NotNull;
import org.jetbrains.annotations.Nullable;
import javax.swing.*;
+import java.awt.*;
+import java.awt.image.BufferedImage;
public class IconUtil {
@@ -178,4 +181,20 @@ public class IconUtil {
private static FileIconPatcher[] getPatchers() {
return FileIconPatcherHolder.ourPatchers;
}
+
+ public static Image toImage(@NotNull Icon icon) {
+ if (icon instanceof ImageIcon) {
+ return ((ImageIcon)icon).getImage();
+ }
+ else {
+ final int w = icon.getIconWidth();
+ final int h = icon.getIconHeight();
+ final BufferedImage image = GraphicsEnvironment.getLocalGraphicsEnvironment()
+ .getDefaultScreenDevice().getDefaultConfiguration().createCompatibleImage(w, h, Color.TRANSLUCENT);
+ final Graphics2D g = image.createGraphics();
+ icon.paintIcon(null, g, 0, 0);
+ g.dispose();
+ return image;
+ }
+ }
}
diff --git a/platform/platform-impl/src/com/intellij/openapi/editor/impl/CaretModelImpl.java b/platform/platform-impl/src/com/intellij/openapi/editor/impl/CaretModelImpl.java
index 9d4e8afd9e36..c8a218c3a956 100644
--- a/platform/platform-impl/src/com/intellij/openapi/editor/impl/CaretModelImpl.java
+++ b/platform/platform-impl/src/com/intellij/openapi/editor/impl/CaretModelImpl.java
@@ -213,7 +213,7 @@ public class CaretModelImpl implements CaretModel, PrioritizedDocumentListener,
int newLineNumber = visualCaret.line + lineShift;
int newColumnNumber = visualCaret.column + columnShift;
- if (desiredX >= 0) {
+ if (desiredX >= 0 && !ApplicationManager.getApplication().isUnitTestMode()) {
newColumnNumber = myEditor.xyToVisualPosition(new Point(desiredX, Math.max(0, newLineNumber) * myEditor.getLineHeight())).column;
}
diff --git a/platform/platform-impl/src/com/intellij/openapi/editor/impl/EditorGutterComponentImpl.java b/platform/platform-impl/src/com/intellij/openapi/editor/impl/EditorGutterComponentImpl.java
index 1adc8a45b4d0..1fb75bc9dda8 100644
--- a/platform/platform-impl/src/com/intellij/openapi/editor/impl/EditorGutterComponentImpl.java
+++ b/platform/platform-impl/src/com/intellij/openapi/editor/impl/EditorGutterComponentImpl.java
@@ -27,6 +27,7 @@ package com.intellij.openapi.editor.impl;
import com.intellij.codeInsight.hint.TooltipController;
import com.intellij.codeInsight.hint.TooltipGroup;
import com.intellij.ide.IdeEventQueue;
+import com.intellij.ide.dnd.*;
import com.intellij.ide.ui.UISettings;
import com.intellij.ide.ui.customization.CustomActionsSchema;
import com.intellij.openapi.actionSystem.*;
@@ -43,10 +44,12 @@ import com.intellij.openapi.editor.markup.*;
import com.intellij.openapi.project.DumbAwareAction;
import com.intellij.openapi.ui.popup.Balloon;
import com.intellij.openapi.util.Comparing;
+import com.intellij.openapi.util.Pair;
import com.intellij.openapi.util.Ref;
import com.intellij.openapi.util.SystemInfo;
import com.intellij.ui.HintHint;
import com.intellij.ui.awt.RelativePoint;
+import com.intellij.util.IconUtil;
import com.intellij.util.containers.HashMap;
import com.intellij.util.ui.UIUtil;
import gnu.trove.TIntArrayList;
@@ -59,15 +62,12 @@ import org.jetbrains.annotations.Nullable;
import javax.swing.*;
import javax.swing.plaf.ComponentUI;
import java.awt.*;
-import java.awt.datatransfer.DataFlavor;
-import java.awt.datatransfer.Transferable;
-import java.awt.dnd.*;
import java.awt.event.*;
import java.awt.geom.AffineTransform;
import java.util.*;
import java.util.List;
-class EditorGutterComponentImpl extends EditorGutterComponentEx implements MouseListener, MouseMotionListener {
+class EditorGutterComponentImpl extends EditorGutterComponentEx implements MouseListener, MouseMotionListener, DnDTarget, DnDSource {
private static final Logger LOG = Logger.getInstance("#com.intellij.openapi.editor.impl.EditorGutterComponentImpl");
private static final int START_ICON_AREA_WIDTH = 15;
private static final int FREE_PAINTERS_AREA_WIDTH = 3;
@@ -86,16 +86,14 @@ class EditorGutterComponentImpl extends EditorGutterComponentEx implements Mouse
private final Map myProviderToListener = new HashMap();
private static final int GAP_BETWEEN_ANNOTATIONS = 6;
private Color myBackgroundColor = null;
- private GutterDraggableObject myGutterDraggableObject;
private String myLastGutterToolTip = null;
private int myLastPreferredHeight = -1;
public EditorGutterComponentImpl(EditorImpl editor) {
myEditor = editor;
if (!ApplicationManager.getApplication().isHeadlessEnvironment()) {
- new DropTarget(this, new MyDropTargetListener());
- final DragSource dragSource = DragSource.getDefaultDragSource();
- dragSource.createDefaultDragGestureRecognizer(this, DnDConstants.ACTION_COPY_OR_MOVE, new MyDragGestureListener());
+ DnDManager.getInstance().registerSource(this, this);
+ DnDManager.getInstance().registerTarget(this, this);
}
setOpaque(true);
}
@@ -342,6 +340,57 @@ class EditorGutterComponentImpl extends EditorGutterComponentEx implements Mouse
g2.setTransform(old);
}
+ @Override
+ public boolean update(DnDEvent aEvent) {
+ aEvent.setDropPossible(true, null);
+ return false;
+ }
+
+ @Override
+ public void drop(DnDEvent aEvent) {
+ final Object attachedObject = aEvent.getAttachedObject();
+ if (attachedObject instanceof GutterIconRenderer) {
+ final GutterDraggableObject draggableObject = ((GutterIconRenderer)attachedObject).getDraggableObject();
+ if (draggableObject != null) {
+ final int line = convertPointToLineNumber(aEvent.getPoint());
+ if (line != -1) {
+ draggableObject.copy(line, myEditor.getVirtualFile());
+ }
+ }
+ }
+ }
+
+ @Override
+ public void cleanUpOnLeave() {
+ }
+
+ @Override
+ public void updateDraggedImage(Image image, Point dropPoint, Point imageOffset) {
+ }
+
+ @Override
+ public boolean canStartDragging(DnDAction action, Point dragOrigin) {
+ return (action == DnDAction.MOVE || action == DnDAction.COPY) && getGutterRenderer(dragOrigin) != null;
+ }
+
+ @Override
+ public DnDDragStartBean startDragging(DnDAction action, Point dragOrigin) {
+ return new DnDDragStartBean(getGutterRenderer(dragOrigin));
+ }
+
+ @Override
+ public Pair createDraggedImage(DnDAction action, Point dragOrigin) {
+ return new Pair(IconUtil.toImage(getGutterRenderer(dragOrigin).getIcon()), dragOrigin);
+ }
+
+ @Override
+ public void dragDropEnd() {
+ }
+
+ @Override
+ public void dropActionChanged(int gestureModifiers) {
+ }
+
private interface RangeHighlighterProcessor {
void process(RangeHighlighter highlighter);
}
@@ -1264,25 +1313,30 @@ class EditorGutterComponentImpl extends EditorGutterComponentEx implements Mouse
TooltipController.getInstance().cancelTooltip(GUTTER_TOOLTIP_GROUP, e, false);
}
- @Nullable
- private GutterIconRenderer getGutterRenderer(final Point p) {
- final int ex = convertX((int)p.getX());
+ private int convertPointToLineNumber(final Point p) {
int line = myEditor.yPositionToLogicalLineNumber((int)p.getY());
- if (line >= myEditor.getDocument().getLineCount()) return null;
+ if (line >= myEditor.getDocument().getLineCount()) return -1;
int startOffset = myEditor.getDocument().getLineStartOffset(line);
final FoldRegion region = myEditor.getFoldingModel().getCollapsedRegionAtOffset(startOffset);
if (region != null) {
line = myEditor.getDocument().getLineNumber(region.getEndOffset());
- if (line >= myEditor.getDocument().getLineCount()) return null;
+ if (line >= myEditor.getDocument().getLineCount()) return -1;
}
+ return line;
+ }
+ @Nullable
+ private GutterIconRenderer getGutterRenderer(final Point p) {
+ int line = convertPointToLineNumber(p);
+ if (line == -1) return null;
ArrayList renderers = myLineToGutterRenderers.get(line);
if (renderers == null) return null;
final GutterIconRenderer[] result = {null};
processIconsRow(line, renderers, new LineGutterIconRendererProcessor() {
public void process(int x, int y, GutterIconRenderer renderer) {
+ final int ex = convertX((int)p.getX());
Icon icon = renderer.getIcon();
if (x <= ex && ex <= x + icon.getIconWidth() &&
y <= p.getY() && p.getY() <= y + icon.getIconHeight()) {
@@ -1310,114 +1364,4 @@ class EditorGutterComponentImpl extends EditorGutterComponentEx implements Mouse
}
myProviderToListener.clear();
}
-
- private static final DataFlavor[] FLAVORS;
- static {
- DataFlavor[] flavors;
- try {
- final Class aClass = EditorGutterComponentImpl.class;
- //noinspection HardCodedStringLiteral
- flavors = new DataFlavor[]{new DataFlavor(
- DataFlavor.javaJVMLocalObjectMimeType + ";class=" + aClass.getName(), "GutterTransferable", aClass.getClassLoader()
- )};
- }
- catch (ClassNotFoundException e) {
- LOG.error(e); // should not happen
- flavors = new DataFlavor[0];
- }
- FLAVORS = flavors;
- }
-
- private class MyDragGestureListener implements DragGestureListener {
- public void dragGestureRecognized(DragGestureEvent dge) {
- if ((dge.getDragAction() & DnDConstants.ACTION_MOVE) == 0) return;
- final GutterIconRenderer renderer = getGutterRenderer(dge.getDragOrigin());
- if (renderer != null) {
- final GutterDraggableObject draggableObject = renderer.getDraggableObject();
- if (draggableObject != null) {
- try {
- myGutterDraggableObject = draggableObject;
- final MyDragSourceListener dragSourceListener = new MyDragSourceListener();
- dge.startDrag(DragSource.DefaultMoveNoDrop, new Transferable () {
- public DataFlavor[] getTransferDataFlavors() {
- return FLAVORS;
- }
-
- public boolean isDataFlavorSupported(DataFlavor flavor) {
- DataFlavor[] flavors = getTransferDataFlavors();
- for (DataFlavor flavor1 : flavors) {
- if (flavor.equals(flavor1)) {
- return true;
- }
- }
- return false;
- }
-
- public Object getTransferData(DataFlavor flavor) {
- return null;
- }
- }, dragSourceListener);
- }
- catch (InvalidDnDOperationException e) {
- // OK, can't dnd
- }
- }
-
- }
- }
- }
-
- private class MyDragSourceListener extends DragSourceAdapter {
- public void dragEnter(DragSourceDragEvent e) {
- updateCursor(e);
- }
-
- public void dragOver(DragSourceDragEvent e) {
- updateCursor(e);
- }
-
- public void dropActionChanged(DragSourceDragEvent e) {
- e.getDragSourceContext().setCursor(null);//setCursor (e.getDragSourceContext());
- }
-
- private void updateCursor(final DragSourceDragEvent e) {
- final DragSourceContext context = e.getDragSourceContext();
- final Point screenPoint = e.getLocation();
- if (screenPoint != null) {
- final Point gutterPoint = new Point(screenPoint);
- SwingUtilities.convertPointFromScreen(gutterPoint, EditorGutterComponentImpl.this);
- if (contains(gutterPoint)){
- final Point editorPoint = new Point(screenPoint);
- SwingUtilities.convertPointFromScreen(editorPoint, myEditor.getContentComponent());
- int line = myEditor.yPositionToLogicalLineNumber((int)editorPoint.getY());
- final Cursor cursor = myGutterDraggableObject.getCursor(line);
- context.setCursor(cursor);
- return;
- }
- }
- context.setCursor(null);
- }
-
- public void dragDropEnd(DragSourceDropEvent e) {
- if (!e.getDropSuccess()) return;
-
- if (e.getDropAction() == DnDConstants.ACTION_MOVE) {
- myGutterDraggableObject.removeSelf();
- }
- }
- }
-
- private class MyDropTargetListener extends DropTargetAdapter {
- public void drop(DropTargetDropEvent e) {
- if (myGutterDraggableObject != null) {
- int dropAction = e.getDropAction();
- if ((dropAction & DnDConstants.ACTION_MOVE) != 0) {
- int line = myEditor.yPositionToLogicalLineNumber((int)e.getLocation().getY());
- e.dropComplete(myGutterDraggableObject.copy(line));
- return;
- }
- }
- e.rejectDrop();
- }
- }
}
diff --git a/platform/platform-impl/src/com/intellij/openapi/editor/impl/EditorImpl.java b/platform/platform-impl/src/com/intellij/openapi/editor/impl/EditorImpl.java
index 817d9c403aad..b5592d73278e 100644
--- a/platform/platform-impl/src/com/intellij/openapi/editor/impl/EditorImpl.java
+++ b/platform/platform-impl/src/com/intellij/openapi/editor/impl/EditorImpl.java
@@ -1105,7 +1105,14 @@ public final class EditorImpl extends UserDataHolderBase implements EditorEx, Hi
return result;
}
int line = calcLogicalLineNumber(offset);
- int lineStartOffset = myDocument.getLineStartOffset(line);
+ int lineStartOffset;
+ if (line >= myDocument.getLineCount()) {
+ lineStartOffset = myDocument.getTextLength();
+ }
+ else {
+ lineStartOffset = myDocument.getLineStartOffset(line);
+ }
+
int result = logicalToVisualLine(line);
// There is a possible case that logical line that contains target offset is soft-wrapped (represented in more than one visual
diff --git a/platform/platform-impl/src/com/intellij/openapi/vfs/ex/temp/TempFileSystem.java b/platform/platform-impl/src/com/intellij/openapi/vfs/ex/temp/TempFileSystem.java
index d8ac54057138..53c50574e1ab 100644
--- a/platform/platform-impl/src/com/intellij/openapi/vfs/ex/temp/TempFileSystem.java
+++ b/platform/platform-impl/src/com/intellij/openapi/vfs/ex/temp/TempFileSystem.java
@@ -245,6 +245,11 @@ public class TempFileSystem extends NewVirtualFileSystem {
public String[] list() {
return ArrayUtil.EMPTY_STRING_ARRAY;
}
+
+ @Override
+ public String toString() {
+ return getClass().getSimpleName() + ": " + myName;
+ }
}
private static class FSDir extends FSItem {
diff --git a/platform/platform-impl/src/com/intellij/ui/EditorTextFieldProvider.java b/platform/platform-impl/src/com/intellij/ui/EditorTextFieldProvider.java
index 933c7eb835e1..c6d669203130 100644
--- a/platform/platform-impl/src/com/intellij/ui/EditorTextFieldProvider.java
+++ b/platform/platform-impl/src/com/intellij/ui/EditorTextFieldProvider.java
@@ -28,15 +28,6 @@ import org.jetbrains.annotations.NotNull;
*/
public interface EditorTextFieldProvider {
- /**
- * @param language target language used by document that will be displayed by returned editor
- * @param project target project
- * @param features features to use within the returned editor text field
- * @return Multiline {@link EditorTextField} with spell checking support.
- */
- @NotNull
- EditorTextField getEditorField(@NotNull Language language, @NotNull Project project, @NotNull EditorCustomization.Feature ... features);
-
/**
* It's possible either {@link EditorCustomization#addCustomization(EditorEx, EditorCustomization.Feature) apply} or
* {@link EditorCustomization#removeCustomization(EditorEx, EditorCustomization.Feature) remove} customizations from
diff --git a/platform/platform-resources-en/src/messages/ApplicationBundle.properties b/platform/platform-resources-en/src/messages/ApplicationBundle.properties
index 0e580c30af42..d6e18c427278 100644
--- a/platform/platform-resources-en/src/messages/ApplicationBundle.properties
+++ b/platform/platform-resources-en/src/messages/ApplicationBundle.properties
@@ -132,6 +132,7 @@ wrapping.keep.when.reformatting=Keep when reformatting
wrapping.keep.line.breaks=Line breaks
wrapping.keep.comment.at.first.column=Comment at first column
wrapping.keep.simple.methods.in.one.line=Simple methods in one line
+wrapping.keep.multiple.expressions.in.one.line=Multiple expressions in one line
wrapping.keep.simple.blocks.in.one.line=Simple blocks in one line
wrapping.do.not.wrap=Do not wrap
diff --git a/platform/platform-resources-en/src/messages/ProjectBundle.properties b/platform/platform-resources-en/src/messages/ProjectBundle.properties
index daeb0acdff8a..66375fb926c4 100644
--- a/platform/platform-resources-en/src/messages/ProjectBundle.properties
+++ b/platform/platform-resources-en/src/messages/ProjectBundle.properties
@@ -170,6 +170,9 @@ library.attach.classes.description=Select jar/zip files or directories in which
library.attach.jar.directory.to.library.action=Attach Jar Directories to Library \"{0}\"
library.attach.jar.directory.action=Attach Jar Directories
library.attach.jar.directory.description=Select directories in which jar/zip files are located
+library.attach.jar.sources.directory.to.library.action=Attach Source Archive Directories to Library \"{0}\"
+library.attach.jar.sources.directory.action=Attach Source Archive Directories
+library.attach.jar.sources.directory.description=Select directories in which source jar/zip files are located
library.sources.not.found=Sources not found
library.sources.not.attached=Sources not attached
library.attach.sources.action=Attach Sources
@@ -179,6 +182,7 @@ library.attach.javadoc.action=Attach Javadoc
library.attach.javadoc.description=Select jar/zip files or directories in which library javadoc documentation is located
module.libraries.attach.jar.directories.button=Attach Jar &Directories...
+module.libraries.attach.jar.sources.directories.button=Attach Source Archive D&irectories...
library.attach.external.annotations.action=Attach external annotations
library.attach.external.annotations.description=Select root where external annotations is located
@@ -459,7 +463,7 @@ label.text.framework.support.description=This will download all needed libraries
file.chooser.directory.for.downloaded.libraries.title=Directory for Downloaded Libraries
file.chooser.directory.for.downloaded.libraries.description=Downloaded libraries will be copied to selected directory
dialog.title.library.downloading.settings=Library Downloading Settings
-directory.roots.copy.label=Copy library content to directory (optional):
+directory.roots.copy.label=Copy library content to directory (optional):
combobox.item.global.library=Global Library
combobox.item.project.library=Project Library
combobox.item.module.library=Module Library
@@ -481,4 +485,4 @@ project.new.wizard.import.footnote=Import from external model is available from
loading.components.for=Loading components for ''{0}''
initializing.components=Initializing components
-library.docs.node=Documentation
\ No newline at end of file
+library.docs.node=Documentation
diff --git a/platform/platform-resources-en/src/messages/RefactoringBundle.properties b/platform/platform-resources-en/src/messages/RefactoringBundle.properties
index 3eb998446656..dc13df3beed0 100644
--- a/platform/platform-resources-en/src/messages/RefactoringBundle.properties
+++ b/platform/platform-resources-en/src/messages/RefactoringBundle.properties
@@ -743,4 +743,5 @@ change.signature.leave.blank.default.value=Leave &blank
change.signature.feel.lucky=Feel &lucky
change.signature.use.selected.value=Use selected &value
-search.for.references=Search for re&ferences
\ No newline at end of file
+search.for.references=Search for re&ferences
+0.is.not.an.identifier={0} is not a correct identifier to use in {1}
\ No newline at end of file
diff --git a/platform/platform-resources/src/idea/LangActions.xml b/platform/platform-resources/src/idea/LangActions.xml
index 8d1074c547f9..a87fe7ed3a9f 100644
--- a/platform/platform-resources/src/idea/LangActions.xml
+++ b/platform/platform-resources/src/idea/LangActions.xml
@@ -786,6 +786,11 @@
+
+
+
+
+
diff --git a/platform/smRunner/src/com/intellij/execution/testframework/sm/runner/GeneralTestEventsProcessor.java b/platform/smRunner/src/com/intellij/execution/testframework/sm/runner/GeneralTestEventsProcessor.java
index 9cc012aef90d..9d9f907dafd0 100644
--- a/platform/smRunner/src/com/intellij/execution/testframework/sm/runner/GeneralTestEventsProcessor.java
+++ b/platform/smRunner/src/com/intellij/execution/testframework/sm/runner/GeneralTestEventsProcessor.java
@@ -37,10 +37,12 @@ public interface GeneralTestEventsProcessor extends Disposable {
void onTestFinished(@NotNull final String testName,
final int duration);
- void onTestFailure(@NotNull final String testName,
+ void onTestFailure(@NotNull final String testName,
@NotNull final String localizedMessage,
@Nullable final String stackTrace,
- final boolean testError);
+ final boolean testError,
+ @Nullable final String comparisionFailureActualText,
+ @Nullable final String comparisionFailureExpectedText);
void onTestIgnored(@NotNull final String testName,
@NotNull final String ignoreComment,
diff --git a/platform/smRunner/src/com/intellij/execution/testframework/sm/runner/GeneralToSMTRunnerEventsConvertor.java b/platform/smRunner/src/com/intellij/execution/testframework/sm/runner/GeneralToSMTRunnerEventsConvertor.java
index b96b6002905f..c0685f237d26 100644
--- a/platform/smRunner/src/com/intellij/execution/testframework/sm/runner/GeneralToSMTRunnerEventsConvertor.java
+++ b/platform/smRunner/src/com/intellij/execution/testframework/sm/runner/GeneralToSMTRunnerEventsConvertor.java
@@ -240,7 +240,9 @@ public class GeneralToSMTRunnerEventsConvertor implements GeneralTestEventsProce
public void onTestFailure(@NotNull final String testName,
@NotNull final String localizedMessage,
@Nullable final String stackTrace,
- final boolean isTestError) {
+ final boolean isTestError,
+ @Nullable final String comparisionFailureActualText,
+ @Nullable final String comparisionFailureExpectedText) {
SMRunnerUtil.addToInvokeLater(new Runnable() {
public void run() {
final boolean inDebugMode = SMTestRunnerConnectionUtil.isInDebugMode();
@@ -281,8 +283,20 @@ public class GeneralToSMTRunnerEventsConvertor implements GeneralTestEventsProce
if (testProxy == null) {
return;
}
- testProxy.setTestFailed(localizedMessage, stackTrace, isTestError);
+ if (comparisionFailureActualText != null && comparisionFailureExpectedText != null) {
+ testProxy.setTestComparisonFailed(localizedMessage, stackTrace,
+ comparisionFailureActualText, comparisionFailureExpectedText);
+ } else if (comparisionFailureActualText == null && comparisionFailureExpectedText == null) {
+ testProxy.setTestFailed(localizedMessage, stackTrace, isTestError);
+ } else {
+ logProblem("Comparison failure actual and expected texts should be both null or not null.\n"
+ + "Expected:\n"
+ + comparisionFailureExpectedText + "\n"
+ + "Actual:\n"
+ + comparisionFailureActualText,
+ inDebugMode);
+ }
myFailedTestsSet.add(testProxy);
diff --git a/platform/smRunner/src/com/intellij/execution/testframework/sm/runner/OutputToGeneralTestEventsConverter.java b/platform/smRunner/src/com/intellij/execution/testframework/sm/runner/OutputToGeneralTestEventsConverter.java
index fea168f9ef6f..01e4d7a955dc 100644
--- a/platform/smRunner/src/com/intellij/execution/testframework/sm/runner/OutputToGeneralTestEventsConverter.java
+++ b/platform/smRunner/src/com/intellij/execution/testframework/sm/runner/OutputToGeneralTestEventsConverter.java
@@ -184,15 +184,20 @@ public class OutputToGeneralTestEventsConverter implements ProcessOutputConsumer
}
}
- private void fireOnTestFailure(final String testName, final String localizedMessage, final String stackTrace,
- final boolean isTestError) {
+ private void fireOnTestFailure(final String testName,
+ final String localizedMessage, final String stackTrace,
+ final boolean isTestError,
+ @Nullable final String comparisionFailureActualText,
+ @Nullable final String comparisionFailureExpectedText) {
assertNotNull(testName);
assertNotNull(localizedMessage);
// local variable is used to prevent concurrent modification
final GeneralTestEventsProcessor processor = myProcessor;
if (processor != null) {
- processor.onTestFailure(testName, localizedMessage, stackTrace, isTestError);
+ processor.onTestFailure(testName, localizedMessage, stackTrace, isTestError,
+ comparisionFailureActualText,
+ comparisionFailureExpectedText);
}
}
@@ -396,7 +401,12 @@ public class OutputToGeneralTestEventsConverter implements ProcessOutputConsumer
public void visitTestFailed(@NotNull final TestFailed testFailed) {
final boolean isTestError = testFailed.getAttributes().get(ATTR_KEY_TEST_ERROR) != null;
- fireOnTestFailure(testFailed.getTestName(), testFailed.getFailureMessage(), testFailed.getStacktrace(), isTestError);
+ fireOnTestFailure(testFailed.getTestName(),
+ testFailed.getFailureMessage(),
+ testFailed.getStacktrace(),
+ isTestError,
+ testFailed.getActual(),
+ testFailed.getExpected());
}
public void visitPublishArtifacts(@NotNull final PublishArtifacts publishArtifacts) {
diff --git a/platform/smRunner/src/com/intellij/execution/testframework/sm/runner/SMTestProxy.java b/platform/smRunner/src/com/intellij/execution/testframework/sm/runner/SMTestProxy.java
index 390d69b42d7d..6decd4ab0159 100644
--- a/platform/smRunner/src/com/intellij/execution/testframework/sm/runner/SMTestProxy.java
+++ b/platform/smRunner/src/com/intellij/execution/testframework/sm/runner/SMTestProxy.java
@@ -298,6 +298,15 @@ public class SMTestProxy extends AbstractTestProxy {
fireOnNewPrintable(myState);
}
+ public void setTestComparisonFailed(@NotNull final String localizedMessage,
+ @Nullable final String stackTrace,
+ @NotNull final String actualText,
+ @NotNull final String expectedText) {
+ myState = new TestComparisionFailedState(localizedMessage, stackTrace,
+ actualText, expectedText);
+ fireOnNewPrintable(myState);
+ }
+
public void setTestIgnored(@NotNull final String ignoreComment,
@Nullable final String stackTrace) {
myState = new TestIgnoredState(ignoreComment, stackTrace);
@@ -391,6 +400,15 @@ public class SMTestProxy extends AbstractTestProxy {
return TestsPresentationUtil.getPresentableName(this);
}
+ @Override
+ @Nullable
+ public AssertEqualsDiffViewerProvider getDiffViewerProvider() {
+ if (myState instanceof AssertEqualsDiffViewerProvider) {
+ return (AssertEqualsDiffViewerProvider)myState;
+ }
+ return null;
+ }
+
@Override
public String toString() {
return getPresentableName();
diff --git a/platform/smRunner/src/com/intellij/execution/testframework/sm/runner/states/TestComparisionFailedState.java b/platform/smRunner/src/com/intellij/execution/testframework/sm/runner/states/TestComparisionFailedState.java
new file mode 100644
index 000000000000..79cf7e93881c
--- /dev/null
+++ b/platform/smRunner/src/com/intellij/execution/testframework/sm/runner/states/TestComparisionFailedState.java
@@ -0,0 +1,85 @@
+/*
+ * Copyright 2000-2011 JetBrains s.r.o.
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+package com.intellij.execution.testframework.sm.runner.states;
+
+import com.intellij.execution.testframework.AbstractTestProxy;
+import com.intellij.execution.testframework.CompositePrintable;
+import com.intellij.execution.testframework.Printer;
+import com.intellij.execution.testframework.stacktrace.DiffHyperlink;
+import com.intellij.execution.ui.ConsoleViewContentType;
+import com.intellij.openapi.project.Project;
+import com.intellij.openapi.util.text.StringUtil;
+import org.jetbrains.annotations.NotNull;
+import org.jetbrains.annotations.Nullable;
+
+/**
+ * @author Roman.Chernyatchik
+ */
+public class TestComparisionFailedState extends TestFailedState implements AbstractTestProxy.AssertEqualsDiffViewerProvider {
+ private final String myErrorMsgPresentation;
+ private final String myStacktracePresentation;
+ private DiffHyperlink myHyperlink;
+
+
+ public TestComparisionFailedState(@Nullable final String localizedMessage,
+ @Nullable final String stackTrace,
+ @NotNull final String actualText,
+ @NotNull final String expectedText) {
+ super(localizedMessage, stackTrace);
+ myHyperlink = new DiffHyperlink(actualText, expectedText, null);
+
+ myErrorMsgPresentation = StringUtil.isEmptyOrSpaces(localizedMessage) ? ""
+ : localizedMessage;
+ myStacktracePresentation = StringUtil.isEmptyOrSpaces(stackTrace) ? ""
+ : stackTrace;
+ }
+
+ @Override
+ public void printOn(Printer printer) {
+ printer.print(CompositePrintable.NEW_LINE, ConsoleViewContentType.ERROR_OUTPUT);
+ printer.mark();
+
+ // Error msg
+ if (myErrorMsgPresentation != null) {
+ printer.print(myErrorMsgPresentation, ConsoleViewContentType.ERROR_OUTPUT);
+ }
+
+ // Diff link
+ myHyperlink.printOn(printer);
+
+ // Stacktrace
+ if (myStacktracePresentation != null) {
+ printer.print(CompositePrintable.NEW_LINE, ConsoleViewContentType.ERROR_OUTPUT);
+
+ printer.print(myStacktracePresentation, ConsoleViewContentType.ERROR_OUTPUT);
+ printer.print(CompositePrintable.NEW_LINE, ConsoleViewContentType.ERROR_OUTPUT);
+ }
+ }
+
+ public void openDiff(final Project project) {
+ myHyperlink.openDiff(project);
+ }
+
+ @Override
+ public String getExpecteed() {
+ return myHyperlink.getLeft();
+ }
+
+ @Override
+ public String getActual() {
+ return myHyperlink.getRight();
+ }
+}
diff --git a/platform/smRunner/src/com/intellij/execution/testframework/sm/runner/states/TestFailedState.java b/platform/smRunner/src/com/intellij/execution/testframework/sm/runner/states/TestFailedState.java
index 879f75b6b77a..a9b3c3a7bc49 100644
--- a/platform/smRunner/src/com/intellij/execution/testframework/sm/runner/states/TestFailedState.java
+++ b/platform/smRunner/src/com/intellij/execution/testframework/sm/runner/states/TestFailedState.java
@@ -17,7 +17,6 @@ package com.intellij.execution.testframework.sm.runner.states;
import com.intellij.execution.testframework.CompositePrintable;
import com.intellij.execution.testframework.Printer;
-import com.intellij.execution.testframework.sm.runner.SMTestProxy;
import com.intellij.execution.ui.ConsoleViewContentType;
import com.intellij.openapi.util.text.StringUtil;
import org.jetbrains.annotations.NotNull;
diff --git a/platform/smRunner/testSrc/com/intellij/execution/testframework/sm/runner/GeneralToSMTRunnerEventsConvertorTest.java b/platform/smRunner/testSrc/com/intellij/execution/testframework/sm/runner/GeneralToSMTRunnerEventsConvertorTest.java
index 7e44c03084ee..1418f5b3f9fa 100644
--- a/platform/smRunner/testSrc/com/intellij/execution/testframework/sm/runner/GeneralToSMTRunnerEventsConvertorTest.java
+++ b/platform/smRunner/testSrc/com/intellij/execution/testframework/sm/runner/GeneralToSMTRunnerEventsConvertorTest.java
@@ -125,7 +125,18 @@ public class GeneralToSMTRunnerEventsConvertorTest extends BaseSMTRunnerTestCase
public void testOnTestFailure() {
onTestStarted("some_test");
- myEventsProcessor.onTestFailure("some_test", "", "", false);
+ myEventsProcessor.onTestFailure("some_test", "", "", false, null, null);
+
+ final String fullName = myEventsProcessor.getFullTestName("some_test");
+ final SMTestProxy proxy = myEventsProcessor.getProxyByFullTestName(fullName);
+
+ assertTrue(proxy.isDefect());
+ assertFalse(proxy.isInProgress());
+ }
+
+ public void testOnTestComparisionFailure() {
+ onTestStarted("some_test");
+ myEventsProcessor.onTestFailure("some_test", "", "", false, "actual", "expected");
final String fullName = myEventsProcessor.getFullTestName("some_test");
final SMTestProxy proxy = myEventsProcessor.getProxyByFullTestName(fullName);
@@ -136,8 +147,8 @@ public class GeneralToSMTRunnerEventsConvertorTest extends BaseSMTRunnerTestCase
public void testOnTestFailure_Twice() {
onTestStarted("some_test");
- myEventsProcessor.onTestFailure("some_test", "", "", false);
- myEventsProcessor.onTestFailure("some_test", "", "", false);
+ myEventsProcessor.onTestFailure("some_test", "", "", false, null, null);
+ myEventsProcessor.onTestFailure("some_test", "", "", false, null, null);
assertEquals(1, myEventsProcessor.getRunningTestsQuantity());
assertEquals(1, myEventsProcessor.getFailedTestsSet().size());
@@ -145,7 +156,7 @@ public class GeneralToSMTRunnerEventsConvertorTest extends BaseSMTRunnerTestCase
public void testOnTestError() {
onTestStarted("some_test");
- myEventsProcessor.onTestFailure("some_test", "", "", true);
+ myEventsProcessor.onTestFailure("some_test", "", "", true, null, null);
final String fullName = myEventsProcessor.getFullTestName("some_test");
final SMTestProxy proxy = myEventsProcessor.getProxyByFullTestName(fullName);
@@ -213,7 +224,7 @@ public class GeneralToSMTRunnerEventsConvertorTest extends BaseSMTRunnerTestCase
public void testOnFinishedTesting_WithFailure() {
onTestStarted("test");
- myEventsProcessor.onTestFailure("test", "", "", false);
+ myEventsProcessor.onTestFailure("test", "", "", false, null, null);
myEventsProcessor.onTestFinished("test", 10);
myEventsProcessor.onFinishTesting();
@@ -229,7 +240,7 @@ public class GeneralToSMTRunnerEventsConvertorTest extends BaseSMTRunnerTestCase
public void testOnFinishedTesting_WithError() {
onTestStarted("test");
- myEventsProcessor.onTestFailure("test", "", "", true);
+ myEventsProcessor.onTestFailure("test", "", "", true, null, null);
myEventsProcessor.onTestFinished("test", 10);
myEventsProcessor.onFinishTesting();
diff --git a/platform/smRunner/testSrc/com/intellij/execution/testframework/sm/runner/SMTRunnerConsoleTest.java b/platform/smRunner/testSrc/com/intellij/execution/testframework/sm/runner/SMTRunnerConsoleTest.java
index d7e55369934f..f68a3c6392e3 100644
--- a/platform/smRunner/testSrc/com/intellij/execution/testframework/sm/runner/SMTRunnerConsoleTest.java
+++ b/platform/smRunner/testSrc/com/intellij/execution/testframework/sm/runner/SMTRunnerConsoleTest.java
@@ -203,7 +203,7 @@ public class SMTRunnerConsoleTest extends BaseSMTRunnerTestCase {
public void testProcessor_OnFailure() {
final SMTestProxy myTest1 = startTestWithPrinter("my_test");
- myEventsProcessor.onTestFailure("my_test", "error msg", "method1:1\nmethod2:2", false);
+ myEventsProcessor.onTestFailure("my_test", "error msg", "method1:1\nmethod2:2", false, null, null);
myEventsProcessor.onTestOutput("my_test", "stdout1 ", true);
myEventsProcessor.onTestOutput("my_test", "stderr1 ", false);
@@ -217,7 +217,7 @@ public class SMTRunnerConsoleTest extends BaseSMTRunnerTestCase {
final SMTestProxy myTest2 = startTestWithPrinter("my_test2");
myEventsProcessor.onTestOutput("my_test2", "stdout1 ", true);
myEventsProcessor.onTestOutput("my_test2", "stderr1 ", false);
- myEventsProcessor.onTestFailure("my_test2", "error msg", "method1:1\nmethod2:2", false);
+ myEventsProcessor.onTestFailure("my_test2", "error msg", "method1:1\nmethod2:2", false, null, null);
assertAllOutputs(myMockResetablePrinter, "stdout1 ", "stderr1 \nerror msg\nmethod1:1\nmethod2:2\n", "");
final MockPrinter mockPrinter2 = new MockPrinter(true);
@@ -228,7 +228,7 @@ public class SMTRunnerConsoleTest extends BaseSMTRunnerTestCase {
public void testProcessor_OnFailure_EmptyStacktrace() {
final SMTestProxy myTest1 = startTestWithPrinter("my_test");
- myEventsProcessor.onTestFailure("my_test", "error msg", "\n\n", false);
+ myEventsProcessor.onTestFailure("my_test", "error msg", "\n\n", false, null, null);
myEventsProcessor.onTestOutput("my_test", "stdout1 ", true);
myEventsProcessor.onTestOutput("my_test", "stderr1 ", false);
@@ -239,10 +239,70 @@ public class SMTRunnerConsoleTest extends BaseSMTRunnerTestCase {
assertAllOutputs(mockPrinter1, "stdout1 ", "stderr1 \nerror msg\n", "");
}
+ public void testProcessor_OnFailure_Comparision_Strings() {
+ final SMTestProxy myTest1 = startTestWithPrinter("my_test");
+
+ myEventsProcessor.onTestFailure("my_test", "error msg", "method1:1\nmethod2:2", false, "actual", "expected");
+ myEventsProcessor.onTestOutput("my_test", "stdout1 ", true);
+ myEventsProcessor.onTestOutput("my_test", "stderr1 ", false);
+
+ assertAllOutputs(myMockResetablePrinter,
+ // std out
+ "stdout1 ",
+ // std err
+ "\n" +
+ "error msg\n" +
+ "actual\n" +
+ "expected\n" +
+ "\n" +
+ "method1:1\n" +
+ "method2:2\n" +
+ "stderr1 ",
+ // std sys
+ "Expected :Actual :");
+
+ final MockPrinter mockPrinter1 = new MockPrinter(true);
+ mockPrinter1.onNewAvailable(myTest1);
+ assertAllOutputs(mockPrinter1,
+ // std out
+ "stdout1 ",
+ // std err
+ "stderr1 \nerror msg\n" +
+ "actual\n" +
+ "expected\n" +
+ "\n" +
+ "method1:1\nmethod2:2\n",
+ // std sys
+ "Expected :Actual :");
+ }
+
+ public void testProcessor_OnFailure_Comparision_MultilineTexts() {
+ final SMTestProxy myTest1 = startTestWithPrinter("my_test");
+
+ myEventsProcessor.onTestFailure("my_test", "error msg", "method1:1\nmethod2:2", false,
+ "this is:\nactual", "this is:\nexpected");
+ myEventsProcessor.onTestOutput("my_test", "stdout1 ", true);
+ myEventsProcessor.onTestOutput("my_test", "stderr1 ", false);
+
+ assertAllOutputs(myMockResetablePrinter, "stdout1 ", "\nerror msg \n" +
+ "\n" +
+ "method1:1\n" +
+ "method2:2\n" +
+ "stderr1 ", "");
+
+ final MockPrinter mockPrinter1 = new MockPrinter(true);
+ mockPrinter1.onNewAvailable(myTest1);
+ assertAllOutputs(mockPrinter1, "stdout1 ", "stderr1 \n" +
+ "error msg \n" +
+ "\n" +
+ "method1:1\n" +
+ "method2:2\n", "");
+ }
+
public void testProcessor_OnError() {
final SMTestProxy myTest1 = startTestWithPrinter("my_test");
- myEventsProcessor.onTestFailure("my_test", "error msg", "method1:1\nmethod2:2", true);
+ myEventsProcessor.onTestFailure("my_test", "error msg", "method1:1\nmethod2:2", true, null, null);
myEventsProcessor.onTestOutput("my_test", "stdout1 ", true);
myEventsProcessor.onTestOutput("my_test", "stderr1 ", false);
@@ -256,7 +316,7 @@ public class SMTRunnerConsoleTest extends BaseSMTRunnerTestCase {
final SMTestProxy myTest2 = startTestWithPrinter("my_test2");
myEventsProcessor.onTestOutput("my_test2", "stdout1 ", true);
myEventsProcessor.onTestOutput("my_test2", "stderr1 ", false);
- myEventsProcessor.onTestFailure("my_test2", "error msg", "method1:1\nmethod2:2", true);
+ myEventsProcessor.onTestFailure("my_test2", "error msg", "method1:1\nmethod2:2", true, null, null);
assertAllOutputs(myMockResetablePrinter, "stdout1 ", "stderr1 \nerror msg\nmethod1:1\nmethod2:2\n", "");
final MockPrinter mockPrinter2 = new MockPrinter(true);
diff --git a/platform/smRunner/testSrc/com/intellij/execution/testframework/sm/runner/SMTestProxyTest.java b/platform/smRunner/testSrc/com/intellij/execution/testframework/sm/runner/SMTestProxyTest.java
index 0c560a8da989..e993f57de7bc 100644
--- a/platform/smRunner/testSrc/com/intellij/execution/testframework/sm/runner/SMTestProxyTest.java
+++ b/platform/smRunner/testSrc/com/intellij/execution/testframework/sm/runner/SMTestProxyTest.java
@@ -177,6 +177,25 @@ public class SMTestProxyTest extends BaseSMTRunnerTestCase {
assertTrue(mySimpleTest.getMagnitudeInfo() == Magnitude.FAILED_INDEX);
}
+
+ public void testTestFailed_ComparisionAssertion() {
+ mySimpleTest.setStarted();
+ mySimpleTest.setTestComparisonFailed("", "", "", "");
+
+ assertFalse(mySimpleTest.isInProgress());
+ assertTrue(mySimpleTest.wasLaunched());
+ assertTrue(mySimpleTest.isDefect());
+ assertTrue(mySimpleTest.getMagnitudeInfo() == Magnitude.FAILED_INDEX);
+
+ mySimpleTest.setFinished();
+
+ assertFalse(mySimpleTest.isInProgress());
+ assertTrue(mySimpleTest.wasLaunched());
+ assertTrue(mySimpleTest.isDefect());
+
+ assertTrue(mySimpleTest.getMagnitudeInfo() == Magnitude.FAILED_INDEX);
+ }
+
public void testTestFailed_InSuite() {
mySuite.setStarted();
mySuite.addChild(mySimpleTest);
diff --git a/platform/smRunner/testSrc/com/intellij/execution/testframework/sm/runner/ui/SMTestRunnerResultsFormTest.java b/platform/smRunner/testSrc/com/intellij/execution/testframework/sm/runner/ui/SMTestRunnerResultsFormTest.java
index dc85ce7e2078..ee7e92c93df2 100644
--- a/platform/smRunner/testSrc/com/intellij/execution/testframework/sm/runner/ui/SMTestRunnerResultsFormTest.java
+++ b/platform/smRunner/testSrc/com/intellij/execution/testframework/sm/runner/ui/SMTestRunnerResultsFormTest.java
@@ -231,7 +231,7 @@ public class SMTestRunnerResultsFormTest extends BaseSMTRunnerTestCase {
myEventsProcessor.onTestStarted("test_failed", null);
myResultsViewer.performUpdate();
- myEventsProcessor.onTestFailure("test_failed", "", "", false);
+ myEventsProcessor.onTestFailure("test_failed", "", "", false, null, null);
myResultsViewer.performUpdate();
myEventsProcessor.onTestFinished("test_failed", 10);
myResultsViewer.performUpdate();
@@ -258,7 +258,7 @@ public class SMTestRunnerResultsFormTest extends BaseSMTRunnerTestCase {
myEventsProcessor.onTestStarted("test_failed", null);
myResultsViewer.performUpdate();
- myEventsProcessor.onTestFailure("test_failed", "", "", false);
+ myEventsProcessor.onTestFailure("test_failed", "", "", false, null, null);
myResultsViewer.performUpdate();
myEventsProcessor.onTestFinished("test_failed", 10);
myResultsViewer.performUpdate();
diff --git a/platform/testFramework/src/com/intellij/testFramework/fixtures/impl/CodeInsightTestFixtureImpl.java b/platform/testFramework/src/com/intellij/testFramework/fixtures/impl/CodeInsightTestFixtureImpl.java
index 779e883e6877..1c94c54fcc2a 100644
--- a/platform/testFramework/src/com/intellij/testFramework/fixtures/impl/CodeInsightTestFixtureImpl.java
+++ b/platform/testFramework/src/com/intellij/testFramework/fixtures/impl/CodeInsightTestFixtureImpl.java
@@ -1500,8 +1500,18 @@ public class CodeInsightTestFixtureImpl extends BaseFixture implements CodeInsig
EditorUtil.fillVirtualSpaceUntilCaret(myEditor);
}
PsiDocumentManager.getInstance(getProject()).commitAllDocuments();
+
+ final String fileText = originalFile.getText();
+ final String path = getTestDataPath() + "/" + expectedFile;
+
+ /*final VirtualFile result = LocalFileSystem.getInstance().findFileByPath(path);
+ final int caret = myEditor.getCaretModel().getOffset();
+ final String newText = myFile == originalFile ? fileText.substring(0, caret) + "" + fileText.substring(caret) : fileText;
+ VfsUtil.saveText(result, newText);*/
+
checkResult(expectedFile, stripTrailingSpaces,
- SelectionAndCaretMarkupLoader.fromFile(getTestDataPath() + "/" + expectedFile, getProject()), originalFile.getText());
+ SelectionAndCaretMarkupLoader.fromFile(path, getProject()), fileText);
+
}
private void checkResult(final String expectedFile,
diff --git a/platform/testFramework/src/com/intellij/testFramework/fixtures/impl/LightTempDirTestFixtureImpl.java b/platform/testFramework/src/com/intellij/testFramework/fixtures/impl/LightTempDirTestFixtureImpl.java
index 691f259047c4..ad0934eb4242 100644
--- a/platform/testFramework/src/com/intellij/testFramework/fixtures/impl/LightTempDirTestFixtureImpl.java
+++ b/platform/testFramework/src/com/intellij/testFramework/fixtures/impl/LightTempDirTestFixtureImpl.java
@@ -83,25 +83,12 @@ public class LightTempDirTestFixtureImpl extends BaseFixture implements TempDirT
return ApplicationManager.getApplication().runWriteAction(new Computable() {
@Override
public VirtualFile compute() {
- VirtualFile root = getSourceRoot();
- if (path.length() == 0) return root;
- String trimPath = StringUtil.trimStart(path, "/");
- final List dirs = StringUtil.split(trimPath, "/");
- for (String dirName : dirs) {
- VirtualFile dir = root.findChild(dirName);
- if (dir != null) {
- root = dir;
- }
- else {
- try {
- root = root.createChildDirectory(this, dirName);
- }
- catch (IOException e) {
- throw new RuntimeException(e);
- }
- }
+ try {
+ return findOrCreateChildDir(getSourceRoot(), path);
+ }
+ catch (IOException e) {
+ throw new RuntimeException(e);
}
- return root;
}
});
}
@@ -135,21 +122,32 @@ public class LightTempDirTestFixtureImpl extends BaseFixture implements TempDirT
}
private VirtualFile findOrCreateChildDir(VirtualFile root, String relativePath) throws IOException {
- String thisLevel = relativePath;
- String nextLevel = null;
- final int pos = relativePath.indexOf('/');
- if (pos > 0) {
- thisLevel = relativePath.substring(0, pos);
- nextLevel = relativePath.substring(pos+1);
+ if (relativePath.length() == 0) return root;
+ String trimPath = StringUtil.trimStart(relativePath, "/");
+ final List dirs = StringUtil.split(trimPath, "/");
+ for (String dirName : dirs) {
+ if (dirName.equals(".")) continue;
+
+ if (dirName.equals("..")) {
+ root = root.getParent();
+ if (root == null) throw new IllegalArgumentException("Invalid path: " + relativePath);
+ continue;
+ }
+
+ VirtualFile dir = root.findChild(dirName);
+ if (dir != null) {
+ root = dir;
+ }
+ else {
+ try {
+ root = root.createChildDirectory(this, dirName);
+ }
+ catch (IOException e) {
+ throw new RuntimeException(e);
+ }
+ }
}
- VirtualFile child = root.findChild(thisLevel);
- if (child == null) {
- child = root.createChildDirectory(this, thisLevel);
- }
- if (nextLevel != null && nextLevel.length() > 0) {
- return findOrCreateChildDir(child, nextLevel);
- }
- return child;
+ return root;
}
@Override
diff --git a/platform/testRunner/src/com/intellij/execution/testframework/AbstractTestProxy.java b/platform/testRunner/src/com/intellij/execution/testframework/AbstractTestProxy.java
index 0db0d7ed62f4..3ddc3f1d9821 100644
--- a/platform/testRunner/src/com/intellij/execution/testframework/AbstractTestProxy.java
+++ b/platform/testRunner/src/com/intellij/execution/testframework/AbstractTestProxy.java
@@ -124,5 +124,14 @@ public abstract class AbstractTestProxy extends CompositePrintable {
return myExceptionMark;
}
+ @Nullable
+ public AssertEqualsDiffViewerProvider getDiffViewerProvider() {
+ return null;
+ }
+ public interface AssertEqualsDiffViewerProvider {
+ void openDiff(final Project project);
+ String getExpecteed();
+ String getActual();
+ }
}
diff --git a/platform/testRunner/src/com/intellij/execution/testframework/TestTreeView.java b/platform/testRunner/src/com/intellij/execution/testframework/TestTreeView.java
index c7159cef636a..66b7bb3e4b4a 100644
--- a/platform/testRunner/src/com/intellij/execution/testframework/TestTreeView.java
+++ b/platform/testRunner/src/com/intellij/execution/testframework/TestTreeView.java
@@ -20,6 +20,7 @@
*/
package com.intellij.execution.testframework;
+import com.intellij.execution.testframework.actions.ViewAssertEqualsDiffAction;
import com.intellij.openapi.Disposable;
import com.intellij.openapi.actionSystem.ActionPlaces;
import com.intellij.openapi.actionSystem.DataProvider;
@@ -92,5 +93,6 @@ public abstract class TestTreeView extends Tree implements DataProvider {
});
TreeUtil.installActions(this);
PopupHandler.installPopupHandler(this, IdeActions.GROUP_TESTTREE_POPUP, ActionPlaces.TESTTREE_VIEW_POPUP);
+ ViewAssertEqualsDiffAction.registerShortcut(this);
}
}
\ No newline at end of file
diff --git a/plugins/junit/src/com/intellij/execution/junit2/ui/actions/ViewAssertEqualsDiffAction.java b/platform/testRunner/src/com/intellij/execution/testframework/actions/ViewAssertEqualsDiffAction.java
similarity index 76%
rename from plugins/junit/src/com/intellij/execution/junit2/ui/actions/ViewAssertEqualsDiffAction.java
rename to platform/testRunner/src/com/intellij/execution/testframework/actions/ViewAssertEqualsDiffAction.java
index 56180ec82ab1..9c03a18bdc92 100644
--- a/plugins/junit/src/com/intellij/execution/junit2/ui/actions/ViewAssertEqualsDiffAction.java
+++ b/platform/testRunner/src/com/intellij/execution/testframework/actions/ViewAssertEqualsDiffAction.java
@@ -14,11 +14,8 @@
* limitations under the License.
*/
-package com.intellij.execution.junit2.ui.actions;
+package com.intellij.execution.testframework.actions;
-import com.intellij.execution.junit2.TestProxy;
-import com.intellij.execution.junit2.states.ComparisonFailureState;
-import com.intellij.execution.junit2.states.TestState;
import com.intellij.execution.testframework.AbstractTestProxy;
import com.intellij.openapi.actionSystem.*;
import org.jetbrains.annotations.NonNls;
@@ -31,8 +28,10 @@ public class ViewAssertEqualsDiffAction extends AnAction {
public void actionPerformed(final AnActionEvent e) {
final AbstractTestProxy testProxy = AbstractTestProxy.DATA_KEY.getData(e.getDataContext());
if (testProxy != null) {
- final ComparisonFailureState state = (ComparisonFailureState)((TestProxy)testProxy).getState();
- state.openDiff(PlatformDataKeys.PROJECT.getData(e.getDataContext()));
+ final AbstractTestProxy.AssertEqualsDiffViewerProvider diffViewerProvider = testProxy.getDiffViewerProvider();
+ if (diffViewerProvider != null) {
+ diffViewerProvider.openDiff(PlatformDataKeys.PROJECT.getData(e.getDataContext()));
+ }
}
}
@@ -45,9 +44,8 @@ public class ViewAssertEqualsDiffAction extends AnAction {
}
else {
final AbstractTestProxy test = AbstractTestProxy.DATA_KEY.getData(dataContext);
- if (test instanceof TestProxy) {
- final TestState state = ((TestProxy)test).getState();
- enabled = state instanceof ComparisonFailureState;
+ if (test != null) {
+ enabled = test.getDiffViewerProvider() != null;
}
else {
enabled = false;
diff --git a/platform/util/src/com/intellij/openapi/diagnostic/LogUtil.java b/platform/util/src/com/intellij/openapi/diagnostic/LogUtil.java
new file mode 100644
index 000000000000..adbc69fcff19
--- /dev/null
+++ b/platform/util/src/com/intellij/openapi/diagnostic/LogUtil.java
@@ -0,0 +1,26 @@
+/*
+ * Copyright 2000-2011 JetBrains s.r.o.
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+package com.intellij.openapi.diagnostic;
+
+import org.jetbrains.annotations.Nullable;
+
+public class LogUtil {
+ private LogUtil() { }
+
+ public static String objectAndClass(@Nullable final Object o) {
+ return o != null ? o + " (" + o.getClass().getName() + ")" : "null";
+ }
+}
diff --git a/platform/util/src/com/intellij/util/containers/MultiMap.java b/platform/util/src/com/intellij/util/containers/MultiMap.java
index fb5a7d93e53b..0884bf68c8a3 100644
--- a/platform/util/src/com/intellij/util/containers/MultiMap.java
+++ b/platform/util/src/com/intellij/util/containers/MultiMap.java
@@ -128,9 +128,11 @@ public class MultiMap {
public void removeValue(final K key, final V value) {
final Collection values = myMap.get(key);
- values.remove(value);
- if (values.isEmpty()) {
- myMap.remove(key);
+ if (values != null) {
+ values.remove(value);
+ if (values.isEmpty()) {
+ myMap.remove(key);
+ }
}
}
@@ -206,4 +208,16 @@ public class MultiMap {
public static MultiMap emptyInstance() {
return EMPTY;
}
+
+ @Override
+ public boolean equals(Object o) {
+ if (this == o) return true;
+ if (!(o instanceof MultiMap)) return false;
+ return myMap.equals(((MultiMap)o).myMap);
+ }
+
+ @Override
+ public int hashCode() {
+ return myMap.hashCode();
+ }
}
diff --git a/platform/util/src/com/intellij/util/ui/UIUtil.java b/platform/util/src/com/intellij/util/ui/UIUtil.java
index 403b1089820e..f418d324ce57 100644
--- a/platform/util/src/com/intellij/util/ui/UIUtil.java
+++ b/platform/util/src/com/intellij/util/ui/UIUtil.java
@@ -1778,5 +1778,16 @@ public class UIUtil {
});
}
+ @Nullable
+ public static T findComponentOfType(JComponent parent, Class cls) {
+ if (parent == null || cls.isAssignableFrom(parent.getClass())) return (T)parent;
+ for (Component component : parent.getComponents()) {
+ if (component instanceof JComponent) {
+ T comp = findComponentOfType((JComponent)component, cls);
+ if (comp != null) return comp;
+ }
+ }
+ return null;
+ }
}
diff --git a/platform/vcs-api/src/com/intellij/openapi/vcs/CollectionsMultiplier.java b/platform/vcs-api/src/com/intellij/openapi/vcs/CollectionsMultiplier.java
new file mode 100644
index 000000000000..156fa3ca1200
--- /dev/null
+++ b/platform/vcs-api/src/com/intellij/openapi/vcs/CollectionsMultiplier.java
@@ -0,0 +1,61 @@
+/*
+ * Copyright 2000-2011 JetBrains s.r.o.
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+package com.intellij.openapi.vcs;
+
+import com.intellij.util.Consumer;
+import org.jetbrains.annotations.Nullable;
+
+import java.util.ArrayList;
+import java.util.Collections;
+import java.util.List;
+
+/**
+ * @author irengrig
+ * Date: 2/2/11
+ * Time: 10:11 AM
+ * Cartesian product
+ */
+public class CollectionsMultiplier {
+ private List> myInner;
+
+ public void add(@Nullable final List list) {
+ if (list == null || list.isEmpty()) return;
+ if (myInner == null) {
+ myInner = Collections.singletonList(list);
+ return;
+ }
+ final List> copy = myInner;
+ myInner = new ArrayList>();
+ for (T t : list) {
+ for (List existing : copy) {
+ final ArrayList newList = new ArrayList(existing);
+ newList.add(t);
+ myInner.add(newList);
+ }
+ }
+ }
+
+ public boolean isEmpty() {
+ return myInner == null;
+ }
+
+ public void iterateResult(final Consumer> consumer) {
+ if (myInner == null) return;
+ for (List list : myInner) {
+ consumer.consume(list);
+ }
+ }
+}
diff --git a/platform/vcs-api/src/com/intellij/openapi/vcs/changes/CommitSession.java b/platform/vcs-api/src/com/intellij/openapi/vcs/changes/CommitSession.java
index f294d2b32ec7..e1ac2fd5555a 100644
--- a/platform/vcs-api/src/com/intellij/openapi/vcs/changes/CommitSession.java
+++ b/platform/vcs-api/src/com/intellij/openapi/vcs/changes/CommitSession.java
@@ -43,6 +43,11 @@ public interface CommitSession {
public void executionCanceled() {
}
+
+ @Override
+ public String getHelpId() {
+ return null;
+ }
};
/**
@@ -57,4 +62,10 @@ public interface CommitSession {
boolean canExecute(Collection changes, String commitMessage);
void execute(Collection changes, String commitMessage);
void executionCanceled();
+
+ /**
+ * @return the ID of the help topic to show for the dialog
+ * @since 10.5
+ */
+ String getHelpId();
}
diff --git a/platform/vcs-impl/src/com/intellij/openapi/vcs/changes/patch/CreatePatchCommitExecutor.java b/platform/vcs-impl/src/com/intellij/openapi/vcs/changes/patch/CreatePatchCommitExecutor.java
index 519fa1c6f415..42ac02e16028 100644
--- a/platform/vcs-impl/src/com/intellij/openapi/vcs/changes/patch/CreatePatchCommitExecutor.java
+++ b/platform/vcs-impl/src/com/intellij/openapi/vcs/changes/patch/CreatePatchCommitExecutor.java
@@ -198,5 +198,10 @@ public class CreatePatchCommitExecutor implements CommitExecutorWithHelp, Projec
public void executionCanceled() {
}
+
+ @Override
+ public String getHelpId() {
+ return null;
+ }
}
}
\ No newline at end of file
diff --git a/platform/vcs-impl/src/com/intellij/openapi/vcs/changes/shelf/ShelveChangesCommitExecutor.java b/platform/vcs-impl/src/com/intellij/openapi/vcs/changes/shelf/ShelveChangesCommitExecutor.java
index 22c37a6bcdc1..bfb8a1cce25b 100644
--- a/platform/vcs-impl/src/com/intellij/openapi/vcs/changes/shelf/ShelveChangesCommitExecutor.java
+++ b/platform/vcs-impl/src/com/intellij/openapi/vcs/changes/shelf/ShelveChangesCommitExecutor.java
@@ -112,5 +112,10 @@ public class ShelveChangesCommitExecutor implements CommitExecutorWithHelp {
public void executionCanceled() {
}
+
+ @Override
+ public String getHelpId() {
+ return null;
+ }
}
}
diff --git a/platform/vcs-impl/src/com/intellij/openapi/vcs/changes/ui/CommitChangeListDialog.java b/platform/vcs-impl/src/com/intellij/openapi/vcs/changes/ui/CommitChangeListDialog.java
index b069e48e0f5e..b076b3e4af61 100644
--- a/platform/vcs-impl/src/com/intellij/openapi/vcs/changes/ui/CommitChangeListDialog.java
+++ b/platform/vcs-impl/src/com/intellij/openapi/vcs/changes/ui/CommitChangeListDialog.java
@@ -256,12 +256,14 @@ public class CommitChangeListDialog extends DialogWrapper implements CheckinProj
myLastKnownComment = comment;
myLastSelectedListName = initialSelection == null ? myBrowser.getSelectedChangeList().getName() : initialSelection.getName();
} else {
- setCommitMessage(VcsConfiguration.getInstance(project).LAST_COMMIT_MESSAGE);
updateComment();
- String messageFromVcs = getInitialMessageFromVcs();
- if (messageFromVcs != null) {
- myCommitMessageArea.setText(messageFromVcs);
+ if (StringUtil.isEmptyOrSpaces(myCommitMessageArea.getComment())) {
+ setCommitMessage(VcsConfiguration.getInstance(project).LAST_COMMIT_MESSAGE);
+ final String messageFromVcs = getInitialMessageFromVcs();
+ if (messageFromVcs != null) {
+ myCommitMessageArea.setText(messageFromVcs);
+ }
}
}
diff --git a/platform/vcs-impl/src/com/intellij/openapi/vcs/changes/ui/SessionDialog.java b/platform/vcs-impl/src/com/intellij/openapi/vcs/changes/ui/SessionDialog.java
index 2d25392c59a2..0ff88ea86e3c 100644
--- a/platform/vcs-impl/src/com/intellij/openapi/vcs/changes/ui/SessionDialog.java
+++ b/platform/vcs-impl/src/com/intellij/openapi/vcs/changes/ui/SessionDialog.java
@@ -85,4 +85,14 @@ public class SessionDialog extends DialogWrapper {
super.dispose();
myOKButtonUpdateAlarm.cancelAllRequests();
}
+
+ @Override
+ protected String getHelpId() {
+ try {
+ return mySession.getHelpId();
+ }
+ catch (AbstractMethodError e) {
+ return null;
+ }
+ }
}
diff --git a/platform/vcs-impl/src/com/intellij/openapi/vcs/ui/CommitMessage.java b/platform/vcs-impl/src/com/intellij/openapi/vcs/ui/CommitMessage.java
index a720f87cfbc8..514d17eb4ca0 100644
--- a/platform/vcs-impl/src/com/intellij/openapi/vcs/ui/CommitMessage.java
+++ b/platform/vcs-impl/src/com/intellij/openapi/vcs/ui/CommitMessage.java
@@ -80,10 +80,14 @@ public class CommitMessage extends JPanel implements Disposable {
private static EditorTextField createEditorField(final Project project, final boolean checkSpelling) {
EditorTextFieldProvider service = ServiceManager.getService(project, EditorTextFieldProvider.class);
Set enabledFeatures = EnumSet.of(EditorCustomization.Feature.SOFT_WRAP);
+ Set disabledFeatures = EnumSet.of(EditorCustomization.Feature.ADDITIONAL_PAGE_AT_BOTTOM);
if (checkSpelling) {
enabledFeatures.add(EditorCustomization.Feature.SPELL_CHECK);
}
- Set disabledFeatures = EnumSet.of(EditorCustomization.Feature.ADDITIONAL_PAGE_AT_BOTTOM);
+ else {
+ disabledFeatures.add(EditorCustomization.Feature.SPELL_CHECK);
+ }
+
EditorTextField editorField = service.getEditorField(FileTypes.PLAIN_TEXT.getLanguage(), project, enabledFeatures, disabledFeatures);
editorField.getDocument().putUserData(DATA_CONTEXT_KEY, DataManager.getInstance().getDataContext(editorField.getComponent()));
return editorField;
diff --git a/platform/vcs-impl/src/com/intellij/platform/PlatformVcsDetector.java b/platform/vcs-impl/src/com/intellij/platform/PlatformVcsDetector.java
index 9a27b64efc8d..82604dd6c195 100644
--- a/platform/vcs-impl/src/com/intellij/platform/PlatformVcsDetector.java
+++ b/platform/vcs-impl/src/com/intellij/platform/PlatformVcsDetector.java
@@ -23,6 +23,7 @@ import com.intellij.openapi.vcs.AbstractVcs;
import com.intellij.openapi.vcs.VcsDirectoryMapping;
import com.intellij.openapi.vcs.impl.ProjectLevelVcsManagerImpl;
import com.intellij.openapi.vfs.VirtualFile;
+import com.intellij.ui.AppUIUtil;
import org.jetbrains.annotations.NonNls;
import org.jetbrains.annotations.NotNull;
@@ -41,16 +42,21 @@ public class PlatformVcsDetector implements ProjectComponent {
public void projectOpened() {
StartupManager.getInstance(myProject).runWhenProjectIsInitialized(new DumbAwareRunnable() {
public void run() {
- VirtualFile file = ProjectBaseDirectory.getInstance(myProject).getBaseDir(myProject.getBaseDir());
- if (myVcsManager.needAutodetectMappings()) {
- AbstractVcs vcs = myVcsManager.findVersioningVcs(file);
- if (vcs != null && vcs != myVcsManager.getVcsFor(file)) {
- myVcsManager.removeDirectoryMapping(new VcsDirectoryMapping("", ""));
- myVcsManager.setAutoDirectoryMapping(file.getPath(), vcs.getName());
- myVcsManager.cleanupMappings();
- myVcsManager.updateActiveVcss();
+ AppUIUtil.invokeLaterIfProjectAlive(myProject, new DumbAwareRunnable() {
+ @Override
+ public void run() {
+ VirtualFile file = ProjectBaseDirectory.getInstance(myProject).getBaseDir(myProject.getBaseDir());
+ if (myVcsManager.needAutodetectMappings()) {
+ AbstractVcs vcs = myVcsManager.findVersioningVcs(file);
+ if (vcs != null && vcs != myVcsManager.getVcsFor(file)) {
+ myVcsManager.removeDirectoryMapping(new VcsDirectoryMapping("", ""));
+ myVcsManager.setAutoDirectoryMapping(file.getPath(), vcs.getName());
+ myVcsManager.cleanupMappings();
+ myVcsManager.updateActiveVcss();
+ }
+ }
}
- }
+ });
}
});
}
diff --git a/platform/xdebugger-impl/src/com/intellij/xdebugger/impl/breakpoints/XLineBreakpointImpl.java b/platform/xdebugger-impl/src/com/intellij/xdebugger/impl/breakpoints/XLineBreakpointImpl.java
index b7f931f603d6..7320e895d910 100644
--- a/platform/xdebugger-impl/src/com/intellij/xdebugger/impl/breakpoints/XLineBreakpointImpl.java
+++ b/platform/xdebugger-impl/src/com/intellij/xdebugger/impl/breakpoints/XLineBreakpointImpl.java
@@ -270,8 +270,7 @@ public class XLineBreakpointImpl extends XBreak
}
}
- private boolean canMoveTo(int line) {
- final VirtualFile file = getFile();
+ private boolean canMoveTo(int line, VirtualFile file) {
return file != null && myType.canPutAt(file, line, getProject());
}
@@ -389,11 +388,9 @@ public class XLineBreakpointImpl
extends XBreak
@Override
public GutterDraggableObject getDraggableObject() {
return new GutterDraggableObject() {
- public void removeSelf() {
- }
-
- public boolean copy(int line) {
- if (canMoveTo(line)) {
+ public boolean copy(int line, VirtualFile file) {
+ if (canMoveTo(line, file)) {
+ setFileUrl(file.getUrl());
setLine(line);
return true;
}
@@ -401,7 +398,7 @@ public class XLineBreakpointImpl
extends XBreak
}
public Cursor getCursor(int line) {
- return canMoveTo(line) ? DragSource.DefaultMoveDrop : DragSource.DefaultMoveNoDrop;
+ return canMoveTo(line, getFile()) ? DragSource.DefaultMoveDrop : DragSource.DefaultMoveNoDrop;
}
};
}
diff --git a/plugins/android/resources/fileTemplates/j2ee/Application.java.ft b/plugins/android/resources/fileTemplates/j2ee/Application.java.ft
new file mode 100644
index 000000000000..336051a028f2
--- /dev/null
+++ b/plugins/android/resources/fileTemplates/j2ee/Application.java.ft
@@ -0,0 +1,7 @@
+package ${PACKAGE_NAME};
+
+import android.app.Application;
+
+#parse("File Header.java")
+public class ${NAME} extends Application {
+}
diff --git a/plugins/android/resources/fileTemplates/j2ee/Application.java.html b/plugins/android/resources/fileTemplates/j2ee/Application.java.html
new file mode 100644
index 000000000000..09a7bfbff9e3
--- /dev/null
+++ b/plugins/android/resources/fileTemplates/j2ee/Application.java.html
@@ -0,0 +1,5 @@
+
+
+This is a built-in file template used to create custom Application class in Android applications.
+
+
\ No newline at end of file
diff --git a/plugins/android/resources/messages/AndroidBundle.properties b/plugins/android/resources/messages/AndroidBundle.properties
index e98186580071..6a224277a061 100644
--- a/plugins/android/resources/messages/AndroidBundle.properties
+++ b/plugins/android/resources/messages/AndroidBundle.properties
@@ -231,4 +231,5 @@ android.compilation.error.apt.gen.not.specified=AAPT destination directory not s
android.compilation.error.aidl.gen.not.specified=AIDL destination directory not specified for module {0}
android.compilation.error.apk.path.not.specified=Final APK path not specified for module {0}
android.restart.logcat.action.text=Restart
-android.restart.logcat.action.description=Restart logging
\ No newline at end of file
+android.restart.logcat.action.description=Restart logging
+android.new.component.dialog.application.item=Application
\ No newline at end of file
diff --git a/plugins/android/src/org/jetbrains/android/AndroidFileTemplateProvider.java b/plugins/android/src/org/jetbrains/android/AndroidFileTemplateProvider.java
index 660aa42babc8..b35681b54376 100644
--- a/plugins/android/src/org/jetbrains/android/AndroidFileTemplateProvider.java
+++ b/plugins/android/src/org/jetbrains/android/AndroidFileTemplateProvider.java
@@ -42,6 +42,7 @@ public class AndroidFileTemplateProvider implements FileTemplateGroupDescriptorF
@NonNls public static final String RESOURCE_FILE_TEMPLATE = "resourceFile.xml";
@NonNls public static final String LAYOUT_RESOURCE_FILE_TEMPLATE = "layoutResourceFile.xml";
@NonNls public static final String ACTIVITY = "Activity.java";
+ @NonNls public static final String APPLICATION = "Application.java";
@NonNls public static final String SERVICE = "Service.java";
@NonNls public static final String BROADCAST_RECEIVER = "Broadcast Receiver.java";
@@ -52,6 +53,7 @@ public class AndroidFileTemplateProvider implements FileTemplateGroupDescriptorF
group.addTemplate(new FileTemplateDescriptor(RESOURCE_FILE_TEMPLATE, StdFileTypes.XML.getIcon()));
group.addTemplate(new FileTemplateDescriptor(LAYOUT_RESOURCE_FILE_TEMPLATE, StdFileTypes.XML.getIcon()));
group.addTemplate(new FileTemplateDescriptor(ACTIVITY, StdFileTypes.JAVA.getIcon()));
+ group.addTemplate(new FileTemplateDescriptor(APPLICATION, StdFileTypes.JAVA.getIcon()));
group.addTemplate(new FileTemplateDescriptor(SERVICE, StdFileTypes.JAVA.getIcon()));
group.addTemplate(new FileTemplateDescriptor(BROADCAST_RECEIVER, StdFileTypes.JAVA.getIcon()));
group.addTemplate(new FileTemplateDescriptor(REMOTE_INTERFACE_TEMPLATE, AndroidIdlFileType.ourFileType.getIcon()));
diff --git a/plugins/android/src/org/jetbrains/android/actions/NewAndroidComponentAction.java b/plugins/android/src/org/jetbrains/android/actions/NewAndroidComponentAction.java
index a09b41c039f4..bba3e11c914e 100644
--- a/plugins/android/src/org/jetbrains/android/actions/NewAndroidComponentAction.java
+++ b/plugins/android/src/org/jetbrains/android/actions/NewAndroidComponentAction.java
@@ -18,7 +18,6 @@ package org.jetbrains.android.actions;
import com.intellij.ide.IdeView;
import com.intellij.openapi.actionSystem.*;
import com.intellij.openapi.module.Module;
-import com.intellij.openapi.project.Project;
import com.intellij.openapi.ui.DialogWrapper;
import com.intellij.psi.JavaDirectoryService;
import com.intellij.psi.PsiDirectory;
@@ -64,12 +63,14 @@ public class NewAndroidComponentAction extends AnAction {
return;
}
- final Project project = PlatformDataKeys.PROJECT.getData(dataContext);
+ final Module module = LangDataKeys.MODULE.getData(dataContext);
+
+ if (module == null) return;
final PsiDirectory dir = view.getOrChooseDirectory();
if (dir == null) return;
- NewAndroidComponentDialog dialog = new NewAndroidComponentDialog(project, dir);
+ NewAndroidComponentDialog dialog = new NewAndroidComponentDialog(module, dir);
dialog.show();
if (dialog.getExitCode() != DialogWrapper.OK_EXIT_CODE) {
return;
diff --git a/plugins/android/src/org/jetbrains/android/actions/NewAndroidComponentDialog.java b/plugins/android/src/org/jetbrains/android/actions/NewAndroidComponentDialog.java
index 9e9ff9cf8e7d..aa3cbd09b151 100644
--- a/plugins/android/src/org/jetbrains/android/actions/NewAndroidComponentDialog.java
+++ b/plugins/android/src/org/jetbrains/android/actions/NewAndroidComponentDialog.java
@@ -18,16 +18,19 @@ package org.jetbrains.android.actions;
import com.intellij.CommonBundle;
import com.intellij.ide.actions.ElementCreator;
import com.intellij.ide.actions.TemplateKindCombo;
+import com.intellij.openapi.application.ApplicationManager;
import com.intellij.openapi.module.Module;
import com.intellij.openapi.module.ModuleUtil;
import com.intellij.openapi.project.Project;
import com.intellij.openapi.ui.DialogWrapper;
+import com.intellij.openapi.util.Computable;
import com.intellij.psi.*;
+import com.intellij.psi.search.searches.ClassInheritorsSearch;
import com.intellij.util.Icons;
import com.intellij.util.IncorrectOperationException;
import org.jetbrains.android.AndroidFileTemplateProvider;
-import org.jetbrains.android.dom.manifest.*;
import org.jetbrains.android.dom.manifest.Action;
+import org.jetbrains.android.dom.manifest.*;
import org.jetbrains.android.dom.resources.ResourceValue;
import org.jetbrains.android.facet.AndroidFacet;
import org.jetbrains.android.util.AndroidBundle;
@@ -55,12 +58,18 @@ public class NewAndroidComponentDialog extends DialogWrapper {
private PsiElement[] myCreatedElements;
- protected NewAndroidComponentDialog(final Project project, final PsiDirectory directory) {
- super(project);
+ protected NewAndroidComponentDialog(@NotNull final Module module, final PsiDirectory directory) {
+ super(module.getProject());
myKindLabel.setLabelFor(myKindCombo);
myKindCombo.registerUpDownHint(myNameField);
myUpDownHint.setIcon(Icons.UP_DOWN_ARROWS);
myKindCombo.addItem(AndroidBundle.message("android.new.component.dialog.activity.item"), null, AndroidFileTemplateProvider.ACTIVITY);
+
+ if (!containsCustomApplicationClass(module)) {
+ myKindCombo.addItem(AndroidBundle.message("android.new.component.dialog.application.item"), null,
+ AndroidFileTemplateProvider.APPLICATION);
+ }
+
myKindCombo.addItem(AndroidBundle.message("android.new.component.dialog.service.item"), null, AndroidFileTemplateProvider.SERVICE);
myKindCombo.addItem(AndroidBundle.message("android.new.component.dialog.broadcast.receiver.item"), null,
AndroidFileTemplateProvider.BROADCAST_RECEIVER);
@@ -68,7 +77,7 @@ public class NewAndroidComponentDialog extends DialogWrapper {
AndroidFileTemplateProvider.REMOTE_INTERFACE_TEMPLATE);
init();
setTitle(AndroidBundle.message("android.new.component.action.command.name"));
- myCreator = new ElementCreator(project, CommonBundle.getErrorTitle()) {
+ myCreator = new ElementCreator(module.getProject(), CommonBundle.getErrorTitle()) {
@Override
protected void checkBeforeCreate(String newName) throws IncorrectOperationException {
JavaDirectoryService.getInstance().checkCreateClass(directory, newName);
@@ -76,7 +85,7 @@ public class NewAndroidComponentDialog extends DialogWrapper {
@Override
protected PsiElement[] create(String newName) throws Exception {
- final PsiElement element = NewAndroidComponentDialog.this.create(newName, directory, project);
+ final PsiElement element = NewAndroidComponentDialog.this.create(newName, directory, module.getProject());
if (element != null) {
return new PsiElement[]{element};
}
@@ -93,11 +102,23 @@ public class NewAndroidComponentDialog extends DialogWrapper {
public void actionPerformed(ActionEvent e) {
String selected = myKindCombo.getSelectedName();
myMarkAsStartupActivityCheckBox.setEnabled(AndroidFileTemplateProvider.ACTIVITY.equals(selected));
- myLabelField.setEnabled(!AndroidFileTemplateProvider.REMOTE_INTERFACE_TEMPLATE.equals(selected));
+ myLabelField.setEnabled(!AndroidFileTemplateProvider.REMOTE_INTERFACE_TEMPLATE.equals(selected) &&
+ !AndroidFileTemplateProvider.APPLICATION.equals(selected));
}
});
}
+ private static boolean containsCustomApplicationClass(@NotNull final Module module) {
+ final JavaPsiFacade facade = JavaPsiFacade.getInstance(module.getProject());
+ PsiClass applicationClass = ApplicationManager.getApplication().runReadAction(new Computable() {
+ @Nullable
+ public PsiClass compute() {
+ return facade.findClass(AndroidUtils.APPLICATION_CLASS_NAME, module.getModuleWithDependenciesAndLibrariesScope(false));
+ }
+ });
+ return applicationClass != null && ClassInheritorsSearch.search(applicationClass, module.getModuleScope(), true).findFirst() != null;
+ }
+
@Nullable
private PsiElement create(String newName, PsiDirectory directory, Project project) throws Exception {
return doCreate(myKindCombo.getSelectedName(), directory, project, newName, myLabelField.getText(),
@@ -175,6 +196,9 @@ public class NewAndroidComponentDialog extends DialogWrapper {
receiver.getReceiverClass().setValue(aClass);
return receiver;
}
+ else if (AndroidFileTemplateProvider.APPLICATION.equals(templateName)) {
+ application.getName().setValue(aClass);
+ }
return null;
}
diff --git a/plugins/android/src/org/jetbrains/android/facet/AndroidFacetConfiguration.java b/plugins/android/src/org/jetbrains/android/facet/AndroidFacetConfiguration.java
index 5c5369ad61a4..25ba1e9fb203 100644
--- a/plugins/android/src/org/jetbrains/android/facet/AndroidFacetConfiguration.java
+++ b/plugins/android/src/org/jetbrains/android/facet/AndroidFacetConfiguration.java
@@ -77,15 +77,19 @@ public class AndroidFacetConfiguration implements FacetConfiguration {
private AndroidFacet myFacet = null;
public void init(@NotNull Module module, @NotNull VirtualFile contentRoot) {
+ init(module, contentRoot.getPath());
+ }
+
+ public void init(@NotNull Module module, @NotNull String baseDirectoryPath) {
String moduleDirPath = AndroidRootUtil.getModuleDirPath(module);
if (moduleDirPath == null) {
return;
}
- if (moduleDirPath.equals(contentRoot.getPath())) {
+ if (moduleDirPath.equals(baseDirectoryPath)) {
return;
}
- String s = FileUtil.getRelativePath(moduleDirPath, contentRoot.getPath(), '/');
+ String s = FileUtil.getRelativePath(moduleDirPath, baseDirectoryPath, '/');
GEN_FOLDER_RELATIVE_PATH_APT = '/' + s + GEN_FOLDER_RELATIVE_PATH_APT;
GEN_FOLDER_RELATIVE_PATH_AIDL = '/' + s + GEN_FOLDER_RELATIVE_PATH_AIDL;
diff --git a/plugins/android/src/org/jetbrains/android/facet/AndroidFacetEditorTab.java b/plugins/android/src/org/jetbrains/android/facet/AndroidFacetEditorTab.java
index 5afed5173670..99ef1974899a 100644
--- a/plugins/android/src/org/jetbrains/android/facet/AndroidFacetEditorTab.java
+++ b/plugins/android/src/org/jetbrains/android/facet/AndroidFacetEditorTab.java
@@ -171,6 +171,10 @@ public class AndroidFacetEditorTab extends FacetEditorTab {
public void actionPerformed(ActionEvent e) {
AndroidFacetConfiguration configuration = new AndroidFacetConfiguration();
Module module = myContext.getModule();
+ VirtualFile[] contentRoots = ModuleRootManager.getInstance(module).getContentRoots();
+ if (contentRoots.length == 1) {
+ configuration.init(module, contentRoots[0]);
+ }
if (AndroidMavenUtil.isMavenizedModule(module)) {
AndroidMavenProvider mavenProvider = AndroidMavenUtil.getMavenProvider();
if (mavenProvider != null) {
diff --git a/plugins/android/src/org/jetbrains/android/maven/AndroidFacetImporter.java b/plugins/android/src/org/jetbrains/android/maven/AndroidFacetImporter.java
index 8149f074ff51..9e9b93a75adc 100644
--- a/plugins/android/src/org/jetbrains/android/maven/AndroidFacetImporter.java
+++ b/plugins/android/src/org/jetbrains/android/maven/AndroidFacetImporter.java
@@ -76,6 +76,8 @@ public class AndroidFacetImporter extends FacetImporter> loadStashStackAsCommits(@NotNull Project project, @NotNull VirtualFile root,
+ SymbolicRefs refs, final String... parameters) throws VcsException {
+ GitSimpleHandler h = new GitSimpleHandler(project, root, GitCommand.STASH);
+ GitLogParser parser = new GitLogParser(SHORT_HASH, HASH, COMMIT_TIME, AUTHOR_NAME, AUTHOR_TIME, AUTHOR_EMAIL, COMMITTER_NAME, COMMITTER_EMAIL, SHORT_PARENTS, REF_NAMES, SHORT_REF_LOG_SELECTOR, SUBJECT, BODY);
+ h.setSilent(true);
+ h.setNoSSH(true);
+ h.addParameters("list");
+ h.addParameters(parameters);
+ h.addParameters(parser.getPretty());
+ parser.parseStatusBeforeName(true);
+
+ String out;
+ try {
+ h.setCharset(Charset.forName(GitConfigUtil.getLogEncoding(project, root)));
+ out = h.run();
+ }
+ catch (VcsException e) {
+ GitUIUtil.showOperationError(project, e, h.printableCommandLine());
+ return null;
+ }
+ final List gitLogRecords = parser.parse(out);
+ final List> result = new ArrayList>();
+ for (GitLogRecord gitLogRecord : gitLogRecords) {
+ final GitCommit gitCommit = createCommit(project, refs, root, gitLogRecord);
+ result.add(new Pair(gitLogRecord.getShortenedRefLog(), gitCommit));
+ }
+ return result;
+ }
+
public static List commitsDetails(Project project,
FilePath path, SymbolicRefs refs,
final Collection commitsIds) throws VcsException {
diff --git a/plugins/git4idea/src/git4idea/history/GitLogParser.java b/plugins/git4idea/src/git4idea/history/GitLogParser.java
index 07f9c4e23bea..1903b62315cb 100644
--- a/plugins/git4idea/src/git4idea/history/GitLogParser.java
+++ b/plugins/git4idea/src/git4idea/history/GitLogParser.java
@@ -15,22 +15,9 @@
*/
package git4idea.history;
-import com.intellij.openapi.project.Project;
-import com.intellij.openapi.util.Pair;
import com.intellij.openapi.util.text.StringUtil;
-import com.intellij.openapi.vcs.FilePath;
-import com.intellij.openapi.vcs.FileStatus;
-import com.intellij.openapi.vcs.VcsException;
-import com.intellij.openapi.vcs.changes.Change;
-import com.intellij.openapi.vcs.changes.ContentRevision;
-import com.intellij.openapi.vfs.VirtualFile;
import com.intellij.util.Function;
-import com.intellij.util.containers.Convertor;
-import git4idea.GitContentRevision;
-import git4idea.GitRevisionNumber;
-import git4idea.history.wholeTree.AbstractHash;
-import java.io.File;
import java.util.*;
/**
@@ -80,8 +67,8 @@ class GitLogParser {
* These are the pieces of information about a commit which we want to get from 'git log'.
*/
enum GitLogOption {
- SHORT_HASH("h"), HASH("H"), COMMIT_TIME("ct"), AUTHOR_NAME("an"), AUTHOR_TIME("at"), AUTHOR_EMAIL("ae"), COMMITTER_NAME("cn"), COMMITTER_EMAIL("ce"), SUBJECT("s"), BODY("b"),
- SHORT_PARENTS("p"), PARENTS("P"), REF_NAMES("d");
+ SHORT_HASH("h"), HASH("H"), COMMIT_TIME("ct"), AUTHOR_NAME("an"), AUTHOR_TIME("at"), AUTHOR_EMAIL("ae"), COMMITTER_NAME("cn"),
+ COMMITTER_EMAIL("ce"), SUBJECT("s"), BODY("b"), SHORT_PARENTS("p"), PARENTS("P"), REF_NAMES("d"), SHORT_REF_LOG_SELECTOR("gd");
private String myPlaceholder;
private GitLogOption(String placeholder) { myPlaceholder = placeholder; }
diff --git a/plugins/git4idea/src/git4idea/history/GitLogRecord.java b/plugins/git4idea/src/git4idea/history/GitLogRecord.java
index 143d7221f3e8..fc2a93d79710 100644
--- a/plugins/git4idea/src/git4idea/history/GitLogRecord.java
+++ b/plugins/git4idea/src/git4idea/history/GitLogRecord.java
@@ -31,12 +31,7 @@ import git4idea.GitUtil;
import git4idea.history.wholeTree.AbstractHash;
import org.jetbrains.annotations.NotNull;
-import java.util.ArrayList;
-import java.util.Arrays;
-import java.util.Collection;
-import java.util.Date;
-import java.util.List;
-import java.util.Map;
+import java.util.*;
import static git4idea.history.GitLogParser.GitLogOption.*;
@@ -90,6 +85,7 @@ class GitLogRecord {
String getCommitterEmail() { return lookup(COMMITTER_EMAIL); }
String getSubject() { return lookup(SUBJECT); }
String getBody() { return lookup(BODY); }
+ String getShortenedRefLog() { return lookup(SHORT_REF_LOG_SELECTOR); }
// access methods with some formatting or conversion
diff --git a/plugins/git4idea/src/git4idea/history/browser/ChangesFilter.java b/plugins/git4idea/src/git4idea/history/browser/ChangesFilter.java
index 7eab34c11434..c785612ec32c 100644
--- a/plugins/git4idea/src/git4idea/history/browser/ChangesFilter.java
+++ b/plugins/git4idea/src/git4idea/history/browser/ChangesFilter.java
@@ -21,6 +21,7 @@ import com.intellij.openapi.vcs.FilePath;
import com.intellij.openapi.vcs.changes.FilePathsHelper;
import com.intellij.openapi.vfs.VfsUtil;
import com.intellij.openapi.vfs.VirtualFile;
+import com.intellij.util.ArrayUtil;
import com.intellij.util.PairProcessor;
import git4idea.GitUtil;
import org.jetbrains.annotations.NotNull;
@@ -31,6 +32,21 @@ import java.util.regex.Pattern;
public class ChangesFilter {
+ public static void filtersToParameters(Collection filters, List parameters) {
+ for (Filter filter : filters) {
+ filter.getCommandParametersFilter().applyToCommandLine(parameters);
+ }
+ }
+
+ public static String[] filtersToParameterArray(Collection filters) {
+ if (filters == null || filters.isEmpty()) return ArrayUtil.EMPTY_STRING_ARRAY;
+ final ArrayList strings = new ArrayList();
+ for (Filter filter : filters) {
+ filter.getCommandParametersFilter().applyToCommandLine(strings);
+ }
+ return strings.toArray(new String[strings.size()]);
+ }
+
public abstract static class Merger {
private final Collection myFilters;
private MemoryFilter myResult;
diff --git a/plugins/git4idea/src/git4idea/history/browser/GitCommit.java b/plugins/git4idea/src/git4idea/history/browser/GitCommit.java
index 62ae1432f672..71f2af4485c7 100644
--- a/plugins/git4idea/src/git4idea/history/browser/GitCommit.java
+++ b/plugins/git4idea/src/git4idea/history/browser/GitCommit.java
@@ -16,7 +16,9 @@
package git4idea.history.browser;
import com.intellij.openapi.vcs.FilePath;
+import com.intellij.openapi.vcs.ObjectsConvertor;
import com.intellij.openapi.vcs.changes.Change;
+import com.intellij.util.containers.Convertor;
import git4idea.history.wholeTree.AbstractHash;
import org.jetbrains.annotations.NotNull;
@@ -212,4 +214,13 @@ public class GitCommit {
public void setOnTracked(boolean onTracked) {
myOnTracked = onTracked;
}
+
+ public List getConvertedParents() {
+ return ObjectsConvertor.convert(getParentsHashes(), new Convertor() {
+ @Override
+ public AbstractHash convert(String o) {
+ return AbstractHash.create(o);
+ }
+ });
+ }
}
diff --git a/plugins/git4idea/src/git4idea/history/browser/LowLevelAccessImpl.java b/plugins/git4idea/src/git4idea/history/browser/LowLevelAccessImpl.java
index 9db1e22fe7be..ffd72352ba15 100644
--- a/plugins/git4idea/src/git4idea/history/browser/LowLevelAccessImpl.java
+++ b/plugins/git4idea/src/git4idea/history/browser/LowLevelAccessImpl.java
@@ -54,9 +54,7 @@ public class LowLevelAccessImpl implements LowLevelAccess {
final AsynchConsumer consumer,
Getter isCanceled, int useMaxCnt) throws VcsException {
final List parameters = new ArrayList();
- for (ChangesFilter.Filter filter : filters) {
- filter.getCommandParametersFilter().applyToCommandLine(parameters);
- }
+ ChangesFilter.filtersToParameters(filters, parameters);
if (! startingPoints.isEmpty()) {
for (String startingPoint : startingPoints) {
@@ -110,6 +108,13 @@ public class LowLevelAccessImpl implements LowLevelAccess {
refs.setTrackedRemote(current.getTrackedRemoteName(myProject, myRoot));
}
refs.setUsername(GitConfigUtil.getValue(myProject, myRoot, GitConfigUtil.USER_NAME));
+ // todo
+ /*GitStashUtils.loadStashStack(myProject, myRoot, new Consumer() {
+ @Override
+ public void consume(StashInfo stashInfo) {
+
+ }
+ });*/
return refs;
}
@@ -125,10 +130,8 @@ public class LowLevelAccessImpl implements LowLevelAccess {
parameters.add("--max-count=" + useMaxCnt);
}
- for (ChangesFilter.Filter filter : filters) {
- filter.getCommandParametersFilter().applyToCommandLine(parameters);
- }
-
+ ChangesFilter.filtersToParameters(filters, parameters);
+
if (! startingPoints.isEmpty()) {
for (String startingPoint : startingPoints) {
parameters.add(startingPoint);
diff --git a/plugins/git4idea/src/git4idea/history/wholeTree/ByRootLoader.java b/plugins/git4idea/src/git4idea/history/wholeTree/ByRootLoader.java
new file mode 100644
index 000000000000..be33f969f000
--- /dev/null
+++ b/plugins/git4idea/src/git4idea/history/wholeTree/ByRootLoader.java
@@ -0,0 +1,207 @@
+/*
+ * Copyright 2000-2011 JetBrains s.r.o.
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+package git4idea.history.wholeTree;
+
+import com.intellij.openapi.progress.ProgressIndicator;
+import com.intellij.openapi.progress.ProgressManager;
+import com.intellij.openapi.project.Project;
+import com.intellij.openapi.util.Pair;
+import com.intellij.openapi.vcs.VcsException;
+import com.intellij.util.Consumer;
+import com.intellij.util.continuation.ContinuationContext;
+import com.intellij.util.continuation.TaskDescriptor;
+import com.intellij.util.continuation.Where;
+import git4idea.changes.GitChangeUtils;
+import git4idea.history.GitHistoryUtils;
+import git4idea.history.browser.*;
+import org.jetbrains.annotations.NotNull;
+
+import java.util.*;
+
+/**
+ * @author irengrig
+ * Date: 2/1/11
+ * Time: 6:30 PM
+ *
+ * We wouldn't include it into growth controller (not many rows loaded)
+ */
+public class ByRootLoader extends TaskDescriptor {
+ private final Project myProject;
+ private final LoaderAndRefresherImpl.MyRootHolder myRootHolder;
+ private final LowLevelAccess myLowLevelAccess;
+ private final Mediator myMediator;
+ private final DetailsCache myDetailsCache;
+ private SymbolicRefs mySymbolicRefs;
+ private final Mediator.Ticket myTicket;
+ private final UsersIndex myUsersIndex;
+ private final Collection myStartingPoints;
+ @NotNull
+ private final GitLogFilters myGitLogFilters;
+
+ public ByRootLoader(Project project,
+ LoaderAndRefresherImpl.MyRootHolder rootHolder,
+ Mediator mediator,
+ DetailsCache detailsCache,
+ Mediator.Ticket ticket, UsersIndex usersIndex, GitLogFilters gitLogFilters, final Collection startingPoints) {
+ super("Initial checks", Where.POOLED);
+ myProject = project;
+ myRootHolder = rootHolder;
+ myUsersIndex = usersIndex;
+ myStartingPoints = startingPoints;
+ myLowLevelAccess = new LowLevelAccessImpl(myProject, myRootHolder.getRoot());
+ myMediator = mediator;
+ myDetailsCache = detailsCache;
+ myTicket = ticket;
+ myGitLogFilters = gitLogFilters;
+ }
+
+ @Override
+ public void run(ContinuationContext context) {
+ final ProgressIndicator pi = ProgressManager.getInstance().getProgressIndicator();
+ progress(pi, "Load branches and tags");
+ initSymbRefs();
+ progress(pi, "Load stashed");
+ loadStash();
+ progress(pi, "Try to load by reference");
+ loadByHashesAside(context);
+ }
+
+ private void progress(final ProgressIndicator pi, final String progress) {
+ if (pi != null) {
+ pi.checkCanceled();
+ pi.setText(progress);
+ }
+ }
+
+ private void loadStash() {
+ // start is not on a branch
+ if (myStartingPoints != null && (! myStartingPoints.isEmpty())) return;
+
+ final List details = new ArrayList();
+ final List commits = new ArrayList();
+ final Map stashMap = new HashMap();
+ final List> parents = myGitLogFilters.isEmpty() ? new ArrayList>() : null;
+
+ myGitLogFilters.callConsumer(new Consumer>() {
+ @Override
+ public void consume(List filters) {
+ try {
+ final List> stash = GitHistoryUtils.loadStashStackAsCommits(myProject, myRootHolder.getRoot(),
+ mySymbolicRefs, ChangesFilter.filtersToParameterArray(filters));
+ if (stash == null) return;
+ for (Pair pair : stash) {
+ final GitCommit gitCommit = pair.getSecond();
+ if (stashMap.containsKey(gitCommit.getShortHash())) continue;
+
+ details.add(gitCommit);
+ if (parents != null) {
+ parents.add(gitCommit.getConvertedParents());
+ }
+ commits.add(createCommitI(gitCommit));
+ stashMap.put(gitCommit.getShortHash(), pair.getFirst());
+ }
+ }
+ catch (VcsException e) {
+ myMediator.acceptException(e);
+ }
+ }
+ }, true);
+
+ myDetailsCache.putStash(myRootHolder.getRoot(), stashMap);
+ // does not work
+ //myDetailsCache.acceptAnswer(details, myRootHolder.getRoot());
+ myMediator.appendResult(myTicket, commits, parents);
+ }
+
+ // if there're filters -> parents shouldn't be loaded
+ public void loadByHashesAside(final ContinuationContext context) {
+ final List result = new ArrayList();
+ final Set controlSet = new HashSet();
+
+ final List hashes = myGitLogFilters.getPossibleReferencies();
+ if (hashes == null) return;
+ myGitLogFilters.callConsumer(new Consumer>() {
+ @Override
+ public void consume(List filters) {
+ for (String hash : hashes) {
+ try {
+ final SHAHash shaHash = GitChangeUtils.commitExists(myProject, myRootHolder.getRoot(), hash, ChangesFilter.filtersToParameterArray(filters));
+ if (shaHash == null) continue;
+ if (controlSet.contains(shaHash)) continue;
+ controlSet.add(shaHash);
+
+ if (myStartingPoints != null && (! myStartingPoints.isEmpty())) {
+ boolean matches = false;
+ for (String startingPoint : myStartingPoints) {
+ if(GitChangeUtils.isAnyLevelChild(myProject, myRootHolder.getRoot(), shaHash, startingPoint)) {
+ matches = true;
+ break;
+ }
+ }
+ if (! matches) continue;
+ }
+ final List commits = myLowLevelAccess.getCommitDetails(Collections.singletonList(shaHash.getValue()), mySymbolicRefs);
+ if (commits.isEmpty()) continue;
+
+ myDetailsCache.acceptAnswer(commits, myRootHolder.getRoot());
+ appendCommits(result, commits);
+ }
+ catch (VcsException e1) {
+ continue;
+ }
+ }
+ }
+ }, false);
+
+ if (! result.isEmpty()) {
+ final StepType stepType = myMediator.appendResult(myTicket, result, null);
+ // here we react only on "stop", not on "pause"
+ if (StepType.STOP.equals(stepType)) {
+ context.cancelEverything();
+ }
+ }
+ }
+
+ private void appendCommits(List result, List commits) {
+ for (GitCommit commit : commits) {
+ CommitI commitObj = createCommitI(commit);
+ result.add(commitObj);
+ }
+ }
+
+ private CommitI createCommitI(GitCommit commit) {
+ CommitI commitObj =
+ new Commit(commit.getShortHash().getString(), commit.getDate().getTime(), myUsersIndex.put(commit.getAuthor()));
+ commitObj = myRootHolder.decorateByRoot(commitObj);
+ return commitObj;
+ }
+
+ private void initSymbRefs() {
+ if (mySymbolicRefs == null) {
+ try {
+ mySymbolicRefs = myLowLevelAccess.getRefs();
+ myMediator.reportSymbolicRefs(myTicket, myRootHolder.getRoot(), mySymbolicRefs);
+ }
+ catch (VcsException e) {
+ myMediator.acceptException(e);
+ }
+ }
+ }
+
+ public SymbolicRefs getSymbolicRefs() {
+ return mySymbolicRefs;
+ }
+}
diff --git a/plugins/git4idea/src/git4idea/history/wholeTree/DetailsCache.java b/plugins/git4idea/src/git4idea/history/wholeTree/DetailsCache.java
index 0d5c30e68302..cea830af3525 100644
--- a/plugins/git4idea/src/git4idea/history/wholeTree/DetailsCache.java
+++ b/plugins/git4idea/src/git4idea/history/wholeTree/DetailsCache.java
@@ -20,26 +20,30 @@ import com.intellij.openapi.vfs.VirtualFile;
import com.intellij.util.containers.MultiMap;
import com.intellij.util.containers.SLRUMap;
import git4idea.history.browser.GitCommit;
+import org.jetbrains.annotations.Nullable;
import java.util.Collection;
+import java.util.HashMap;
import java.util.List;
+import java.util.Map;
/**
* @author irengrig
*/
public class DetailsCache {
private final static int ourSize = 400;
- private boolean mySomethingIsMissing;
private final SLRUMap, GitCommit> myCache;
private final SLRUMap, List> myBranches;
private final DetailsLoaderImpl myDetailsLoader;
private final ModalityState myModalityState;
private AbstractCalledLater myRefresh;
+ private final Map> myStash;
private final Object myLock;
public DetailsCache(final Project project, final UIRefresh uiRefresh, final DetailsLoaderImpl detailsLoader, final ModalityState modalityState) {
myDetailsLoader = detailsLoader;
myModalityState = modalityState;
+ myStash = new HashMap>();
myRefresh = new AbstractCalledLater(project, myModalityState) {
@Override
public void run() {
@@ -47,7 +51,6 @@ public class DetailsCache {
}
};
myLock = new Object();
- mySomethingIsMissing = false;
myCache = new SLRUMap, GitCommit>(ourSize, 50);
myBranches = new SLRUMap, List>(10, 10);
}
@@ -60,9 +63,6 @@ public class DetailsCache {
public void acceptQuestion(final MultiMap hashes) {
if (hashes.isEmpty()) return;
- synchronized (myLock) {
- mySomethingIsMissing = ! hashes.isEmpty();
- }
myDetailsLoader.load(hashes);
}
@@ -71,9 +71,6 @@ public class DetailsCache {
for (GitCommit commit : commits) {
myCache.put(new Pair(root, commit.getShortHash()), commit);
}
-// if (mySomethingIsMissing) {
- mySomethingIsMissing = false;
-// }
}
myRefresh.callMe();
}
@@ -94,9 +91,25 @@ public class DetailsCache {
}
}
- public void resetBranchesCache() {
+ public void resetAsideCaches() {
synchronized (myLock) {
myBranches.clear();
+ myStash.clear();
+ myCache.clear();
+ }
+ }
+
+ public void putStash(final VirtualFile root, final Map stash) {
+ synchronized (myLock) {
+ myStash.put(root, stash);
+ }
+ }
+
+ @Nullable
+ public String getStashName(final VirtualFile root, final AbstractHash hash) {
+ synchronized (myLock) {
+ final Map map = myStash.get(root);
+ return map == null ? null : map.get(hash);
}
}
}
diff --git a/plugins/git4idea/src/git4idea/history/wholeTree/GitLogFilters.java b/plugins/git4idea/src/git4idea/history/wholeTree/GitLogFilters.java
new file mode 100644
index 000000000000..639386002470
--- /dev/null
+++ b/plugins/git4idea/src/git4idea/history/wholeTree/GitLogFilters.java
@@ -0,0 +1,101 @@
+/*
+ * Copyright 2000-2011 JetBrains s.r.o.
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+package git4idea.history.wholeTree;
+
+import com.google.common.collect.Sets;
+import com.intellij.util.Consumer;
+import git4idea.history.browser.ChangesFilter;
+import org.jetbrains.annotations.Nullable;
+
+import java.util.ArrayList;
+import java.util.Collections;
+import java.util.List;
+import java.util.Set;
+
+/**
+ * @author irengrig
+ * Date: 2/1/11
+ * Time: 7:27 PM
+ */
+public class GitLogFilters {
+ @Nullable
+ private final ChangesFilter.Comment myCommentFilter;
+ @Nullable
+ private final Set myCommitterFilters;
+ @Nullable
+ private final Set myStructureFilters;
+ @Nullable
+ private final List myPossibleReferencies;
+
+ public GitLogFilters() {
+ this(null, null, null, null);
+ }
+
+ public GitLogFilters(@Nullable ChangesFilter.Comment commentFilter,
+ @Nullable Set committerFilters,
+ @Nullable Set structureFilters, @Nullable List possibleReferencies) {
+ myCommentFilter = commentFilter;
+ myCommitterFilters = committerFilters;
+ myStructureFilters = structureFilters;
+ myPossibleReferencies = possibleReferencies;
+ }
+
+ public void callConsumer(final Consumer> consumer, boolean takeComment) {
+ final List> filters = new ArrayList>();
+ if (takeComment && myCommentFilter != null) {
+ filters.add(Collections.singletonMap(myCommentFilter, myCommentFilter).keySet());
+ }
+ if (myCommitterFilters != null) {
+ filters.add(myCommitterFilters);
+ }
+ if (myStructureFilters != null) {
+ filters.add(myStructureFilters);
+ }
+ final Set> cartesian = Sets.cartesianProduct(filters);
+ if (cartesian.isEmpty()) {
+ consumer.consume(Collections.emptyList());
+ } else {
+ for (List list : cartesian) {
+ consumer.consume(list);
+ }
+ }
+ }
+
+ @Nullable
+ public ChangesFilter.Comment getCommentFilter() {
+ return myCommentFilter;
+ }
+
+ @Nullable
+ public Set getCommitterFilters() {
+ return myCommitterFilters;
+ }
+
+ @Nullable
+ public Set getStructureFilters() {
+ return myStructureFilters;
+ }
+
+ public boolean isEmpty() {
+ return myCommentFilter == null && (myCommitterFilters == null || myCommitterFilters.isEmpty()) &&
+ (myStructureFilters == null || myStructureFilters.isEmpty());
+ }
+
+ @Nullable
+ public List getPossibleReferencies() {
+ return myPossibleReferencies;
+ }
+}
diff --git a/plugins/git4idea/src/git4idea/history/wholeTree/GitLogUI.java b/plugins/git4idea/src/git4idea/history/wholeTree/GitLogUI.java
index b48d540f3782..7d8dd71cfdd1 100644
--- a/plugins/git4idea/src/git4idea/history/wholeTree/GitLogUI.java
+++ b/plugins/git4idea/src/git4idea/history/wholeTree/GitLogUI.java
@@ -365,7 +365,7 @@ public class GitLogUI implements Disposable {
if (gitCommit == null) return;
final List branches = myDetailsCache.getBranches(root, commit.getHash());
if (branches != null) {
- myDetails.putBranches(gitCommit, branches);
+ myDetails.putBranches(root, gitCommit, branches);
}
final Application application = ApplicationManager.getApplication();
application.executeOnPooledThread(new Runnable() {
@@ -383,7 +383,7 @@ public class GitLogUI implements Disposable {
if (myDetails.isMissingBranchesInfo() && afterRows.length == 1 && afterRows[0] == rows[0]) {
final CommitI afterCommit = myTableModel.getCommitAt(rows[0]);
if (afterCommit.holdsDecoration() || (! afterCommit.equals(commit))) return;
- myDetails.putBranches(gitCommit, branches);
+ myDetails.putBranches(root, gitCommit, branches);
}
}
}, ModalityState.NON_MODAL, myProject.getDisposed());
@@ -888,22 +888,27 @@ public class GitLogUI implements Disposable {
}
private Color getLogicBackground(final boolean isSelected, final int row) {
- final Color bkgColor;
+ Color bkgColor;
final CommitI commitAt = myTableModel.getCommitAt(row);
GitCommit gitCommit = null;
+ VirtualFile root = null;
if (commitAt != null & (! commitAt.holdsDecoration())) {
- gitCommit = myDetailsCache.convert(commitAt.selectRepository(myRootsUnderVcs), commitAt.getHash());
+ root = commitAt.selectRepository(myRootsUnderVcs);
+ gitCommit = myDetailsCache.convert(root, commitAt.getHash());
}
if (isSelected) {
bkgColor = UIUtil.getTableSelectionBackground();
} else {
- if (gitCommit != null && gitCommit.isOnLocal() && gitCommit.isOnTracked()) {
- bkgColor = Colors.commonThisBranch;
- } else if (gitCommit != null && gitCommit.isOnLocal()) {
- bkgColor = Colors.ownThisBranch;
- } else {
- bkgColor = UIUtil.getTableBackground();
+ bkgColor = UIUtil.getTableBackground();
+ if (gitCommit != null) {
+ if (myDetailsCache.getStashName(root, gitCommit.getShortHash()) != null) {
+ bkgColor = Colors.stashed;
+ } else if (gitCommit.isOnLocal() && gitCommit.isOnTracked()) {
+ bkgColor = Colors.commonThisBranch;
+ } else if (gitCommit.isOnLocal()) {
+ bkgColor = Colors.ownThisBranch;
+ }
}
}
return bkgColor;
@@ -986,7 +991,7 @@ public class GitLogUI implements Disposable {
private void reloadRequest() {
myState = StepType.CONTINUE;
final int was = myTableModel.getRowCount();
- myDetailsCache.resetBranchesCache();
+ myDetailsCache.resetAsideCaches();
final Collection startingPoints = mySelectedBranch == null ? Collections.emptyList() : Collections.singletonList(mySelectedBranch);
myDescriptionRenderer.resetIcons();
final boolean commentFilterEmpty = StringUtil.isEmptyOrSpaces(myPreviousFilter);
@@ -995,29 +1000,31 @@ public class GitLogUI implements Disposable {
if (commentFilterEmpty && (myUserFilterI.myFilter == null)) {
myUsersSearchContext.clear();
- myMediator.reload(new RootsHolder(myRootsUnderVcs), startingPoints, Collections.>emptyList(), null);
+ myMediator.reload(new RootsHolder(myRootsUnderVcs), startingPoints, new GitLogFilters());
} else {
- final List> filters = new ArrayList>();
-
+ ChangesFilter.Comment comment = null;
if (! commentFilterEmpty) {
final Pair> preparse = preparse(myPreviousFilter);
final String first = preparse.getFirst();
- filters.add(Collections.singletonList(new ChangesFilter.Comment(first)));
+ comment = new ChangesFilter.Comment(first);
}
+ Set userFilters = null;
if (myUserFilterI.myFilter != null) {
final String[] strings = myUserFilterI.myFilter.split(",");
- final List userFilters = new ArrayList();
+ userFilters = new HashSet();
for (String string : strings) {
string = string.trim();
if (string.length() == 0) continue;
myUsersSearchContext.add(string.toLowerCase());
final String regexp = StringUtil.escapeToRegexp(string);
userFilters.add(new ChangesFilter.Committer(regexp));
+ userFilters.add(new ChangesFilter.Author(regexp));
}
- filters.add(userFilters);
}
- myMediator.reload(new RootsHolder(myRootsUnderVcs), startingPoints, filters, commentFilterEmpty ? null : myPreviousFilter.split("[\\s]"));
+ final List possibleReferencies = commentFilterEmpty ? null : Arrays.asList(myPreviousFilter.split("[\\s]"));
+ myMediator.reload(new RootsHolder(myRootsUnderVcs), startingPoints, new GitLogFilters(comment, userFilters, null,
+ possibleReferencies));
}
updateMoreVisibility();
selectionChanged();
@@ -1031,6 +1038,7 @@ public class GitLogUI implements Disposable {
Color local = new Color(117,238,199);
Color ownThisBranch = new Color(198,255,226);
Color commonThisBranch = new Color(223,223,255);
+ Color stashed = new Color(225,225,225);
}
private class MySpecificDetails {
@@ -1064,9 +1072,9 @@ public class GitLogUI implements Disposable {
return scrollPane;
}
- public void putBranches(final GitCommit commit, final List branches) {
+ public void putBranches(VirtualFile root, final GitCommit commit, final List