diff --git a/build.txt b/build.txt
index fbe9662c6076..d6241f2dc103 100644
--- a/build.txt
+++ b/build.txt
@@ -1 +1 @@
-138.SNAPSHOT
+140.SNAPSHOT
diff --git a/build/gant.xml b/build/gant.xml
index 4b56378f1652..88f2749a3f13 100644
--- a/build/gant.xml
+++ b/build/gant.xml
@@ -12,6 +12,7 @@
+
diff --git a/build/scripts/libLicenses.gant b/build/scripts/libLicenses.gant
index 70e22cda7d1d..3065c26d756c 100644
--- a/build/scripts/libLicenses.gant
+++ b/build/scripts/libLicenses.gant
@@ -280,6 +280,7 @@ libraryLicense(name: "ReflectASM", libraryName: "reflectasm-1.0.7.jar", version:
libraryLicense(name: "Objenesis", libraryName: "objenesis-1.2.jar", version: "1.2", license: "Apache 2.0", url: "http://objenesis.org/", licenseUrl: "http://apache.org/licenses/LICENSE-2.0")
libraryLicense(name: "EditorConfig Java Core", libraryName: "editorconfig-core-java.jar", version: "1.0", license: "Apache 2.0", url: "https://github.com/editorconfig/editorconfig-core-java/", licenseUrl: "https://github.com/editorconfig/editorconfig-core-java/blob/master/LICENSE")
libraryLicense(name: "Fest", libraryName: "fest", version: "", license: "Apache 2.0", licenseUrl: "http://www.apache.org/licenses/LICENSE-2.0.txt", url: "https://code.google.com/p/fest/")
+libraryLicense(name: "Gherkin", libraryName: "Gherkin", version: "2.12.2", license: "MIT", licenseUrl: "http://www.apache.org/licenses/LICENSE-2.0.txt", url: "https://github.com/cucumber/gherkin")
jetbrainsLibrary("Coverage")
jetbrainsLibrary("CoverageReport")
jetbrainsLibrary("JPS")
diff --git a/java/java-analysis-impl/src/com/intellij/codeInsight/daemon/impl/quickfix/RemoveUnusedVariableUtil.java b/java/java-analysis-impl/src/com/intellij/codeInsight/daemon/impl/quickfix/RemoveUnusedVariableUtil.java
index 59f7cad05f12..a024ba343962 100644
--- a/java/java-analysis-impl/src/com/intellij/codeInsight/daemon/impl/quickfix/RemoveUnusedVariableUtil.java
+++ b/java/java-analysis-impl/src/com/intellij/codeInsight/daemon/impl/quickfix/RemoveUnusedVariableUtil.java
@@ -16,6 +16,7 @@
package com.intellij.codeInsight.daemon.impl.quickfix;
import com.intellij.psi.*;
+import com.intellij.psi.tree.IElementType;
import com.intellij.psi.util.InheritanceUtil;
import com.intellij.psi.util.PropertyUtil;
import com.intellij.psi.util.PsiUtil;
@@ -104,7 +105,25 @@ public class RemoveUnusedVariableUtil {
sideEffects.add(element);
return true;
}
- PsiElement[] children = element.getChildren();
+
+ IElementType tokenType = null;
+ PsiExpression operand = null;
+ if (element instanceof PsiPrefixExpression) {
+ operand = ((PsiPrefixExpression)element).getOperand();
+ tokenType = ((PsiPrefixExpression)element).getOperationTokenType();
+ } else if (element instanceof PsiPostfixExpression) {
+ operand = ((PsiPostfixExpression)element).getOperand();
+ tokenType = ((PsiPostfixExpression)element).getOperationTokenType();
+ }
+
+ if (JavaTokenType.MINUSMINUS.equals(tokenType) || JavaTokenType.PLUSPLUS.equals(tokenType)) {
+ operand = PsiUtil.deparenthesizeExpression(operand);
+ if (!(operand instanceof PsiReferenceExpression && ((PsiReferenceExpression)operand).resolve() == variable)) {
+ sideEffects.add(element);
+ return true;
+ }
+ }
+ PsiElement[] children = element.getChildren();
for (PsiElement child : children) {
checkSideEffects(child, variable, sideEffects);
diff --git a/java/java-analysis-impl/src/com/intellij/codeInspection/java15api/Java15APIUsageInspectionBase.java b/java/java-analysis-impl/src/com/intellij/codeInspection/java15api/Java15APIUsageInspectionBase.java
index fdeb517f5a1d..8ade742af3d6 100644
--- a/java/java-analysis-impl/src/com/intellij/codeInspection/java15api/Java15APIUsageInspectionBase.java
+++ b/java/java-analysis-impl/src/com/intellij/codeInspection/java15api/Java15APIUsageInspectionBase.java
@@ -203,8 +203,10 @@ public class Java15APIUsageInspectionBase extends BaseJavaBatchLocalInspectionTo
@Override public void visitClass(PsiClass aClass) {
// Don't go into classes (anonymous, locals).
if (!aClass.hasModifierProperty(PsiModifier.ABSTRACT)) {
- final LanguageLevel effectiveLanguageLevel = getEffectiveLanguageLevel(ModuleUtilCore.findModuleForPsiElement(aClass));
- if (!effectiveLanguageLevel.isAtLeast(LanguageLevel.JDK_1_8) &&
+ final Module module = ModuleUtilCore.findModuleForPsiElement(aClass);
+ final LanguageLevel effectiveLanguageLevel = module != null ? getEffectiveLanguageLevel(module) : null;
+ if (effectiveLanguageLevel != null &&
+ !effectiveLanguageLevel.isAtLeast(LanguageLevel.JDK_1_8) &&
JavaVersionService.getInstance().getJavaSdkVersion(aClass).isAtLeast(JavaSdkVersion.JDK_1_8)) {
final List methods = new ArrayList();
for (HierarchicalMethodSignature methodSignature : aClass.getVisibleSignatures()) {
diff --git a/java/java-analysis-impl/src/com/intellij/codeInspection/uncheckedWarnings/UncheckedWarningLocalInspectionBase.java b/java/java-analysis-impl/src/com/intellij/codeInspection/uncheckedWarnings/UncheckedWarningLocalInspectionBase.java
index fa2789880371..b24f152537a5 100644
--- a/java/java-analysis-impl/src/com/intellij/codeInspection/uncheckedWarnings/UncheckedWarningLocalInspectionBase.java
+++ b/java/java-analysis-impl/src/com/intellij/codeInspection/uncheckedWarnings/UncheckedWarningLocalInspectionBase.java
@@ -375,8 +375,9 @@ public class UncheckedWarningLocalInspectionBase extends BaseJavaBatchLocalInspe
public void visitReturnStatement(PsiReturnStatement statement) {
super.visitReturnStatement(statement);
if (IGNORE_UNCHECKED_ASSIGNMENT) return;
+ final PsiLambdaExpression lambdaExpression = PsiTreeUtil.getParentOfType(statement, PsiLambdaExpression.class);
final PsiMethod method = PsiTreeUtil.getParentOfType(statement, PsiMethod.class);
- if (method != null) {
+ if (method != null && (lambdaExpression == null || PsiTreeUtil.isAncestor(lambdaExpression, method, true))) {
final PsiType returnType = method.getReturnType();
if (returnType != null && returnType != PsiType.VOID) {
final PsiExpression returnValue = statement.getReturnValue();
diff --git a/java/java-impl/src/com/intellij/codeInsight/highlighting/JavaPairedBraceMatcher.java b/java/java-impl/src/com/intellij/codeInsight/highlighting/JavaPairedBraceMatcher.java
index e0ba601a07cf..82d5ddb07997 100644
--- a/java/java-impl/src/com/intellij/codeInsight/highlighting/JavaPairedBraceMatcher.java
+++ b/java/java-impl/src/com/intellij/codeInsight/highlighting/JavaPairedBraceMatcher.java
@@ -28,7 +28,8 @@ import com.intellij.psi.tree.TokenSet;
public class JavaPairedBraceMatcher extends PairedBraceMatcherAdapter {
private static final TokenSet TYPE_TOKENS =
TokenSet.orSet(StdTokenSets.WHITE_SPACE_OR_COMMENT_BIT_SET,
- TokenSet.create(JavaTokenType.IDENTIFIER, JavaTokenType.COMMA,
+ TokenSet.create(JavaTokenType.IDENTIFIER, JavaTokenType.COMMA,
+ JavaTokenType.AT,//anno
JavaTokenType.RBRACKET, JavaTokenType.LBRACKET, //arrays
JavaTokenType.QUEST, JavaTokenType.EXTENDS_KEYWORD, JavaTokenType.SUPER_KEYWORD));//wildcards
diff --git a/java/java-impl/src/com/intellij/codeInsight/intention/impl/AddOverrideAnnotationAction.java b/java/java-impl/src/com/intellij/codeInsight/intention/impl/AddOverrideAnnotationAction.java
index b9bd7cd8b019..f2609b2a4433 100644
--- a/java/java-impl/src/com/intellij/codeInsight/intention/impl/AddOverrideAnnotationAction.java
+++ b/java/java-impl/src/com/intellij/codeInsight/intention/impl/AddOverrideAnnotationAction.java
@@ -1,5 +1,5 @@
/*
- * Copyright 2000-2009 JetBrains s.r.o.
+ * Copyright 2000-2014 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.
@@ -31,7 +31,6 @@ import org.jetbrains.annotations.NotNull;
* @author ven
*/
public class AddOverrideAnnotationAction implements IntentionAction {
- private static final String JAVA_LANG_OVERRIDE = "java.lang.Override";
@Override
@NotNull
@@ -51,11 +50,11 @@ public class AddOverrideAnnotationAction implements IntentionAction {
if (!file.getManager().isInProject(file)) return false;
PsiMethod method = findMethod(file, editor.getCaretModel().getOffset());
if (method == null) return false;
- if (method.getModifierList().findAnnotation(JAVA_LANG_OVERRIDE) != null) return false;
+ if (method.getModifierList().findAnnotation(CommonClassNames.JAVA_LANG_OVERRIDE) != null) return false;
PsiMethod[] superMethods = method.findSuperMethods();
for (PsiMethod superMethod : superMethods) {
if (!superMethod.hasModifierProperty(PsiModifier.ABSTRACT)
- && new AddAnnotationFix(JAVA_LANG_OVERRIDE, method).isAvailable(project, editor, file)) {
+ && new AddAnnotationFix(CommonClassNames.JAVA_LANG_OVERRIDE, method).isAvailable(project, editor, file)) {
return true;
}
}
@@ -67,7 +66,7 @@ public class AddOverrideAnnotationAction implements IntentionAction {
public void invoke(@NotNull Project project, Editor editor, PsiFile file) throws IncorrectOperationException {
PsiMethod method = findMethod(file, editor.getCaretModel().getOffset());
if (method != null) {
- new AddAnnotationFix(JAVA_LANG_OVERRIDE, method).invoke(project, editor, file);
+ new AddAnnotationFix(CommonClassNames.JAVA_LANG_OVERRIDE, method).invoke(project, editor, file);
}
}
diff --git a/java/java-impl/src/com/intellij/refactoring/invertBoolean/InvertBooleanHandler.java b/java/java-impl/src/com/intellij/refactoring/invertBoolean/InvertBooleanHandler.java
index df8b69cb7064..70d4570a9ced 100644
--- a/java/java-impl/src/com/intellij/refactoring/invertBoolean/InvertBooleanHandler.java
+++ b/java/java-impl/src/com/intellij/refactoring/invertBoolean/InvertBooleanHandler.java
@@ -56,13 +56,11 @@ public class InvertBooleanHandler implements RefactoringActionHandler {
return;
}
- if (!CommonRefactoringUtil.checkReadOnlyStatus(project, var)) return;
if (var instanceof PsiParameter && ((PsiParameter)var).getDeclarationScope() instanceof PsiMethod) {
final PsiMethod method = (PsiMethod)((PsiParameter)var).getDeclarationScope();
final PsiMethod superMethod = SuperMethodWarningUtil.checkSuperMethod(method, RefactoringBundle.message("to.refactor"));
- if (superMethod != null) {
- var = superMethod.getParameterList().getParameters()[method.getParameterList().getParameterIndex((PsiParameter)var)];
- }
+ if (superMethod == null) return;
+ var = superMethod.getParameterList().getParameters()[method.getParameterList().getParameterIndex((PsiParameter)var)];
}
new InvertBooleanDialog(var).show();
@@ -87,9 +85,8 @@ public class InvertBooleanHandler implements RefactoringActionHandler {
}
final PsiMethod superMethod = SuperMethodWarningUtil.checkSuperMethod(method, RefactoringBundle.message("to.refactor"));
- if (superMethod != null) method = superMethod;
-
- if (!CommonRefactoringUtil.checkReadOnlyStatus(project, method)) return;
+ if (superMethod == null) return;
+ method = superMethod;
new InvertBooleanDialog(method).show();
}
diff --git a/java/java-tests/testData/codeInsight/daemonCodeAnalyzer/genericsHighlighting8/UncheckedWarningInsideLambdaReturnStatement.java b/java/java-tests/testData/codeInsight/daemonCodeAnalyzer/genericsHighlighting8/UncheckedWarningInsideLambdaReturnStatement.java
new file mode 100644
index 000000000000..856523a80fb5
--- /dev/null
+++ b/java/java-tests/testData/codeInsight/daemonCodeAnalyzer/genericsHighlighting8/UncheckedWarningInsideLambdaReturnStatement.java
@@ -0,0 +1,65 @@
+import java.util.ArrayList;
+import java.util.List;
+import java.util.stream.Stream;
+
+class Test {
+
+ private Repository repository = null;
+
+ public Stream test() {
+ return repository.all()
+ .flatMap(foo -> {
+
+ class AB {
+ List a() {
+ return new ArrayList();
+ }
+ }
+
+ AB ab = new AB();
+ System.out.println(ab);
+
+ if (foo != null) {
+ return repository.update();
+ }
+ return Stream.empty();
+ })
+ .map(UpdateResult::getPerson);
+ }
+
+
+ public static class Repository {
+
+ public Stream all() {
+ return Stream.empty();
+ }
+
+ public Stream update() {
+ return Stream.empty();
+ }
+
+ }
+
+ public static class Person {
+ }
+
+ public static class UpdateResult {
+
+ private final Person person;
+
+ private final Object metadata;
+
+ public UpdateResult(Person person, Object metadata) {
+ this.person = person;
+ this.metadata = metadata;
+ }
+
+ public Person getPerson() {
+ return person;
+ }
+
+ public Object getMetadata() {
+ return metadata;
+ }
+ }
+}
\ No newline at end of file
diff --git a/java/java-tests/testSrc/com/intellij/codeInsight/daemon/lambda/GenericsHighlighting8Test.java b/java/java-tests/testSrc/com/intellij/codeInsight/daemon/lambda/GenericsHighlighting8Test.java
index a919843a3164..49027135eecf 100644
--- a/java/java-tests/testSrc/com/intellij/codeInsight/daemon/lambda/GenericsHighlighting8Test.java
+++ b/java/java-tests/testSrc/com/intellij/codeInsight/daemon/lambda/GenericsHighlighting8Test.java
@@ -762,6 +762,10 @@ public class GenericsHighlighting8Test extends LightDaemonAnalyzerTestCase {
public void testIDEA78402() { doTest(); }
+ public void testUncheckedWarningInsideLambdaReturnStatement() throws Exception {
+ doTest(true);
+ }
+
private void doTest() {
doTest(false);
}
diff --git a/java/java-tests/testSrc/com/intellij/codeInsight/highlighting/JavaBraceMatcherTest.java b/java/java-tests/testSrc/com/intellij/codeInsight/highlighting/JavaBraceMatcherTest.java
index d90b336cff4d..30188c16f0cf 100644
--- a/java/java-tests/testSrc/com/intellij/codeInsight/highlighting/JavaBraceMatcherTest.java
+++ b/java/java-tests/testSrc/com/intellij/codeInsight/highlighting/JavaBraceMatcherTest.java
@@ -24,10 +24,10 @@ public class JavaBraceMatcherTest extends LightCodeInsightFixtureTestCase {
public void testGenerics() {
myFixture.configureByText("a.java", "import java.util.ArrayList;" +
"class A {" +
- " ArrayList extends String[]> f;" +
+ " ArrayList extends @Anno String[]> f;" +
"}");
final int offset = BraceMatchingUtil.getMatchedBraceOffset(myFixture.getEditor(), true, myFixture.getFile());
- assertEquals(66, offset);
+ assertEquals(72, offset);
}
public void testBrokenText() {
diff --git a/platform/analysis-impl/src/com/intellij/codeInsight/daemon/impl/GeneralHighlightingPass.java b/platform/analysis-impl/src/com/intellij/codeInsight/daemon/impl/GeneralHighlightingPass.java
index 757a3f63bfda..ea35f552da73 100644
--- a/platform/analysis-impl/src/com/intellij/codeInsight/daemon/impl/GeneralHighlightingPass.java
+++ b/platform/analysis-impl/src/com/intellij/codeInsight/daemon/impl/GeneralHighlightingPass.java
@@ -86,7 +86,12 @@ public class GeneralHighlightingPass extends ProgressableTextEditorHighlightingP
private static final Comparator VISITOR_ORDER_COMPARATOR = new Comparator() {
@Override
public int compare(final HighlightVisitor o1, final HighlightVisitor o2) {
- return o1.order() - o2.order();
+ int delta = o1.order() - o2.order();
+ if (delta != 0) return delta;
+ if (o1.getClass() == o2.getClass()) {
+ LOG.error("Duplicate visitors registered: "+o1 +" and "+o2 + " ("+o1.getClass()+")");
+ }
+ return 0;
}
};
protected final EditorColorsScheme myGlobalScheme;
diff --git a/platform/dvcs-impl/src/com/intellij/dvcs/branch/DvcsBranchPopup.java b/platform/dvcs-impl/src/com/intellij/dvcs/branch/DvcsBranchPopup.java
index e4b52fea4683..c3c98afa34dc 100644
--- a/platform/dvcs-impl/src/com/intellij/dvcs/branch/DvcsBranchPopup.java
+++ b/platform/dvcs-impl/src/com/intellij/dvcs/branch/DvcsBranchPopup.java
@@ -87,8 +87,7 @@ public abstract class DvcsBranchPopup {
@NotNull
private String createPopupTitle(@NotNull Repo currentRepository) {
String title = myVcs.getDisplayName() + " Branches";
- if (myRepositoryManager.moreThanOneRoot() &&
- (myMultiRootBranchConfig.diverged() || myVcsSettings.getSyncSetting() == DvcsSyncSettings.Value.DONT_SYNC)) {
+ if (myRepositoryManager.moreThanOneRoot() && myVcsSettings.getSyncSetting() == DvcsSyncSettings.Value.DONT_SYNC) {
title += " in " + DvcsUtil.getShortRepositoryName(currentRepository);
}
return title;
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 7a8d84e018be..6b8b9ed34617 100644
--- a/platform/lang-api/src/com/intellij/psi/codeStyle/CommonCodeStyleSettings.java
+++ b/platform/lang-api/src/com/intellij/psi/codeStyle/CommonCodeStyleSettings.java
@@ -918,7 +918,15 @@ public class CommonCodeStyleSettings {
@Override
public void writeExternal(Element element) throws WriteExternalException {
- DefaultJDOMExternalizer.writeExternal(this, element, new DifferenceFilter(this, new IndentOptions()));
+ DefaultJDOMExternalizer.writeExternal(this, element, new DefaultJDOMExternalizer.JDOMFilter() {
+ @Override
+ public boolean isAccept(@NotNull Field field) {
+ if ("KEEP_INDENTS_ON_EMPTY_LINES".equals(field.getName())) {
+ return KEEP_INDENTS_ON_EMPTY_LINES;
+ }
+ return true;
+ }
+ });
}
public void serialize(Element indentOptionsElement, final IndentOptions defaultOptions) {
diff --git a/platform/lang-api/src/com/intellij/psi/codeStyle/arrangement/ArrangementUtil.java b/platform/lang-api/src/com/intellij/psi/codeStyle/arrangement/ArrangementUtil.java
index 2bc92f71fe94..174db45b2f11 100644
--- a/platform/lang-api/src/com/intellij/psi/codeStyle/arrangement/ArrangementUtil.java
+++ b/platform/lang-api/src/com/intellij/psi/codeStyle/arrangement/ArrangementUtil.java
@@ -205,7 +205,7 @@ public class ArrangementUtil {
public void visit(@NotNull ArrangementAtomMatchCondition condition) {
ArrangementSettingsToken type = condition.getType();
Object value = condition.getValue();
- result.put(condition.getType(), type.equals(value) ? null : value);
+ result.put(condition.getType(), type.equals(value) ? null : value);
}
@Override
@@ -260,10 +260,10 @@ public class ArrangementUtil {
@Nullable
public static ArrangementEntryMatcher buildMatcher(@NotNull ArrangementAtomMatchCondition condition) {
if (StdArrangementTokenType.ENTRY_TYPE.is(condition.getType())) {
- return new ByTypeArrangementEntryMatcher(condition.getType());
+ return new ByTypeArrangementEntryMatcher(condition);
}
else if (StdArrangementTokenType.MODIFIER.is(condition.getType())) {
- return new ByModifierArrangementEntryMatcher(condition.getType());
+ return new ByModifierArrangementEntryMatcher(condition);
}
else if (StdArrangementTokens.Regexp.NAME.equals(condition.getType())) {
return new ByNameArrangementEntryMatcher(condition.getValue().toString());
diff --git a/platform/lang-api/src/com/intellij/psi/codeStyle/arrangement/match/ByModifierArrangementEntryMatcher.java b/platform/lang-api/src/com/intellij/psi/codeStyle/arrangement/match/ByModifierArrangementEntryMatcher.java
index d972eb824fb1..ec58bffb9003 100644
--- a/platform/lang-api/src/com/intellij/psi/codeStyle/arrangement/match/ByModifierArrangementEntryMatcher.java
+++ b/platform/lang-api/src/com/intellij/psi/codeStyle/arrangement/match/ByModifierArrangementEntryMatcher.java
@@ -17,6 +17,7 @@ package com.intellij.psi.codeStyle.arrangement.match;
import com.intellij.psi.codeStyle.arrangement.ArrangementEntry;
import com.intellij.psi.codeStyle.arrangement.ModifierAwareArrangementEntry;
+import com.intellij.psi.codeStyle.arrangement.model.ArrangementAtomMatchCondition;
import com.intellij.psi.codeStyle.arrangement.std.ArrangementSettingsToken;
import com.intellij.util.containers.ContainerUtilRt;
import org.jetbrains.annotations.NotNull;
@@ -30,20 +31,28 @@ import java.util.Set;
*/
public class ByModifierArrangementEntryMatcher implements ArrangementEntryMatcher {
- @NotNull private final Set myModifiers = ContainerUtilRt.newHashSet();
+ @NotNull private final Set myModifiers = ContainerUtilRt.newHashSet();
- public ByModifierArrangementEntryMatcher(@NotNull ArrangementSettingsToken interestedModifier) {
+ public ByModifierArrangementEntryMatcher(@NotNull ArrangementAtomMatchCondition interestedModifier) {
myModifiers.add(interestedModifier);
}
- public ByModifierArrangementEntryMatcher(@NotNull Collection interestedModifiers) {
+ public ByModifierArrangementEntryMatcher(@NotNull Collection interestedModifiers) {
myModifiers.addAll(interestedModifiers);
}
@Override
public boolean isMatched(@NotNull ArrangementEntry entry) {
if (entry instanceof ModifierAwareArrangementEntry) {
- return ((ModifierAwareArrangementEntry)entry).getModifiers().containsAll(myModifiers);
+ final Set modifiers = ((ModifierAwareArrangementEntry)entry).getModifiers();
+ for (ArrangementAtomMatchCondition condition : myModifiers) {
+ final Object value = condition.getValue();
+ boolean isInverted = value instanceof Boolean && !((Boolean)value);
+ if (isInverted == modifiers.contains(condition.getType())) {
+ return false;
+ }
+ }
+ return true;
}
return false;
}
diff --git a/platform/lang-api/src/com/intellij/psi/codeStyle/arrangement/match/ByTypeArrangementEntryMatcher.java b/platform/lang-api/src/com/intellij/psi/codeStyle/arrangement/match/ByTypeArrangementEntryMatcher.java
index 14a429fbc80a..b994490fb60a 100644
--- a/platform/lang-api/src/com/intellij/psi/codeStyle/arrangement/match/ByTypeArrangementEntryMatcher.java
+++ b/platform/lang-api/src/com/intellij/psi/codeStyle/arrangement/match/ByTypeArrangementEntryMatcher.java
@@ -17,6 +17,7 @@ package com.intellij.psi.codeStyle.arrangement.match;
import com.intellij.psi.codeStyle.arrangement.ArrangementEntry;
import com.intellij.psi.codeStyle.arrangement.TypeAwareArrangementEntry;
+import com.intellij.psi.codeStyle.arrangement.model.ArrangementAtomMatchCondition;
import com.intellij.psi.codeStyle.arrangement.std.ArrangementSettingsToken;
import com.intellij.util.containers.ContainerUtilRt;
import org.jetbrains.annotations.NotNull;
@@ -36,26 +37,34 @@ import java.util.Set;
*/
public class ByTypeArrangementEntryMatcher implements ArrangementEntryMatcher {
- @NotNull private final Set myTypes = ContainerUtilRt.newHashSet();
+ @NotNull private final Set myTypes = ContainerUtilRt.newHashSet();
- public ByTypeArrangementEntryMatcher(@NotNull ArrangementSettingsToken interestedType) {
+ public ByTypeArrangementEntryMatcher(@NotNull ArrangementAtomMatchCondition interestedType) {
myTypes.add(interestedType);
}
- public ByTypeArrangementEntryMatcher(@NotNull Collection interestedTypes) {
+ public ByTypeArrangementEntryMatcher(@NotNull Collection interestedTypes) {
myTypes.addAll(interestedTypes);
}
@Override
public boolean isMatched(@NotNull ArrangementEntry entry) {
if (entry instanceof TypeAwareArrangementEntry) {
- return ((TypeAwareArrangementEntry)entry).getTypes().containsAll(myTypes);
+ final Set types = ((TypeAwareArrangementEntry)entry).getTypes();
+ for (ArrangementAtomMatchCondition condition : myTypes) {
+ final Object value = condition.getValue();
+ boolean isInverted = value instanceof Boolean && !((Boolean)value);
+ if (isInverted == types.contains(condition.getType())) {
+ return false;
+ }
+ }
+ return true;
}
return false;
}
@NotNull
- public Set getTypes() {
+ public Set getTypes() {
return myTypes;
}
diff --git a/platform/lang-api/src/com/intellij/psi/codeStyle/arrangement/match/DefaultArrangementEntryMatcherSerializer.java b/platform/lang-api/src/com/intellij/psi/codeStyle/arrangement/match/DefaultArrangementEntryMatcherSerializer.java
index b99f2aa45057..2584ec148ef1 100644
--- a/platform/lang-api/src/com/intellij/psi/codeStyle/arrangement/match/DefaultArrangementEntryMatcherSerializer.java
+++ b/platform/lang-api/src/com/intellij/psi/codeStyle/arrangement/match/DefaultArrangementEntryMatcherSerializer.java
@@ -150,12 +150,30 @@ public class DefaultArrangementEntryMatcherSerializer {
if (text != null && processInnerText) {
text = StringUtil.unescapeStringCharacters(matcherElement.getText());
if (!StringUtil.isEmpty(text)) {
- value = text;
+ final Boolean booleanValue = parseBooleanValue(text);
+ if (booleanValue != null) {
+ value = booleanValue;
+ }
+ else {
+ value = text;
+ }
}
}
return new ArrangementAtomMatchCondition(token, value);
}
+ @Nullable
+ private static Boolean parseBooleanValue(@NotNull String text) {
+ if (StringUtil.equalsIgnoreCase(text, Boolean.TRUE.toString())) {
+ return true;
+ }
+
+ if (StringUtil.equalsIgnoreCase(text, Boolean.FALSE.toString())) {
+ return false;
+ }
+ return null;
+ }
+
private static class MySerializationVisitor implements ArrangementMatchConditionVisitor {
Element result;
@@ -168,6 +186,9 @@ public class DefaultArrangementEntryMatcherSerializer {
if (StdArrangementTokenType.REG_EXP.is(type)) {
element.setText(StringUtil.escapeStringCharacters(condition.getValue().toString()));
}
+ else if (condition.getValue() instanceof Boolean) {
+ element.setText(condition.getValue().toString());
+ }
register(element);
}
diff --git a/platform/lang-api/src/com/intellij/psi/codeStyle/arrangement/match/StdArrangementEntryMatcher.java b/platform/lang-api/src/com/intellij/psi/codeStyle/arrangement/match/StdArrangementEntryMatcher.java
index 3225405b94cb..9d4819677803 100644
--- a/platform/lang-api/src/com/intellij/psi/codeStyle/arrangement/match/StdArrangementEntryMatcher.java
+++ b/platform/lang-api/src/com/intellij/psi/codeStyle/arrangement/match/StdArrangementEntryMatcher.java
@@ -18,10 +18,7 @@ package com.intellij.psi.codeStyle.arrangement.match;
import com.intellij.openapi.util.MultiValuesMap;
import com.intellij.psi.codeStyle.arrangement.ArrangementEntry;
import com.intellij.psi.codeStyle.arrangement.model.*;
-import com.intellij.psi.codeStyle.arrangement.std.ArrangementSettingsToken;
-import com.intellij.psi.codeStyle.arrangement.std.StdArrangementSettingsToken;
-import com.intellij.psi.codeStyle.arrangement.std.StdArrangementTokenType;
-import com.intellij.psi.codeStyle.arrangement.std.StdArrangementTokens;
+import com.intellij.psi.codeStyle.arrangement.std.*;
import com.intellij.util.containers.ContainerUtilRt;
import org.jetbrains.annotations.NotNull;
import org.jetbrains.annotations.Nullable;
@@ -129,8 +126,8 @@ public class StdArrangementEntryMatcher implements ArrangementEntryMatcher {
* Maps token type to all arrangement tokens that were encountered so far by parsing conditions with
* {@link #onCondition(ArrangementAtomMatchCondition) onCondition} calls.
*/
- @NotNull protected final MultiValuesMap context =
- new MultiValuesMap();
+ @NotNull protected final MultiValuesMap context =
+ new MultiValuesMap();
@Nullable private String myNamePattern;
@Nullable private String myNamespacePattern;
@Nullable private String myText;
@@ -139,9 +136,9 @@ public class StdArrangementEntryMatcher implements ArrangementEntryMatcher {
* Adds given entry to context by given entry type.
* @param token token added to context
*/
- protected void addToContext(@NotNull StdArrangementSettingsToken token) {
+ protected void addToContext(@NotNull StdArrangementSettingsToken token, @NotNull ArrangementAtomMatchCondition condition) {
StdArrangementTokenType tokenType = token.getTokenType();
- context.put(tokenType, token);
+ context.put(tokenType, condition);
}
@Override
@@ -157,10 +154,10 @@ public class StdArrangementEntryMatcher implements ArrangementEntryMatcher {
myText = condition.getValue().toString();
}
Object v = condition.getValue();
- //Process any StdArrangementSettingsToken. No need to change it when new types of tokens will be processed.
- if (v instanceof StdArrangementSettingsToken) {
- StdArrangementSettingsToken token = (StdArrangementSettingsToken)v;
- addToContext(token);
+ final ArrangementSettingsToken type = condition.getType();
+ if (type instanceof StdArrangementSettingsToken) {
+ //Process any StdArrangementSettingsToken. No need to change it when new types of tokens will be processed.
+ addToContext((StdArrangementSettingsToken)type, condition);
}
}
@@ -168,11 +165,11 @@ public class StdArrangementEntryMatcher implements ArrangementEntryMatcher {
@Override
public Collection buildMatchers() {
List result = ContainerUtilRt.newArrayList(myMatchers);
- Collection entryTokens = context.get(StdArrangementTokenType.ENTRY_TYPE);
+ Collection entryTokens = context.get(StdArrangementTokenType.ENTRY_TYPE);
if (entryTokens!= null) {
result.add(new ByTypeArrangementEntryMatcher(entryTokens));
}
- Collection modifierTokens = context.get(StdArrangementTokenType.MODIFIER);
+ Collection modifierTokens = context.get(StdArrangementTokenType.MODIFIER);
if (modifierTokens != null) {
result.add(new ByModifierArrangementEntryMatcher(modifierTokens));
}
diff --git a/platform/lang-api/src/com/intellij/psi/codeStyle/arrangement/match/StdArrangementMatchRule.java b/platform/lang-api/src/com/intellij/psi/codeStyle/arrangement/match/StdArrangementMatchRule.java
index 220f143010cc..26eb9d65ba63 100644
--- a/platform/lang-api/src/com/intellij/psi/codeStyle/arrangement/match/StdArrangementMatchRule.java
+++ b/platform/lang-api/src/com/intellij/psi/codeStyle/arrangement/match/StdArrangementMatchRule.java
@@ -22,6 +22,7 @@ import com.intellij.psi.codeStyle.arrangement.std.StdArrangementTokenType;
import org.jetbrains.annotations.NotNull;
import org.jetbrains.annotations.Nullable;
+import java.util.Map;
import java.util.Set;
/**
@@ -55,8 +56,10 @@ public class StdArrangementMatchRule extends ArrangementMatchRule implements Clo
@Override
public int compareTo(@NotNull StdArrangementMatchRule o) {
- final Set tokens = ArrangementUtil.extractTokens(getMatcher().getCondition()).keySet();
- final Set tokens1 = ArrangementUtil.extractTokens(o.getMatcher().getCondition()).keySet();
+ final Map tokenValues = ArrangementUtil.extractTokens(getMatcher().getCondition());
+ final Map tokenValues1 = ArrangementUtil.extractTokens(o.getMatcher().getCondition());
+ final Set tokens = tokenValues.keySet();
+ final Set tokens1 = tokenValues1.keySet();
if (tokens1.containsAll(tokens)) {
return tokens.containsAll(tokens1) ? 0 : 1;
}
@@ -65,9 +68,9 @@ public class StdArrangementMatchRule extends ArrangementMatchRule implements Clo
return -1;
}
- final String entryType = getEntryType(tokens);
- final String entryType1 = getEntryType(tokens1);
- final int compare = StringUtil.compare(entryType, entryType1, false);
+ final String entryType = getEntryType(tokenValues);
+ final String entryType1 = getEntryType(tokenValues1);
+ final int compare = StringUtil.compare(entryType1, entryType, false);
if (compare != 0 || tokens.size() == tokens1.size()) {
return compare;
}
@@ -76,10 +79,13 @@ public class StdArrangementMatchRule extends ArrangementMatchRule implements Clo
}
@Nullable
- private static String getEntryType(@NotNull Set tokens) {
- for (ArrangementSettingsToken token : tokens) {
- if (StdArrangementTokenType.ENTRY_TYPE.is(token)) {
- return token.getId();
+ private static String getEntryType(@NotNull Map tokens) {
+ for (Map.Entry token : tokens.entrySet()) {
+ if (StdArrangementTokenType.ENTRY_TYPE.is(token.getKey())) {
+ final Object value = token.getValue();
+ if (!(value instanceof Boolean) || (Boolean)value) {
+ return token.getKey().getId();
+ }
}
}
return null;
diff --git a/platform/lang-api/src/com/intellij/psi/codeStyle/arrangement/model/ArrangementAtomMatchCondition.java b/platform/lang-api/src/com/intellij/psi/codeStyle/arrangement/model/ArrangementAtomMatchCondition.java
index 31673d17586e..64f7ead73931 100644
--- a/platform/lang-api/src/com/intellij/psi/codeStyle/arrangement/model/ArrangementAtomMatchCondition.java
+++ b/platform/lang-api/src/com/intellij/psi/codeStyle/arrangement/model/ArrangementAtomMatchCondition.java
@@ -16,6 +16,7 @@
package com.intellij.psi.codeStyle.arrangement.model;
import com.intellij.psi.codeStyle.arrangement.std.ArrangementSettingsToken;
+import com.intellij.psi.codeStyle.arrangement.std.InvertibleArrangementSettingsToken;
import org.jetbrains.annotations.NotNull;
/**
@@ -31,10 +32,8 @@ public class ArrangementAtomMatchCondition implements ArrangementMatchCondition
@NotNull private final ArrangementSettingsToken myType;
@NotNull private final Object myValue;
- private boolean myInverted;
-
public ArrangementAtomMatchCondition(@NotNull ArrangementSettingsToken type) {
- this(type, type);
+ this(type, type instanceof InvertibleArrangementSettingsToken ? Boolean.TRUE : type);
}
public ArrangementAtomMatchCondition(@NotNull ArrangementSettingsToken type, @NotNull Object value) {
@@ -57,15 +56,10 @@ public class ArrangementAtomMatchCondition implements ArrangementMatchCondition
visitor.visit(this);
}
- public void setInverted(boolean inverted) {
- myInverted = inverted;
- }
-
@Override
public int hashCode() {
int result = myType.hashCode();
result = 31 * result + myValue.hashCode();
- result = 31 * result + (myInverted ? 1 : 0);
return result;
}
@@ -80,9 +74,6 @@ public class ArrangementAtomMatchCondition implements ArrangementMatchCondition
ArrangementAtomMatchCondition setting = (ArrangementAtomMatchCondition)o;
- if (myInverted != setting.myInverted) {
- return false;
- }
if (!myType.equals(setting.myType)) {
return false;
}
@@ -96,18 +87,16 @@ public class ArrangementAtomMatchCondition implements ArrangementMatchCondition
@NotNull
@Override
public ArrangementAtomMatchCondition clone() {
- ArrangementAtomMatchCondition result = new ArrangementAtomMatchCondition(myType, myValue);
- result.setInverted(myInverted);
- return result;
+ return new ArrangementAtomMatchCondition(myType, myValue);
}
@Override
public String toString() {
- if (myType.equals(myValue)) {
- return String.format("%s%s", myInverted ? "not " : "", myType.getRepresentationValue());
+ if (myValue instanceof Boolean) {
+ return String.format("%s%s", (Boolean)myValue ? "" : "not " , myType.getRepresentationValue());
}
else {
- return String.format("%s: %s%s", myType.getRepresentationValue(), myInverted ? "not " : "", myValue.toString().toLowerCase());
+ return String.format("%s: %s", myType.getRepresentationValue(), myValue.toString().toLowerCase());
}
}
}
diff --git a/platform/lang-api/src/com/intellij/psi/codeStyle/arrangement/std/ArrangementStandardSettingsManager.java b/platform/lang-api/src/com/intellij/psi/codeStyle/arrangement/std/ArrangementStandardSettingsManager.java
index 55883c0d3b4b..5b3ccac7d3c8 100644
--- a/platform/lang-api/src/com/intellij/psi/codeStyle/arrangement/std/ArrangementStandardSettingsManager.java
+++ b/platform/lang-api/src/com/intellij/psi/codeStyle/arrangement/std/ArrangementStandardSettingsManager.java
@@ -164,15 +164,22 @@ public class ArrangementStandardSettingsManager {
private int parseWidth(@NotNull ArrangementSettingsToken token, @NotNull SimpleColoredComponent renderer) {
renderer.clear();
- renderer.append(token.getRepresentationValue(),
- SimpleTextAttributes.fromTextAttributes(myColorsProvider.getTextAttributes(token, true)));
+ final String value = getPresentationValue(token);
+ renderer.append(value, SimpleTextAttributes.fromTextAttributes(myColorsProvider.getTextAttributes(token, true)));
int result = renderer.getPreferredSize().width;
renderer.clear();
- renderer.append(token.getRepresentationValue(),
- SimpleTextAttributes.fromTextAttributes(myColorsProvider.getTextAttributes(token, false)));
+ renderer.append(value, SimpleTextAttributes.fromTextAttributes(myColorsProvider.getTextAttributes(token, false)));
return Math.max(result, renderer.getPreferredSize().width);
}
+
+ @NotNull
+ private static String getPresentationValue(@NotNull ArrangementSettingsToken token) {
+ if (token instanceof InvertibleArrangementSettingsToken) {
+ return ((InvertibleArrangementSettingsToken)token).getInvertedRepresentationValue();
+ }
+ return token.getRepresentationValue();
+ }
public List sort(@NotNull Collection tokens) {
List result = ContainerUtilRt.newArrayList(tokens);
diff --git a/platform/lang-api/src/com/intellij/psi/codeStyle/arrangement/std/ArrangementUiComponent.java b/platform/lang-api/src/com/intellij/psi/codeStyle/arrangement/std/ArrangementUiComponent.java
index b752647c12d8..e76818e3cf48 100644
--- a/platform/lang-api/src/com/intellij/psi/codeStyle/arrangement/std/ArrangementUiComponent.java
+++ b/platform/lang-api/src/com/intellij/psi/codeStyle/arrangement/std/ArrangementUiComponent.java
@@ -36,7 +36,7 @@ import java.util.Set;
* @since 3/11/13 10:22 AM
*/
public interface ArrangementUiComponent {
-
+
@Nullable ArrangementSettingsToken getToken();
@NotNull Set getAvailableTokens();
@@ -107,7 +107,20 @@ public interface ArrangementUiComponent {
int getBaselineToUse(int width, int height);
void setListener(@NotNull Listener listener);
-
+
+ /**
+ * Method to process second click on the component,
+ * e.g. we can deselect the component or invert it condition
+ */
+ void handleMouseClickOnSelected();
+
+ /**
+ * For condition that can't be disabled,
+ * e.g. 'not public' can be used with any other rule like 'private' or 'not private'
+ * @return
+ */
+ boolean alwaysCanBeActive();
+
interface Factory {
ExtensionPointName EP_NAME = ExtensionPointName.create("com.intellij.rearranger.ui");
diff --git a/platform/lang-api/src/com/intellij/psi/codeStyle/arrangement/std/InvertibleArrangementSettingsToken.java b/platform/lang-api/src/com/intellij/psi/codeStyle/arrangement/std/InvertibleArrangementSettingsToken.java
new file mode 100644
index 000000000000..0298ab9184b2
--- /dev/null
+++ b/platform/lang-api/src/com/intellij/psi/codeStyle/arrangement/std/InvertibleArrangementSettingsToken.java
@@ -0,0 +1,33 @@
+/*
+ * Copyright 2000-2014 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.psi.codeStyle.arrangement.std;
+
+import org.jetbrains.annotations.NotNull;
+
+/**
+ * Tokens that can be used in conditions in inverted state,
+ * e.g. 'public' -> 'not public' unlike 'order' or 'name' that can't be inverted
+ *
+ * @author Svetlana.Zemlyanskaya
+ */
+public interface InvertibleArrangementSettingsToken {
+
+ /**
+ * Inverted representation value that will be used in UI
+ */
+ @NotNull
+ String getInvertedRepresentationValue();
+}
diff --git a/platform/lang-api/src/com/intellij/psi/codeStyle/arrangement/std/StdArrangementSettingsToken.java b/platform/lang-api/src/com/intellij/psi/codeStyle/arrangement/std/StdArrangementSettingsToken.java
index d6503f56e6f3..2ddbf02c9aec 100644
--- a/platform/lang-api/src/com/intellij/psi/codeStyle/arrangement/std/StdArrangementSettingsToken.java
+++ b/platform/lang-api/src/com/intellij/psi/codeStyle/arrangement/std/StdArrangementSettingsToken.java
@@ -52,9 +52,9 @@ public class StdArrangementSettingsToken extends ArrangementSettingsToken {
return myTokenType;
}
- private StdArrangementSettingsToken(@NotNull String id,
- @NotNull String uiName,
- @NotNull StdArrangementTokenType tokenType) {
+ protected StdArrangementSettingsToken(@NotNull String id,
+ @NotNull String uiName,
+ @NotNull StdArrangementTokenType tokenType) {
super(id, uiName);
myTokenType = tokenType;
}
diff --git a/platform/lang-api/src/com/intellij/psi/codeStyle/arrangement/std/StdArrangementTokens.java b/platform/lang-api/src/com/intellij/psi/codeStyle/arrangement/std/StdArrangementTokens.java
index 61ebcdb97ace..15770aded615 100644
--- a/platform/lang-api/src/com/intellij/psi/codeStyle/arrangement/std/StdArrangementTokens.java
+++ b/platform/lang-api/src/com/intellij/psi/codeStyle/arrangement/std/StdArrangementTokens.java
@@ -87,6 +87,12 @@ public class StdArrangementTokens {
};
}
+ private static StdArrangementSettingsToken invertible(@NotNull String id, @NotNull StdArrangementTokenType type) {
+ StdArrangementSettingsToken result = StdInvertibleArrangementSettingsToken.invertibleTokenById(id, type);
+ TOKENS_BY_ID.put(id, result);
+ return result;
+ }
+
private static StdArrangementSettingsToken token(@NotNull String id, @NotNull StdArrangementTokenType type) {
StdArrangementSettingsToken result = StdArrangementSettingsToken.tokenById(id, type);
TOKENS_BY_ID.put(id, result);
@@ -132,20 +138,23 @@ public class StdArrangementTokens {
}
}
public static class EntryType {
- @NotNull public static final ArrangementSettingsToken CLASS = token("CLASS", StdArrangementTokenType.ENTRY_TYPE);
- @NotNull public static final ArrangementSettingsToken ANONYMOUS_CLASS = token("ANONYMOUS_CLASS", StdArrangementTokenType.ENTRY_TYPE);
- @NotNull public static final ArrangementSettingsToken FIELD = token("FIELD", StdArrangementTokenType.ENTRY_TYPE);
- @NotNull public static final ArrangementSettingsToken CONSTRUCTOR = token("CONSTRUCTOR", StdArrangementTokenType.ENTRY_TYPE);
- @NotNull public static final ArrangementSettingsToken METHOD = token("METHOD", StdArrangementTokenType.ENTRY_TYPE);
- @NotNull public static final ArrangementSettingsToken ENUM = token("ENUM", StdArrangementTokenType.ENTRY_TYPE);
- @NotNull public static final ArrangementSettingsToken INTERFACE = token("INTERFACE", StdArrangementTokenType.ENTRY_TYPE);
- @NotNull public static final ArrangementSettingsToken CONST = token("CONST", StdArrangementTokenType.ENTRY_TYPE);
- @NotNull public static final ArrangementSettingsToken VAR = token("VAR", StdArrangementTokenType.ENTRY_TYPE);
- @NotNull public static final ArrangementSettingsToken PROPERTY = token("PROPERTY", StdArrangementTokenType.ENTRY_TYPE);
- @NotNull public static final ArrangementSettingsToken EVENT_HANDLER = token("EVENT_HANDLER", StdArrangementTokenType.ENTRY_TYPE);
- @NotNull public static final ArrangementSettingsToken STATIC_INIT = token("STATIC_INIT", StdArrangementTokenType.ENTRY_TYPE);
- @NotNull public static final ArrangementSettingsToken NAMESPACE = token("NAMESPACE", StdArrangementTokenType.ENTRY_TYPE);
- @NotNull public static final ArrangementSettingsToken TRAIT = token("TRAIT", StdArrangementTokenType.ENTRY_TYPE);
+ @NotNull public static final ArrangementSettingsToken CLASS = invertible("CLASS", StdArrangementTokenType.ENTRY_TYPE);
+ @NotNull public static final ArrangementSettingsToken ANONYMOUS_CLASS = invertible("ANONYMOUS_CLASS",
+ StdArrangementTokenType.ENTRY_TYPE);
+ @NotNull public static final ArrangementSettingsToken FIELD = invertible("FIELD", StdArrangementTokenType.ENTRY_TYPE);
+ @NotNull public static final ArrangementSettingsToken CONSTRUCTOR = invertible("CONSTRUCTOR", StdArrangementTokenType.ENTRY_TYPE);
+ @NotNull public static final ArrangementSettingsToken METHOD = invertible("METHOD", StdArrangementTokenType.ENTRY_TYPE);
+ @NotNull public static final ArrangementSettingsToken ENUM = invertible("ENUM", StdArrangementTokenType.ENTRY_TYPE);
+ @NotNull public static final ArrangementSettingsToken INTERFACE = invertible("INTERFACE", StdArrangementTokenType.ENTRY_TYPE);
+ @NotNull public static final ArrangementSettingsToken CONST = invertible("CONST", StdArrangementTokenType.ENTRY_TYPE);
+ @NotNull public static final ArrangementSettingsToken VAR = invertible("VAR", StdArrangementTokenType.ENTRY_TYPE);
+ @NotNull public static final ArrangementSettingsToken PROPERTY = invertible("PROPERTY", StdArrangementTokenType.ENTRY_TYPE);
+ @NotNull public static final ArrangementSettingsToken EVENT_HANDLER = invertible("EVENT_HANDLER", StdArrangementTokenType.ENTRY_TYPE);
+ @NotNull public static final ArrangementSettingsToken STATIC_INIT = invertible("STATIC_INIT", StdArrangementTokenType.ENTRY_TYPE);
+ @NotNull public static final ArrangementSettingsToken NAMESPACE = invertible("NAMESPACE", StdArrangementTokenType.ENTRY_TYPE);
+ @NotNull public static final ArrangementSettingsToken TRAIT = invertible("TRAIT", StdArrangementTokenType.ENTRY_TYPE);
+
+ // xml use only two entry types -> invertible tokens make no sense
@NotNull public static final ArrangementSettingsToken XML_TAG =
token("XML_TAG", "arrangement.settings.text.entry.type.xml.tag", StdArrangementTokenType.ENTRY_TYPE);
@NotNull public static final StdArrangementSettingsToken XML_ATTRIBUTE =
@@ -162,17 +171,17 @@ public class StdArrangementTokens {
}
}
public static class Modifier {
- @NotNull public static final ArrangementSettingsToken PUBLIC = token("PUBLIC", StdArrangementTokenType.MODIFIER);
- @NotNull public static final ArrangementSettingsToken PROTECTED = token("PROTECTED", StdArrangementTokenType.MODIFIER);
- @NotNull public static final ArrangementSettingsToken PRIVATE = token("PRIVATE", StdArrangementTokenType.MODIFIER);
- @NotNull public static final ArrangementSettingsToken PACKAGE_PRIVATE = token("PACKAGE_PRIVATE", StdArrangementTokenType.MODIFIER);
- @NotNull public static final ArrangementSettingsToken STATIC = token("STATIC", StdArrangementTokenType.MODIFIER);
- @NotNull public static final ArrangementSettingsToken FINAL = token("FINAL", StdArrangementTokenType.MODIFIER);
- @NotNull public static final ArrangementSettingsToken TRANSIENT = token("TRANSIENT", StdArrangementTokenType.MODIFIER);
- @NotNull public static final ArrangementSettingsToken VOLATILE = token("VOLATILE", StdArrangementTokenType.MODIFIER);
- @NotNull public static final ArrangementSettingsToken SYNCHRONIZED = token("SYNCHRONIZED", StdArrangementTokenType.MODIFIER);
- @NotNull public static final ArrangementSettingsToken ABSTRACT = token("ABSTRACT", StdArrangementTokenType.MODIFIER);
- @NotNull public static final ArrangementSettingsToken OVERRIDE = token("OVERRIDE", StdArrangementTokenType.MODIFIER);
+ @NotNull public static final ArrangementSettingsToken PUBLIC = invertible("PUBLIC", StdArrangementTokenType.MODIFIER);
+ @NotNull public static final ArrangementSettingsToken PROTECTED = invertible("PROTECTED", StdArrangementTokenType.MODIFIER);
+ @NotNull public static final ArrangementSettingsToken PRIVATE = invertible("PRIVATE", StdArrangementTokenType.MODIFIER);
+ @NotNull public static final ArrangementSettingsToken PACKAGE_PRIVATE = invertible("PACKAGE_PRIVATE", StdArrangementTokenType.MODIFIER);
+ @NotNull public static final ArrangementSettingsToken STATIC = invertible("STATIC", StdArrangementTokenType.MODIFIER);
+ @NotNull public static final ArrangementSettingsToken FINAL = invertible("FINAL", StdArrangementTokenType.MODIFIER);
+ @NotNull public static final ArrangementSettingsToken TRANSIENT = invertible("TRANSIENT", StdArrangementTokenType.MODIFIER);
+ @NotNull public static final ArrangementSettingsToken VOLATILE = invertible("VOLATILE", StdArrangementTokenType.MODIFIER);
+ @NotNull public static final ArrangementSettingsToken SYNCHRONIZED = invertible("SYNCHRONIZED", StdArrangementTokenType.MODIFIER);
+ @NotNull public static final ArrangementSettingsToken ABSTRACT = invertible("ABSTRACT", StdArrangementTokenType.MODIFIER);
+ @NotNull public static final ArrangementSettingsToken OVERRIDE = invertible("OVERRIDE", StdArrangementTokenType.MODIFIER);
private static final NotNullLazyValue> TOKENS = collectFields(Modifier.class);
private Modifier() {
diff --git a/platform/lang-api/src/com/intellij/psi/codeStyle/arrangement/std/StdInvertibleArrangementSettingsToken.java b/platform/lang-api/src/com/intellij/psi/codeStyle/arrangement/std/StdInvertibleArrangementSettingsToken.java
new file mode 100644
index 000000000000..3a1fbab38851
--- /dev/null
+++ b/platform/lang-api/src/com/intellij/psi/codeStyle/arrangement/std/StdInvertibleArrangementSettingsToken.java
@@ -0,0 +1,44 @@
+/*
+ * Copyright 2000-2014 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.psi.codeStyle.arrangement.std;
+
+import org.jetbrains.annotations.NonNls;
+import org.jetbrains.annotations.NotNull;
+
+/**
+ * @author Svetlana.Zemlyanskaya
+ */
+public class StdInvertibleArrangementSettingsToken extends StdArrangementSettingsToken implements InvertibleArrangementSettingsToken {
+ private static final String NOT = "not ";
+
+ private StdInvertibleArrangementSettingsToken(@NotNull String id,
+ @NotNull String uiName,
+ @NotNull StdArrangementTokenType tokenType) {
+ super(id, uiName, tokenType);
+ }
+
+ @NotNull
+ public static StdInvertibleArrangementSettingsToken invertibleTokenById(@NonNls @NotNull String id,
+ @NotNull StdArrangementTokenType tokenType) {
+ return new StdInvertibleArrangementSettingsToken(id, id.toLowerCase().replace("_", " "), tokenType);
+ }
+
+ @NotNull
+ @Override
+ public String getInvertedRepresentationValue() {
+ return NOT + getRepresentationValue();
+ }
+}
diff --git a/platform/lang-impl/src/com/intellij/application/options/GeneralCodeStylePanel.java b/platform/lang-impl/src/com/intellij/application/options/GeneralCodeStylePanel.java
index d0e1558abd41..a521067dbfd1 100644
--- a/platform/lang-impl/src/com/intellij/application/options/GeneralCodeStylePanel.java
+++ b/platform/lang-impl/src/com/intellij/application/options/GeneralCodeStylePanel.java
@@ -37,9 +37,9 @@ import com.intellij.openapi.util.text.StringUtil;
import com.intellij.psi.PsiFile;
import com.intellij.psi.codeStyle.CodeStyleSettings;
import com.intellij.ui.IdeBorderFactory;
+import com.intellij.ui.ScrollPaneFactory;
import com.intellij.ui.awt.RelativePoint;
import com.intellij.ui.components.JBLabel;
-import com.intellij.ui.components.JBScrollPane;
import org.jetbrains.annotations.NotNull;
import org.jetbrains.annotations.Nullable;
@@ -77,7 +77,7 @@ public class GeneralCodeStylePanel extends CodeStyleAbstractPanel {
private JPanel myAdditionalSettingsPanel;
private JCheckBox myAutodetectIndentsBox;
private final SmartIndentOptionsEditor myIndentOptionsEditor;
- private final JBScrollPane myScrollPane;
+ private final JScrollPane myScrollPane;
public GeneralCodeStylePanel(CodeStyleSettings settings) {
@@ -106,9 +106,7 @@ public class GeneralCodeStylePanel extends CodeStyleAbstractPanel {
ApplicationBundle.message("settings.code.style.general.formatter.marker.title"), true));
myMarkerOptionsPanel.setBorder(
IdeBorderFactory.createTitledBorder(ApplicationBundle.message("settings.code.style.general.formatter.marker.options.title"), true));
- myScrollPane = new JBScrollPane(myPanel,
- ScrollPaneConstants.VERTICAL_SCROLLBAR_AS_NEEDED, ScrollPaneConstants.HORIZONTAL_SCROLLBAR_NEVER);
- myScrollPane.setBorder(IdeBorderFactory.createEmptyBorder());
+ myScrollPane = ScrollPaneFactory.createScrollPane(myPanel, true);
myAdditionalSettingsPanel.setLayout(new VerticalFlowLayout(true, true));
myAdditionalSettingsPanel.removeAll();
diff --git a/platform/lang-impl/src/com/intellij/application/options/codeStyle/arrangement/component/AbstractArrangementUiComponent.java b/platform/lang-impl/src/com/intellij/application/options/codeStyle/arrangement/component/AbstractArrangementUiComponent.java
index ca508a8f86df..094e6c53e04a 100644
--- a/platform/lang-impl/src/com/intellij/application/options/codeStyle/arrangement/component/AbstractArrangementUiComponent.java
+++ b/platform/lang-impl/src/com/intellij/application/options/codeStyle/arrangement/component/AbstractArrangementUiComponent.java
@@ -175,4 +175,9 @@ public abstract class AbstractArrangementUiComponent implements ArrangementUiCom
}
protected abstract void doReset();
+
+ @Override
+ public boolean alwaysCanBeActive() {
+ return false;
+ }
}
diff --git a/platform/lang-impl/src/com/intellij/application/options/codeStyle/arrangement/component/ArrangementAndMatchConditionComponent.java b/platform/lang-impl/src/com/intellij/application/options/codeStyle/arrangement/component/ArrangementAndMatchConditionComponent.java
index 44b640dbea08..137519fc2742 100644
--- a/platform/lang-impl/src/com/intellij/application/options/codeStyle/arrangement/component/ArrangementAndMatchConditionComponent.java
+++ b/platform/lang-impl/src/com/intellij/application/options/codeStyle/arrangement/component/ArrangementAndMatchConditionComponent.java
@@ -16,7 +16,7 @@
package com.intellij.application.options.codeStyle.arrangement.component;
import com.intellij.application.options.codeStyle.arrangement.ArrangementConstants;
-import com.intellij.psi.codeStyle.arrangement.std.ArrangementStandardSettingsManager;
+import com.intellij.psi.codeStyle.arrangement.std.*;
import com.intellij.application.options.codeStyle.arrangement.match.ArrangementMatchNodeComponentFactory;
import com.intellij.openapi.util.text.StringUtil;
import com.intellij.psi.codeStyle.arrangement.match.StdArrangementMatchRule;
@@ -24,8 +24,6 @@ import com.intellij.psi.codeStyle.arrangement.model.ArrangementAtomMatchConditio
import com.intellij.psi.codeStyle.arrangement.model.ArrangementCompositeMatchCondition;
import com.intellij.psi.codeStyle.arrangement.model.ArrangementMatchCondition;
import com.intellij.psi.codeStyle.arrangement.model.ArrangementMatchConditionVisitor;
-import com.intellij.psi.codeStyle.arrangement.std.ArrangementSettingsToken;
-import com.intellij.psi.codeStyle.arrangement.std.ArrangementUiComponent;
import com.intellij.util.containers.ContainerUtilRt;
import com.intellij.util.ui.GridBag;
import com.intellij.util.ui.UIUtil;
@@ -265,6 +263,18 @@ public class ArrangementAndMatchConditionComponent extends JPanel implements Arr
}
}
+ @Override
+ public void handleMouseClickOnSelected() {
+ for (ArrangementUiComponent component : myComponents) {
+ component.handleMouseClickOnSelected();
+ }
+ }
+
+ @Override
+ public boolean alwaysCanBeActive() {
+ return false;
+ }
+
@Override
public String toString() {
return String.format("(%s)", StringUtil.join(myComponents, " and "));
diff --git a/platform/lang-impl/src/com/intellij/application/options/codeStyle/arrangement/component/ArrangementAtomMatchConditionComponent.java b/platform/lang-impl/src/com/intellij/application/options/codeStyle/arrangement/component/ArrangementAtomMatchConditionComponent.java
index f863088fc07b..d77225868c70 100644
--- a/platform/lang-impl/src/com/intellij/application/options/codeStyle/arrangement/component/ArrangementAtomMatchConditionComponent.java
+++ b/platform/lang-impl/src/com/intellij/application/options/codeStyle/arrangement/component/ArrangementAtomMatchConditionComponent.java
@@ -22,6 +22,7 @@ import com.intellij.application.options.codeStyle.arrangement.color.ArrangementC
import com.intellij.application.options.codeStyle.arrangement.util.InsetsPanel;
import com.intellij.openapi.actionSystem.impl.ActionButton;
import com.intellij.openapi.editor.markup.TextAttributes;
+import com.intellij.openapi.util.text.StringUtil;
import com.intellij.psi.codeStyle.arrangement.model.ArrangementAtomMatchCondition;
import com.intellij.psi.codeStyle.arrangement.std.*;
import com.intellij.ui.IdeBorderFactory;
@@ -97,10 +98,15 @@ public class ArrangementAtomMatchConditionComponent implements ArrangementUiComp
@Nullable private Rectangle myScreenBounds;
@Nullable private Listener myListener;
+ private boolean myInverted = false;
private boolean myEnabled = true;
private boolean mySelected;
private boolean myCloseButtonHovered;
+ // cached value for inverted atom condition, e.g. condition: 'static', opposite: 'not static'
+ @Nullable private ArrangementAtomMatchCondition myOppositeCondition;
+ @Nullable private String myInvertedText;
+
public ArrangementAtomMatchConditionComponent(@NotNull ArrangementStandardSettingsManager manager,
@NotNull ArrangementColorsProvider colorsProvider,
@NotNull ArrangementAtomMatchCondition condition,
@@ -117,7 +123,7 @@ public class ArrangementAtomMatchConditionComponent implements ArrangementUiComp
else {
myBorderStrategy = PREDEFINED_BORDER_STRATEGY;
}
- if (type.equals(condition.getValue())) {
+ if (type.equals(condition.getValue()) || condition.getValue() instanceof Boolean) {
myText = type.getRepresentationValue();
}
else if (StdArrangementTokenType.REG_EXP.is(type)) {
@@ -225,17 +231,27 @@ public class ArrangementAtomMatchConditionComponent implements ArrangementUiComp
if (myCloseButton != null) {
myCloseButton.setVisible(false);
}
+ setData(myCondition.getValue());
}
@NotNull
@Override
public ArrangementAtomMatchCondition getMatchCondition() {
+ if (myInverted == myCondition.getValue()) {
+ if (myOppositeCondition == null) {
+ myOppositeCondition = new ArrangementAtomMatchCondition(myCondition.getType(), !myInverted);
+ }
+ return myOppositeCondition;
+ }
return myCondition;
}
@Override
public void setData(@NotNull Object data) {
- // Do nothing
+ if (data instanceof Boolean && myCondition.getType() instanceof InvertibleArrangementSettingsToken) {
+ myInverted = !((Boolean)data);
+ updateComponentText(mySelected);
+ }
}
@NotNull
@@ -259,9 +275,7 @@ public class ArrangementAtomMatchConditionComponent implements ArrangementUiComp
public void setSelected(boolean selected) {
boolean notifyListener = selected != mySelected;
mySelected = selected;
- myTextControl.clear();
- TextAttributes attributes = myColorsProvider.getTextAttributes(myCondition.getType(), selected);
- myTextControl.append(myText, SimpleTextAttributes.fromTextAttributes(attributes));
+ TextAttributes attributes = updateComponentText(selected);
myBorder.setColor(myColorsProvider.getBorderColor(selected));
myBackgroundColor = attributes.getBackgroundColor();
if (notifyListener && myListener != null) {
@@ -269,6 +283,26 @@ public class ArrangementAtomMatchConditionComponent implements ArrangementUiComp
}
}
+ @NotNull
+ private TextAttributes updateComponentText(boolean selected) {
+ myTextControl.clear();
+ TextAttributes attributes = myColorsProvider.getTextAttributes(myCondition.getType(), selected);
+ myTextControl.append(getComponentText(), SimpleTextAttributes.fromTextAttributes(attributes));
+ return attributes;
+ }
+
+ private String getComponentText() {
+ if (myInverted) {
+ if (StringUtil.isEmpty(myInvertedText)) {
+ final ArrangementSettingsToken token = myCondition.getType();
+ assert token instanceof InvertibleArrangementSettingsToken;
+ myInvertedText = ((InvertibleArrangementSettingsToken)token).getInvertedRepresentationValue();
+ }
+ return myInvertedText;
+ }
+ return myText;
+ }
+
@Override
public boolean isEnabled() {
return myEnabled;
@@ -349,7 +383,7 @@ public class ArrangementAtomMatchConditionComponent implements ArrangementUiComp
@Override
public String toString() {
- return myText;
+ return getComponentText();
}
@NotNull
@@ -377,6 +411,7 @@ public class ArrangementAtomMatchConditionComponent implements ArrangementUiComp
@Override
public void reset() {
setSelected(false);
+ setData(true);
}
@Override
@@ -390,6 +425,19 @@ public class ArrangementAtomMatchConditionComponent implements ArrangementUiComp
myListener = listener;
}
+ @Override
+ public void handleMouseClickOnSelected() {
+ if (myInverted) {
+ setSelected(false);
+ }
+ setData(myInverted);
+ }
+
+ @Override
+ public boolean alwaysCanBeActive() {
+ return myInverted;
+ }
+
private interface BorderStrategy {
RoundedLineBorder create();
void setup(@NotNull Graphics2D g);
diff --git a/platform/lang-impl/src/com/intellij/application/options/codeStyle/arrangement/component/ArrangementCheckBoxUiComponent.java b/platform/lang-impl/src/com/intellij/application/options/codeStyle/arrangement/component/ArrangementCheckBoxUiComponent.java
index 214b036ce845..053585c7c854 100644
--- a/platform/lang-impl/src/com/intellij/application/options/codeStyle/arrangement/component/ArrangementCheckBoxUiComponent.java
+++ b/platform/lang-impl/src/com/intellij/application/options/codeStyle/arrangement/component/ArrangementCheckBoxUiComponent.java
@@ -115,11 +115,16 @@ public class ArrangementCheckBoxUiComponent extends AbstractArrangementUiCompone
@Override
public void setSelected(boolean selected) {
- myCheckBox.setSelected(selected);
+ myCheckBox.setSelected(selected);
}
@Override
public int getBaselineToUse(int width, int height) {
return myTextLabel.getBaseline(width, height);
}
+
+ @Override
+ public void handleMouseClickOnSelected() {
+ setSelected(false);
+ }
}
diff --git a/platform/lang-impl/src/com/intellij/application/options/codeStyle/arrangement/component/ArrangementComboBoxUiComponent.java b/platform/lang-impl/src/com/intellij/application/options/codeStyle/arrangement/component/ArrangementComboBoxUiComponent.java
index cad3fc88ca22..9cfce2abc0ab 100644
--- a/platform/lang-impl/src/com/intellij/application/options/codeStyle/arrangement/component/ArrangementComboBoxUiComponent.java
+++ b/platform/lang-impl/src/com/intellij/application/options/codeStyle/arrangement/component/ArrangementComboBoxUiComponent.java
@@ -123,4 +123,9 @@ public class ArrangementComboBoxUiComponent extends AbstractArrangementUiCompone
public int getBaselineToUse(int width, int height) {
return -1;
}
+
+ @Override
+ public void handleMouseClickOnSelected() {
+ setSelected(false);
+ }
}
diff --git a/platform/lang-impl/src/com/intellij/application/options/codeStyle/arrangement/component/ArrangementLabelUiComponent.java b/platform/lang-impl/src/com/intellij/application/options/codeStyle/arrangement/component/ArrangementLabelUiComponent.java
index 9d89b728e40d..bdb7503f53c1 100644
--- a/platform/lang-impl/src/com/intellij/application/options/codeStyle/arrangement/component/ArrangementLabelUiComponent.java
+++ b/platform/lang-impl/src/com/intellij/application/options/codeStyle/arrangement/component/ArrangementLabelUiComponent.java
@@ -85,4 +85,9 @@ public class ArrangementLabelUiComponent extends AbstractArrangementUiComponent
public int getBaselineToUse(int width, int height) {
return myLabel.getBaseline(width, height);
}
+
+ @Override
+ public void handleMouseClickOnSelected() {
+ setSelected(false);
+ }
}
diff --git a/platform/lang-impl/src/com/intellij/application/options/codeStyle/arrangement/component/ArrangementTextFieldUiComponent.java b/platform/lang-impl/src/com/intellij/application/options/codeStyle/arrangement/component/ArrangementTextFieldUiComponent.java
index dae8d6ba8a88..0e93b8a97ba1 100644
--- a/platform/lang-impl/src/com/intellij/application/options/codeStyle/arrangement/component/ArrangementTextFieldUiComponent.java
+++ b/platform/lang-impl/src/com/intellij/application/options/codeStyle/arrangement/component/ArrangementTextFieldUiComponent.java
@@ -114,7 +114,9 @@ public class ArrangementTextFieldUiComponent extends AbstractArrangementUiCompon
@Override
public void setData(@NotNull Object data) {
- myTextField.setText(data.toString());
+ if (data instanceof String) {
+ myTextField.setText(data.toString());
+ }
}
@Override
@@ -126,4 +128,9 @@ public class ArrangementTextFieldUiComponent extends AbstractArrangementUiCompon
public int getBaselineToUse(int width, int height) {
return myTextField.getBaseline(width, height);
}
+
+ @Override
+ public void handleMouseClickOnSelected() {
+ setSelected(false);
+ }
}
diff --git a/platform/lang-impl/src/com/intellij/application/options/codeStyle/arrangement/match/ArrangementMatchingRuleEditor.java b/platform/lang-impl/src/com/intellij/application/options/codeStyle/arrangement/match/ArrangementMatchingRuleEditor.java
index 4f2ed17842e2..0c51dd5fc0ea 100644
--- a/platform/lang-impl/src/com/intellij/application/options/codeStyle/arrangement/match/ArrangementMatchingRuleEditor.java
+++ b/platform/lang-impl/src/com/intellij/application/options/codeStyle/arrangement/match/ArrangementMatchingRuleEditor.java
@@ -378,7 +378,8 @@ public class ArrangementMatchingRuleEditor extends JPanel implements Arrangement
// don't allow to remove start/end section indication
final Set mutexes = ArrangementSectionRuleManager.getSectionMutexes();
if (!mutexes.contains(component.getToken())) {
- removeCondition(component);
+ component.handleMouseClickOnSelected();
+ refreshConditions();
}
}
else {
@@ -417,7 +418,7 @@ public class ArrangementMatchingRuleEditor extends JPanel implements Arrangement
continue;
}
ArrangementUiComponent c = myComponents.get(key);
- if (c != null && c.isEnabled()) {
+ if (c != null && c.isEnabled() && !c.alwaysCanBeActive()) {
removeCondition(c);
}
}
@@ -425,6 +426,7 @@ public class ArrangementMatchingRuleEditor extends JPanel implements Arrangement
private void removeCondition(@NotNull ArrangementUiComponent component) {
component.setSelected(false);
+ component.setData(true);
refreshConditions();
}
diff --git a/platform/lang-impl/src/com/intellij/application/options/codeStyle/arrangement/util/ArrangementListRowDecorator.java b/platform/lang-impl/src/com/intellij/application/options/codeStyle/arrangement/util/ArrangementListRowDecorator.java
index 5bbba9eb8a7c..897c9cd22fd3 100644
--- a/platform/lang-impl/src/com/intellij/application/options/codeStyle/arrangement/util/ArrangementListRowDecorator.java
+++ b/platform/lang-impl/src/com/intellij/application/options/codeStyle/arrangement/util/ArrangementListRowDecorator.java
@@ -280,6 +280,16 @@ public class ArrangementListRowDecorator extends JPanel implements ArrangementUi
myDelegate.setListener(listener);
}
+ @Override
+ public void handleMouseClickOnSelected() {
+ myDelegate.handleMouseClickOnSelected();
+ }
+
+ @Override
+ public boolean alwaysCanBeActive() {
+ return false;
+ }
+
@Override
public String toString() {
return "list row decorator for " + myDelegate.toString();
diff --git a/platform/lang-impl/src/com/intellij/codeInsight/daemon/impl/PsiChangeHandler.java b/platform/lang-impl/src/com/intellij/codeInsight/daemon/impl/PsiChangeHandler.java
index 661e9bed82da..f5f698e4a40a 100644
--- a/platform/lang-impl/src/com/intellij/codeInsight/daemon/impl/PsiChangeHandler.java
+++ b/platform/lang-impl/src/com/intellij/codeInsight/daemon/impl/PsiChangeHandler.java
@@ -40,12 +40,12 @@ import com.intellij.psi.impl.PsiDocumentManagerImpl;
import com.intellij.psi.impl.PsiDocumentTransactionListener;
import com.intellij.psi.impl.PsiTreeChangeEventImpl;
import com.intellij.util.SmartList;
-import com.intellij.util.containers.ContainerUtil;
import com.intellij.util.messages.MessageBusConnection;
import gnu.trove.THashMap;
import org.jetbrains.annotations.NotNull;
import org.jetbrains.annotations.Nullable;
+import java.util.Collections;
import java.util.List;
import java.util.Map;
@@ -100,7 +100,7 @@ public class PsiChangeHandler extends PsiTreeChangeAdapter implements Disposable
}
private void updateChangesForDocument(@NotNull final Document document) {
- if (DaemonListeners.isUnderIgnoredAction(null)) return;
+ if (DaemonListeners.isUnderIgnoredAction(null) || myProject.isDisposed()) return;
List> toUpdate = changedElements.get(document);
if (toUpdate == null) {
// The document has been changed, but psi hasn't
@@ -111,7 +111,7 @@ public class PsiChangeHandler extends PsiTreeChangeAdapter implements Disposable
PsiElement file = PsiDocumentManager.getInstance(myProject).getCachedPsiFile(document);
if (file == null) return;
- toUpdate = ContainerUtil.newArrayList(Pair.create(file, true));
+ toUpdate = Collections.singletonList(Pair.create(file, true));
}
Application application = ApplicationManager.getApplication();
final Editor editor = FileEditorManager.getInstance(myProject).getSelectedTextEditor();
diff --git a/platform/lang-impl/src/com/intellij/codeInsight/intention/impl/QuickEditAction.java b/platform/lang-impl/src/com/intellij/codeInsight/intention/impl/QuickEditAction.java
index d168002f97a7..5e4f9b315042 100644
--- a/platform/lang-impl/src/com/intellij/codeInsight/intention/impl/QuickEditAction.java
+++ b/platform/lang-impl/src/com/intellij/codeInsight/intention/impl/QuickEditAction.java
@@ -18,6 +18,7 @@ package com.intellij.codeInsight.intention.impl;
import com.intellij.codeInsight.intention.IntentionAction;
import com.intellij.codeInsight.intention.LowPriorityAction;
import com.intellij.injected.editor.DocumentWindow;
+import com.intellij.injected.editor.DocumentWindowImpl;
import com.intellij.lang.Language;
import com.intellij.lang.injection.InjectedLanguageManager;
import com.intellij.openapi.application.ApplicationManager;
@@ -106,7 +107,7 @@ public class QuickEditAction implements IntentionAction, LowPriorityAction {
if (!ApplicationManager.getApplication().isUnitTestMode()) {
DocumentWindow documentWindow = InjectedLanguageUtil.getDocumentWindow(injectedFile);
if (documentWindow != null) {
- handler.navigate(documentWindow.hostToInjected(offset));
+ handler.navigate(((DocumentWindowImpl)documentWindow).hostToUnescaped(offset));
}
}
return handler;
diff --git a/platform/lang-impl/src/com/intellij/injected/editor/DocumentWindowImpl.java b/platform/lang-impl/src/com/intellij/injected/editor/DocumentWindowImpl.java
index 724de4f480ec..3ed4e0a16022 100644
--- a/platform/lang-impl/src/com/intellij/injected/editor/DocumentWindowImpl.java
+++ b/platform/lang-impl/src/com/intellij/injected/editor/DocumentWindowImpl.java
@@ -648,6 +648,27 @@ public class DocumentWindowImpl extends UserDataHolderBase implements Disposable
@Override
public int hostToInjected(int hostOffset) {
+ synchronized (myLock) {
+ Segment hostRangeMarker = myShreds.get(0).getHostRangeMarker();
+ if (hostRangeMarker == null || hostOffset < hostRangeMarker.getStartOffset()) return myShreds.get(0).getPrefix().length();
+ int offset = 0;
+ for (int i = 0; i < myShreds.size(); i++) {
+ offset += myShreds.get(i).getPrefix().length();
+ Segment currentRange = myShreds.get(i).getHostRangeMarker();
+ if (currentRange == null) continue;
+ Segment nextRange = i == myShreds.size() - 1 ? null : myShreds.get(i + 1).getHostRangeMarker();
+ if (nextRange == null || hostOffset < nextRange.getStartOffset()) {
+ if (hostOffset >= currentRange.getEndOffset()) hostOffset = currentRange.getEndOffset();
+ return offset + hostOffset - currentRange.getStartOffset();
+ }
+ offset += currentRange.getEndOffset() - currentRange.getStartOffset();
+ offset += myShreds.get(i).getSuffix().length();
+ }
+ return getTextLength() - myShreds.get(myShreds.size() - 1).getSuffix().length();
+ }
+ }
+
+ public int hostToUnescaped(int hostOffset) {
synchronized (myLock) {
Segment hostRangeMarker = myShreds.get(0).getHostRangeMarker();
if (hostRangeMarker == null || hostOffset < hostRangeMarker.getStartOffset()) return myShreds.get(0).getPrefix().length();
diff --git a/platform/platform-impl/src/com/intellij/openapi/application/impl/ApplicationImpl.java b/platform/platform-impl/src/com/intellij/openapi/application/impl/ApplicationImpl.java
index 67f868deda91..cf87cd8c24d6 100644
--- a/platform/platform-impl/src/com/intellij/openapi/application/impl/ApplicationImpl.java
+++ b/platform/platform-impl/src/com/intellij/openapi/application/impl/ApplicationImpl.java
@@ -594,6 +594,7 @@ public class ApplicationImpl extends PlatformComponentManagerImpl implements App
boolean writeAccessAllowed = isInsideWriteActionEDTOnly();
if (writeAccessAllowed // Disallow running process in separate thread from under write action.
// The thread will deadlock trying to get read action otherwise.
+ || isHeadlessEnvironment() && !isUnitTestMode()
) {
LOG.debug("Starting process with progress from within write action makes no sense");
try {
diff --git a/platform/platform-impl/src/com/intellij/openapi/options/newEditor/SpotlightPainter.java b/platform/platform-impl/src/com/intellij/openapi/options/newEditor/SpotlightPainter.java
index 374b4d10374d..61dc1deae6a1 100644
--- a/platform/platform-impl/src/com/intellij/openapi/options/newEditor/SpotlightPainter.java
+++ b/platform/platform-impl/src/com/intellij/openapi/options/newEditor/SpotlightPainter.java
@@ -80,19 +80,17 @@ abstract class SpotlightPainter extends AbstractPainter {
myGlassPanel.clear();
String text = filter.getFilterText();
myVisible = !text.isEmpty();
- if (myVisible) {
- try {
- SearchableConfigurable searchable = new SearchableConfigurable.Delegate(configurable);
- SearchUtil.lightOptions(searchable, component, text, myGlassPanel).run();
- Runnable search = searchable.enableSearch(text);
- if (search != null && !filter.contains(configurable) && !text.equals(myConfigurableOption.get(configurable))) {
- search.run();
- }
- }
- finally {
- myConfigurableOption.put(configurable, text);
+ try {
+ SearchableConfigurable searchable = new SearchableConfigurable.Delegate(configurable);
+ SearchUtil.lightOptions(searchable, component, text, myGlassPanel).run();
+ Runnable search = searchable.enableSearch(text); // execute for empty string too
+ if (search != null && !filter.contains(configurable) && !text.equals(myConfigurableOption.get(configurable))) {
+ search.run();
}
}
+ finally {
+ myConfigurableOption.put(configurable, text);
+ }
}
else if (!ApplicationManager.getApplication().isUnitTestMode()) {
updateLater();
diff --git a/platform/testFramework/testSrc/com/intellij/psi/codeStyle/arrangement/AbstractRearrangerTest.java b/platform/testFramework/testSrc/com/intellij/psi/codeStyle/arrangement/AbstractRearrangerTest.java
index 92c2723ce3b5..b503f5cf1e59 100644
--- a/platform/testFramework/testSrc/com/intellij/psi/codeStyle/arrangement/AbstractRearrangerTest.java
+++ b/platform/testFramework/testSrc/com/intellij/psi/codeStyle/arrangement/AbstractRearrangerTest.java
@@ -142,6 +142,10 @@ public abstract class AbstractRearrangerTest extends LightPlatformCodeInsightFix
return new ArrangementAtomMatchCondition(token);
}
+ protected static ArrangementAtomMatchCondition atom(@NotNull ArrangementSettingsToken token, boolean included) {
+ return new ArrangementAtomMatchCondition(token, included);
+ }
+
@NotNull
protected static ArrangementAtomMatchCondition atom(@NotNull String nameFilter) {
return new ArrangementAtomMatchCondition(StdArrangementTokens.Regexp.NAME, nameFilter);
diff --git a/platform/util/src/com/intellij/openapi/util/io/FileUtil.java b/platform/util/src/com/intellij/openapi/util/io/FileUtil.java
index 4324deee35d4..d7d632377ab4 100644
--- a/platform/util/src/com/intellij/openapi/util/io/FileUtil.java
+++ b/platform/util/src/com/intellij/openapi/util/io/FileUtil.java
@@ -383,10 +383,10 @@ public class FileUtil extends FileUtilRt {
@Nullable
private static File renameToTempFileOrDelete(@NotNull File file) {
- final File tempDir = new File(getTempDirectory());
+ String tempDir = getTempDirectory();
boolean isSameDrive = true;
if (SystemInfo.isWindows) {
- String tempDirDrive = tempDir.getAbsolutePath().substring(0, 2);
+ String tempDirDrive = tempDir.substring(0, 2);
String fileDrive = file.getAbsolutePath().substring(0, 2);
isSameDrive = tempDirDrive.equalsIgnoreCase(fileDrive);
}
@@ -405,7 +405,7 @@ public class FileUtil extends FileUtilRt {
return null;
}
- private static File getTempFile(@NotNull String originalFileName, @NotNull File parent) {
+ private static File getTempFile(@NotNull String originalFileName, @NotNull String parent) {
int randomSuffix = (int)(System.currentTimeMillis() % 1000);
for (int i = randomSuffix; ; i++) {
@NonNls String name = "___" + originalFileName + i + ASYNC_DELETE_EXTENSION;
diff --git a/platform/util/src/com/intellij/util/containers/ContainerUtil.java b/platform/util/src/com/intellij/util/containers/ContainerUtil.java
index d61dc2424be3..5dd3697d4e32 100644
--- a/platform/util/src/com/intellij/util/containers/ContainerUtil.java
+++ b/platform/util/src/com/intellij/util/containers/ContainerUtil.java
@@ -2220,7 +2220,7 @@ public class ContainerUtil extends ContainerUtilRt {
@NotNull
@Contract(pure=true)
public static ConcurrentIntObjectMap createConcurrentIntObjectMap() {
- return new ConcurrentIntObjectHashMap();
+ return new StripedLockIntObjectConcurrentHashMap();
}
@NotNull
diff --git a/platform/vcs-impl/src/com/intellij/openapi/vcs/changes/ChangeListManagerImpl.java b/platform/vcs-impl/src/com/intellij/openapi/vcs/changes/ChangeListManagerImpl.java
index 87d39a539254..1947e8c36bc1 100644
--- a/platform/vcs-impl/src/com/intellij/openapi/vcs/changes/ChangeListManagerImpl.java
+++ b/platform/vcs-impl/src/com/intellij/openapi/vcs/changes/ChangeListManagerImpl.java
@@ -31,6 +31,7 @@ import com.intellij.openapi.progress.ProgressIndicator;
import com.intellij.openapi.project.DumbAwareRunnable;
import com.intellij.openapi.project.Project;
import com.intellij.openapi.roots.ModuleRootManager;
+import com.intellij.openapi.roots.ProjectFileIndex;
import com.intellij.openapi.roots.impl.DirectoryIndexExcludePolicy;
import com.intellij.openapi.ui.MessageType;
import com.intellij.openapi.ui.Messages;
@@ -328,8 +329,15 @@ public class ChangeListManagerImpl extends ChangeListManagerEx implements Projec
}
}
+ ProjectFileIndex fileIndex = ProjectFileIndex.SERVICE.getInstance(myProject);
+ VirtualFileManager virtualFileManager = VirtualFileManager.getInstance();
for (Module module : ModuleManager.getInstance(myProject).getModules()) {
for (String url : ModuleRootManager.getInstance(module).getExcludeRootUrls()) {
+ VirtualFile file = virtualFileManager.findFileByUrl(url);
+ if (file != null && !fileIndex.isExcluded(file)) {
+ //root is included into some inner module so it shouldn't be ignored
+ continue;
+ }
addDirectoryToIgnoreImplicitly(VfsUtilCore.urlToPath(url));
}
}
diff --git a/platform/vcs-impl/testSrc/com/intellij/openapi/vcs/changes/ConvertExcludedToIgnoredTest.java b/platform/vcs-impl/testSrc/com/intellij/openapi/vcs/changes/ConvertExcludedToIgnoredTest.java
index 4ec5ea4bcdad..e2721e3aeb8d 100644
--- a/platform/vcs-impl/testSrc/com/intellij/openapi/vcs/changes/ConvertExcludedToIgnoredTest.java
+++ b/platform/vcs-impl/testSrc/com/intellij/openapi/vcs/changes/ConvertExcludedToIgnoredTest.java
@@ -1,5 +1,6 @@
package com.intellij.openapi.vcs.changes;
+import com.intellij.openapi.module.ModuleType;
import com.intellij.openapi.project.Project;
import com.intellij.openapi.roots.CompilerProjectExtension;
import com.intellij.openapi.vfs.VirtualFile;
@@ -71,6 +72,14 @@ public class ConvertExcludedToIgnoredTest extends PlatformTestCase {
assertIgnored(excluded);
}
+ public void testDoNotIgnoreInnerModuleExplicitlyMarkedAsExcludedFromOuterModule() throws IOException {
+ VirtualFile inner = createChildDirectory(myContentRoot, "inner");
+ PsiTestUtil.addModule(myProject, ModuleType.EMPTY, "inner", inner);
+ PsiTestUtil.addExcludedRoot(myModule, inner);
+ getChangeListManager().convertExcludedToIgnored();
+ assertFalse(getChangeListManager().isIgnoredFile(inner));
+ }
+
private void assertIgnored(VirtualFile... ignoredDirs) {
assertIgnoredDirectories(getProject(), ignoredDirs);
}
diff --git a/plugins/git4idea/src/git4idea/checkin/GitCheckinEnvironment.java b/plugins/git4idea/src/git4idea/checkin/GitCheckinEnvironment.java
index 705e40384c9a..9f4e77af6c5a 100644
--- a/plugins/git4idea/src/git4idea/checkin/GitCheckinEnvironment.java
+++ b/plugins/git4idea/src/git4idea/checkin/GitCheckinEnvironment.java
@@ -576,9 +576,10 @@ public class GitCheckinEnvironment implements CheckinEnvironment {
private class GitCheckinOptions extends DvcsCommitAdditionalComponent implements CheckinChangeListSpecificComponent {
private final GitVcs myVcs;
- private final ComboBox myAuthor;
+ private final ComboBox myAuthorField;
- private Date myAuthorDate;
+ @Nullable private Date myAuthorDate;
+ @Nullable private String myAuthor;
GitCheckinOptions(@NotNull final Project project, @NotNull CheckinProjectPanel panel) {
super(project, panel);
@@ -606,27 +607,27 @@ public class GitCheckinEnvironment implements CheckinEnvironment {
List list = new ArrayList(authors);
Collections.sort(list);
- myAuthor = new ComboBox(ArrayUtil.toObjectArray(list)) {
+ myAuthorField = new ComboBox(ArrayUtil.toObjectArray(list)) {
@Override
public void addNotify() {
super.addNotify();
// adding in addNotify to make sure the editor is ready for further customization
- StringComboboxEditor comboboxEditor = new StringComboboxEditor(project, FileTypes.PLAIN_TEXT, myAuthor, true);
- myAuthor.setEditor(comboboxEditor);
+ StringComboboxEditor comboboxEditor = new StringComboboxEditor(project, FileTypes.PLAIN_TEXT, myAuthorField, true);
+ myAuthorField.setEditor(comboboxEditor);
EditorEx editor = (EditorEx)comboboxEditor.getEditor();
assert editor != null;
SpellCheckingEditorCustomization.getInstance(false).customize(editor);
+
+ myAuthorField.insertItemAt(myAuthor == null ? "" : myAuthor, 0);
+ myAuthorField.setSelectedIndex(0);
}
};
- myAuthor.setMinimumAndPreferredWidth(100);
-
- myAuthor.insertItemAt("", 0);
- myAuthor.setSelectedItem("");
- myAuthor.setEditable(true);
- authorLabel.setLabelFor(myAuthor);
- myAuthor.setToolTipText(GitBundle.getString("commit.author.tooltip"));
- myPanel.add(myAuthor, c);
+ myAuthorField.setMinimumAndPreferredWidth(100);
+ myAuthorField.setEditable(true);
+ authorLabel.setLabelFor(myAuthorField);
+ myAuthorField.setToolTipText(GitBundle.getString("commit.author.tooltip"));
+ myPanel.add(myAuthorField, c);
}
@Override
@@ -667,13 +668,14 @@ public class GitCheckinEnvironment implements CheckinEnvironment {
@Override
public void refresh() {
super.refresh();
- myAuthor.setSelectedItem("");
+ myAuthor = null;
+ myAuthorDate = null;
reset();
}
@Override
public void saveState() {
- String author = (String)myAuthor.getEditor().getItem();
+ String author = (String)myAuthorField.getEditor().getItem();
if (StringUtil.isEmptyOrSpaces(author)) {
myNextCommitAuthor = null;
}
@@ -695,9 +697,8 @@ public class GitCheckinEnvironment implements CheckinEnvironment {
Object data = list.getData();
if (data instanceof VcsFullCommitDetails) {
VcsFullCommitDetails commit = (VcsFullCommitDetails)data;
- String author = String.format("%s <%s>", commit.getAuthor().getName(), commit.getAuthor().getEmail());
- myAuthor.getEditor().setItem(author);
- myAuthorDate = new Date(commit.getTimestamp());
+ myAuthor = String.format("%s <%s>", commit.getAuthor().getName(), commit.getAuthor().getEmail());
+ myAuthorDate = new Date(commit.getAuthorTime());
}
}
}
diff --git a/plugins/junit/src/com/intellij/execution/junit/JUnitConfiguration.java b/plugins/junit/src/com/intellij/execution/junit/JUnitConfiguration.java
index 0b7ab14a151d..d1edefd03f21 100644
--- a/plugins/junit/src/com/intellij/execution/junit/JUnitConfiguration.java
+++ b/plugins/junit/src/com/intellij/execution/junit/JUnitConfiguration.java
@@ -310,7 +310,7 @@ public class JUnitConfiguration extends ModuleBasedConfiguration tests = new LinkedHashSet();
+ final LinkedHashSet tests = new LinkedHashSet();
for (Object o : patternsElement.getChildren(PATTERN_EL_NAME)) {
Element patternElement = (Element)o;
tests.add(patternElement.getAttributeValue(TEST_CLASS_ATT_NAME));
@@ -403,7 +403,7 @@ public class JUnitConfiguration extends ModuleBasedConfiguration classes, PsiMethod method) {
myData.TEST_OBJECT = TEST_PATTERN;
- final Set patterns = new HashSet();
+ final LinkedHashSet patterns = new LinkedHashSet();
final String methodSufiix;
if (method != null) {
myData.METHOD_NAME = method.getName();
@@ -437,7 +437,7 @@ public class JUnitConfiguration extends ModuleBasedConfiguration myPattern = new LinkedHashSet();
+ private LinkedHashSet myPattern = new LinkedHashSet();
//iws/ipr compatibility
public String ENV_VARIABLES;
private Map myEnvs = new LinkedHashMap();
@@ -581,7 +581,7 @@ public class JUnitConfiguration extends ModuleBasedConfiguration pattern) {
+ public void setPatterns(LinkedHashSet pattern) {
myPattern = pattern;
}
diff --git a/plugins/junit/src/com/intellij/execution/junit/TestObject.java b/plugins/junit/src/com/intellij/execution/junit/TestObject.java
index e1b74d5452ef..eb9de875c346 100644
--- a/plugins/junit/src/com/intellij/execution/junit/TestObject.java
+++ b/plugins/junit/src/com/intellij/execution/junit/TestObject.java
@@ -509,18 +509,18 @@ public abstract class TestObject implements JavaCommandLine {
testNames.add(name);
}
}
+ final JUnitConfiguration.Data data = myConfiguration.getPersistentData();
if (perModule != null) {
for (List perModuleClasses : perModule.values()) {
Collections.sort(perModuleClasses);
testNames.addAll(perModuleClasses);
}
}
- else {
+ else if (JUnitConfiguration.TEST_PACKAGE.equals(data.TEST_OBJECT)) {
Collections.sort(testNames); //sort tests in FQN order
}
- final JUnitConfiguration.Data data = myConfiguration.getPersistentData();
- final String category = data.TEST_OBJECT == JUnitConfiguration.TEST_CATEGORY ? data.getCategory() : "";
+ final String category = JUnitConfiguration.TEST_CATEGORY.equals(data.TEST_OBJECT) ? data.getCategory() : "";
JUnitStarter.printClassesList(testNames, packageName, category, myTempFile);
if (perModule != null && perModule.size() > 1) {
diff --git a/plugins/testng/src/com/theoryinpractice/testng/configuration/SearchingForTestsTask.java b/plugins/testng/src/com/theoryinpractice/testng/configuration/SearchingForTestsTask.java
index 8358fcd253dd..ccc820a83817 100644
--- a/plugins/testng/src/com/theoryinpractice/testng/configuration/SearchingForTestsTask.java
+++ b/plugins/testng/src/com/theoryinpractice/testng/configuration/SearchingForTestsTask.java
@@ -83,7 +83,7 @@ public class SearchingForTestsTask extends Task.Backgroundable {
myServerSocket = serverSocket;
myConfig = config;
myTempFile = tempFile;
- myClasses = new HashMap>();
+ myClasses = new LinkedHashMap>();
}
public void run(@NotNull ProgressIndicator indicator) {
@@ -190,13 +190,13 @@ public class SearchingForTestsTask extends Task.Backgroundable {
}
private void composeTestSuiteFromClasses() {
- Map> map = new HashMap>();
+ Map> map = new LinkedHashMap>();
final boolean findTestMethodsForClass = shouldSearchForTestMethods();
for (final Map.Entry> entry : myClasses.entrySet()) {
final Collection depMethods = entry.getValue();
- Collection methods = new HashSet(depMethods.size());
+ Collection methods = new LinkedHashSet(depMethods.size());
for (PsiMethod method : depMethods) {
methods.add(method.getName());
}
@@ -523,7 +523,7 @@ public class SearchingForTestsTask extends Task.Backgroundable {
final Set alreadyMarkedToBeChecked,
@Nullable final PsiClass... classes) {
if (classes != null && classes.length > 0) {
- final Set groupDependencies = new HashSet();
+ final Set groupDependencies = new LinkedHashSet();
TestNGUtil.collectAnnotationValues(groupDependencies, "dependsOnGroups", methods, classes);
final Set membersToCheckNow = new LinkedHashSet();
if (!groupDependencies.isEmpty()) {
@@ -574,7 +574,7 @@ public class SearchingForTestsTask extends Task.Backgroundable {
final PsiClass... classes) {
final PsiClass[] psiClasses;
if (methods != null && methods.length > 0) {
- final Set containingClasses = new HashSet();
+ final Set containingClasses = new LinkedHashSet();
for (PsiMethod method : methods) {
containingClasses.add(method.getContainingClass());
}
@@ -583,7 +583,7 @@ public class SearchingForTestsTask extends Task.Backgroundable {
psiClasses = classes;
}
for (final PsiClass containingClass : psiClasses) {
- final Set testMethodDependencies = new HashSet();
+ final Set testMethodDependencies = new LinkedHashSet();
TestNGUtil.collectAnnotationValues(testMethodDependencies, "dependsOnMethods", methods, containingClass);
if (!testMethodDependencies.isEmpty()) {
ApplicationManager.getApplication().runReadAction(new Runnable() {
diff --git a/plugins/testng/src/com/theoryinpractice/testng/configuration/TestNGConfiguration.java b/plugins/testng/src/com/theoryinpractice/testng/configuration/TestNGConfiguration.java
index cc87a11d2e3c..70b5693be574 100644
--- a/plugins/testng/src/com/theoryinpractice/testng/configuration/TestNGConfiguration.java
+++ b/plugins/testng/src/com/theoryinpractice/testng/configuration/TestNGConfiguration.java
@@ -269,7 +269,7 @@ public class TestNGConfiguration extends ModuleBasedConfiguration patterns = new LinkedHashSet();
+ LinkedHashSet patterns = new LinkedHashSet();
for (PsiClass pattern : classes) {
patterns.add(JavaExecutionUtil.getRuntimeQualifiedName(pattern) + suffix);
}
@@ -373,7 +373,7 @@ public class TestNGConfiguration extends ModuleBasedConfiguration tests = new LinkedHashSet();
+ final LinkedHashSet tests = new LinkedHashSet();
for (Object o : patternsElement.getChildren(PATTERN_EL_NAME)) {
Element patternElement = (Element)o;
tests.add(patternElement.getAttributeValue(TEST_CLASS_ATT_NAME));
diff --git a/plugins/testng/src/com/theoryinpractice/testng/model/TestData.java b/plugins/testng/src/com/theoryinpractice/testng/model/TestData.java
index b40ab4c3ef03..2a75977483bb 100644
--- a/plugins/testng/src/com/theoryinpractice/testng/model/TestData.java
+++ b/plugins/testng/src/com/theoryinpractice/testng/model/TestData.java
@@ -57,7 +57,7 @@ public class TestData implements Cloneable
public List TEST_LISTENERS = new ArrayList();
public boolean USE_DEFAULT_REPORTERS = false;
public String PROPERTIES_FILE;
- private Set myPatterns = new LinkedHashSet();
+ private LinkedHashSet myPatterns = new LinkedHashSet();
public TestData() {
TEST_OBJECT = TestType.CLASS.getType();
@@ -168,7 +168,7 @@ public class TestData implements Cloneable
data.USE_DEFAULT_REPORTERS = USE_DEFAULT_REPORTERS;
data.ENVS = new LinkedHashMap(ENVS);
- data.myPatterns = new HashSet();
+ data.myPatterns = new LinkedHashSet();
data.myPatterns.addAll(myPatterns);
data.setScope(getScope());
return data;
@@ -251,7 +251,7 @@ public class TestData implements Cloneable
return myPatterns;
}
- public void setPatterns(Set set) {
+ public void setPatterns(LinkedHashSet set) {
myPatterns = set;
}
}
diff --git a/python/pluginResources/META-INF/plugin.xml b/python/pluginResources/META-INF/plugin.xml
index 4539edaa107b..3d8550e82b34 100644
--- a/python/pluginResources/META-INF/plugin.xml
+++ b/python/pluginResources/META-INF/plugin.xml
@@ -4,7 +4,7 @@
PythonCore
Python Community Edition
-
+
= 2 && "install".equals(args[0])) {
- String destFolder = args[1];
+ // install [--exit0]
+ int nextArg = 1;
+
+ // Default install exit code is SwingUpdaterUI.RESULT_REQUIRES_RESTART (42) unless overridden to be 0.
+ // This is used by testUI/build.gradle as gradle expects a javaexec to exit with code 0.
+ boolean useExitCode0 = false;
+ if (args[nextArg].equals("--exit0")) {
+ useExitCode0 = true;
+ nextArg++;
+ }
+
+ String destFolder = args[nextArg++];
initLogger();
logger.info("destFolder: " + destFolder);
- install(destFolder);
+ install(useExitCode0, destFolder);
}
else {
printUsage();
@@ -93,6 +104,10 @@ public class Runner {
}
}
+ public static void infoStackTrace(String msg, Throwable e){
+ logger.info(msg, e);
+ }
+
public static void printStackTrace(Throwable e){
logger.error(e.getMessage(), e);
}
@@ -115,8 +130,8 @@ public class Runner {
private static void printUsage() {
System.err.println("Usage:\n" +
"create " +
- " [ignored=file1;file2;...] [critical=file1;file2;...] [optional=file1;file2;...]\n" +
- "install [log_directory]\n");
+ " [ignored=file1;file2;...] [critical=file1;file2;...] [optional=file1;file2;...]\n" +
+ "install [--exit0] [log_directory]\n");
}
private static void create(String oldBuildDesc,
@@ -127,9 +142,31 @@ public class Runner {
List ignoredFiles,
List criticalFiles,
List optionalFiles) throws IOException, OperationCancelledException {
- UpdaterUI ui = new ConsoleUpdaterUI();
+ File tempPatchFile = Utils.createTempFile();
+ createImpl(oldBuildDesc,
+ newBuildDesc,
+ oldFolder,
+ newFolder,
+ patchFile,
+ tempPatchFile,
+ ignoredFiles,
+ criticalFiles,
+ optionalFiles,
+ new ConsoleUpdaterUI(), resolveJarFile());
+ }
+
+ static void createImpl(String oldBuildDesc,
+ String newBuildDesc,
+ String oldFolder,
+ String newFolder,
+ String outPatchJar,
+ File tempPatchFile,
+ List ignoredFiles,
+ List criticalFiles,
+ List optionalFiles,
+ UpdaterUI ui,
+ File resolvedJar) throws IOException, OperationCancelledException {
try {
- File tempPatchFile = Utils.createTempFile();
PatchFileCreator.create(new File(oldFolder),
new File(newFolder),
tempPatchFile,
@@ -138,13 +175,13 @@ public class Runner {
optionalFiles,
ui);
- logger.info("Packing JAR file: " + patchFile );
- ui.startProcess("Packing JAR file '" + patchFile + "'...");
+ logger.info("Packing JAR file: " + outPatchJar );
+ ui.startProcess("Packing JAR file '" + outPatchJar + "'...");
- FileOutputStream fileOut = new FileOutputStream(patchFile);
+ FileOutputStream fileOut = new FileOutputStream(outPatchJar);
try {
ZipOutputWrapper out = new ZipOutputWrapper(fileOut);
- ZipInputStream in = new ZipInputStream(new FileInputStream(resolveJarFile()));
+ ZipInputStream in = new ZipInputStream(new FileInputStream(resolvedJar));
try {
ZipEntry e;
while ((e = in.getNextEntry()) != null) {
@@ -186,7 +223,7 @@ public class Runner {
Utils.cleanup();
}
- private static void install(final String destFolder) throws Exception {
+ private static void install(final boolean useExitCode0, final String destFolder) throws Exception {
InputStream in = Runner.class.getResourceAsStream("/" + PATCH_PROPERTIES_ENTRY);
Properties props = new Properties();
try {
@@ -213,7 +250,9 @@ public class Runner {
new SwingUpdaterUI(props.getProperty(OLD_BUILD_DESCRIPTION),
props.getProperty(NEW_BUILD_DESCRIPTION),
+ useExitCode0 ? 0 : SwingUpdaterUI.RESULT_REQUIRES_RESTART,
new SwingUpdaterUI.InstallOperation() {
+ @Override
public boolean execute(UpdaterUI ui) throws OperationCancelledException {
logger.info("installing patch to the " + destFolder);
return doInstall(ui, destFolder);
@@ -221,11 +260,26 @@ public class Runner {
});
}
+ interface IJarResolver {
+ File resolveJar() throws IOException;
+ }
+
private static boolean doInstall(UpdaterUI ui, String destFolder) throws OperationCancelledException {
+ return doInstallImpl(ui, destFolder, new IJarResolver() {
+ @Override
+ public File resolveJar() throws IOException {
+ return resolveJarFile();
+ }
+ });
+ }
+
+ static boolean doInstallImpl(UpdaterUI ui,
+ String destFolder,
+ IJarResolver jarResolver) throws OperationCancelledException {
try {
try {
File patchFile = Utils.createTempFile();
- ZipFile jarFile = new ZipFile(resolveJarFile());
+ ZipFile jarFile = new ZipFile(jarResolver.resolveJar());
logger.info("Extracting patch file...");
ui.startProcess("Extracting patch file...");
diff --git a/updater/src/com/intellij/updater/SwingUpdaterUI.java b/updater/src/com/intellij/updater/SwingUpdaterUI.java
index d44fc2e094f1..749dcc2fc350 100644
--- a/updater/src/com/intellij/updater/SwingUpdaterUI.java
+++ b/updater/src/com/intellij/updater/SwingUpdaterUI.java
@@ -10,6 +10,7 @@ import java.awt.event.ActionEvent;
import java.awt.event.ActionListener;
import java.awt.event.WindowAdapter;
import java.awt.event.WindowEvent;
+import java.io.IOException;
import java.io.PrintWriter;
import java.io.StringWriter;
import java.lang.reflect.InvocationTargetException;
@@ -19,7 +20,7 @@ import java.util.concurrent.ConcurrentLinkedQueue;
import java.util.concurrent.atomic.AtomicBoolean;
public class SwingUpdaterUI implements UpdaterUI {
- private static final int RESULT_REQUIRES_RESTART = 42;
+ static final int RESULT_REQUIRES_RESTART = 42;
private static final EmptyBorder FRAME_BORDER = new EmptyBorder(8, 8, 8, 8);
private static final EmptyBorder LABEL_BORDER = new EmptyBorder(0, 0, 5, 0);
@@ -32,6 +33,7 @@ public class SwingUpdaterUI implements UpdaterUI {
private static final String PROCEED_BUTTON_TITLE = "Proceed";
+ private final int mySuccessExitCode;
private final InstallOperation myOperation;
private final JLabel myProcessTitle;
@@ -40,16 +42,30 @@ public class SwingUpdaterUI implements UpdaterUI {
private final JTextArea myConsole;
private final JPanel myConsolePane;
+ private final JButton myRetryButton;
private final JButton myCancelButton;
private final ConcurrentLinkedQueue myQueue = new ConcurrentLinkedQueue();
private final AtomicBoolean isCancelled = new AtomicBoolean(false);
private final AtomicBoolean isRunning = new AtomicBoolean(false);
private final AtomicBoolean hasError = new AtomicBoolean(false);
+ private final AtomicBoolean hasRetry = new AtomicBoolean(false);
private final JFrame myFrame;
private boolean myApplied;
- public SwingUpdaterUI(String oldBuildDesc, String newBuildDesc, InstallOperation operation) {
+ /**
+ * Displays the updater UI and asynchronously runs the operation list.
+ *
+ * @param oldBuildDesc The old build description, for display purposes.
+ * @param newBuildDesc The new build description, for display purposes.
+ * @param successExitCode The desired exit code on success. Default is {@link #RESULT_REQUIRES_RESTART}.
+ * @param operation The install operations to perform.
+ */
+ public SwingUpdaterUI(String oldBuildDesc,
+ String newBuildDesc,
+ int successExitCode,
+ InstallOperation operation) {
+ mySuccessExitCode = successExitCode;
myOperation = operation;
myProcessTitle = new JLabel(" ");
@@ -58,6 +74,10 @@ public class SwingUpdaterUI implements UpdaterUI {
myCancelButton = new JButton(CANCEL_BUTTON_TITLE);
+ myRetryButton = new JButton("Retry");
+ myRetryButton.setEnabled(false);
+ myRetryButton.setVisible(false);
+
myConsole = new JTextArea();
myConsole.setLineWrap(true);
myConsole.setWrapStyleWord(true);
@@ -70,11 +90,19 @@ public class SwingUpdaterUI implements UpdaterUI {
myConsolePane.setVisible(false);
myCancelButton.addActionListener(new ActionListener() {
+ @Override
public void actionPerformed(ActionEvent e) {
doCancel();
}
});
+ myRetryButton.addActionListener(new ActionListener() {
+ @Override
+ public void actionPerformed(ActionEvent e) {
+ doRetry();
+ }
+ });
+
myFrame = new JFrame();
myFrame.setTitle(TITLE);
@@ -104,6 +132,7 @@ public class SwingUpdaterUI implements UpdaterUI {
buttonsPanel.setBorder(BUTTONS_BORDER);
buttonsPanel.setLayout(new BoxLayout(buttonsPanel, BoxLayout.X_AXIS));
buttonsPanel.add(Box.createHorizontalGlue());
+ buttonsPanel.add(myRetryButton);
buttonsPanel.add(myCancelButton);
myProcessTitle.setText("Updating " + oldBuildDesc + " to " + newBuildDesc + "...");
@@ -129,6 +158,7 @@ public class SwingUpdaterUI implements UpdaterUI {
private void startRequestDispatching() {
new Thread(new Runnable() {
+ @Override
public void run() {
while (true) {
try {
@@ -146,6 +176,7 @@ public class SwingUpdaterUI implements UpdaterUI {
}
SwingUtilities.invokeLater(new Runnable() {
+ @Override
public void run() {
for (UpdateRequest each : pendingRequests) {
each.perform();
@@ -172,10 +203,28 @@ public class SwingUpdaterUI implements UpdaterUI {
}
}
+ private void doRetry() {
+ hasError.set(false);
+ hasRetry.set(false);
+ isCancelled.set(false);
+ myQueue.add(new UpdateRequest() {
+ @Override
+ public void perform() {
+ myConsole.setText("");
+ myConsolePane.setVisible(false);
+ myConsolePane.setPreferredSize(new Dimension(10, 200));
+ myRetryButton.setEnabled(false);
+ myCancelButton.setEnabled(true);
+ }
+ });
+ doPerform();
+ }
+
private void doPerform() {
isRunning.set(true);
new Thread(new Runnable() {
+ @Override
public void run() {
try {
myApplied = myOperation.execute(SwingUpdaterUI.this);
@@ -190,6 +239,10 @@ public class SwingUpdaterUI implements UpdaterUI {
finally {
isRunning.set(false);
+ if (hasRetry.get()) {
+ myRetryButton.setVisible(true);
+ myRetryButton.setEnabled(true);
+ }
if (hasError.get()) {
startProcess("Failed to apply patch");
setProgress(100);
@@ -204,15 +257,17 @@ public class SwingUpdaterUI implements UpdaterUI {
}
private void exit() {
- System.exit(myApplied ? RESULT_REQUIRES_RESTART : 0);
+ System.exit(myApplied ? mySuccessExitCode : 0);
}
+ @Override
public Map askUser(final List validationResults) throws OperationCancelledException {
if (validationResults.isEmpty()) return Collections.emptyMap();
final Map result = new HashMap();
try {
SwingUtilities.invokeAndWait(new Runnable() {
+ @Override
public void run() {
final JDialog dialog = new JDialog(myFrame, TITLE, true);
dialog.setLayout(new BorderLayout());
@@ -224,6 +279,7 @@ public class SwingUpdaterUI implements UpdaterUI {
buttonsPanel.add(Box.createHorizontalGlue());
JButton proceedButton = new JButton(PROCEED_BUTTON_TITLE);
proceedButton.addActionListener(new ActionListener() {
+ @Override
public void actionPerformed(ActionEvent e) {
dialog.setVisible(false);
}
@@ -231,6 +287,7 @@ public class SwingUpdaterUI implements UpdaterUI {
JButton cancelButton = new JButton(CANCEL_BUTTON_TITLE);
cancelButton.addActionListener(new ActionListener() {
+ @Override
public void actionPerformed(ActionEvent e) {
isCancelled.set(true);
myCancelButton.setEnabled(false);
@@ -287,8 +344,10 @@ public class SwingUpdaterUI implements UpdaterUI {
return result;
}
+ @Override
public void startProcess(final String title) {
myQueue.add(new UpdateRequest() {
+ @Override
public void perform() {
myProcessStatus.setText(title);
myProcessProgress.setIndeterminate(false);
@@ -297,8 +356,10 @@ public class SwingUpdaterUI implements UpdaterUI {
});
}
+ @Override
public void setProgress(final int percentage) {
myQueue.add(new UpdateRequest() {
+ @Override
public void perform() {
myProcessProgress.setIndeterminate(false);
myProcessProgress.setValue(percentage);
@@ -306,21 +367,43 @@ public class SwingUpdaterUI implements UpdaterUI {
});
}
+ @Override
public void setProgressIndeterminate() {
myQueue.add(new UpdateRequest() {
+ @Override
public void perform() {
myProcessProgress.setIndeterminate(true);
}
});
}
+ @Override
public void setStatus(final String status) {
}
+ @Override
public void showError(final Throwable e) {
hasError.set(true);
+ StringWriter w = new StringWriter();
+
+ if (e instanceof RetryException) {
+ hasRetry.set(true);
+
+ w.write("+----------------\n");
+ w.write("| A file operation failed.\n");
+ w.write("| This might be due to a file being locked by another\n");
+ w.write("| application. Please try closing any application\n");
+ w.write("| that uses the files being updated then press 'Retry'.\n");
+ w.write("+----------------\n");
+ w.write("\n\n");
+ }
+
+ e.printStackTrace(new PrintWriter(w));
+
+ final String content = w.getBuffer().toString();
myQueue.add(new UpdateRequest() {
+ @Override
public void perform() {
StringWriter w = new StringWriter();
if (!myConsolePane.isVisible()) {
@@ -328,9 +411,8 @@ public class SwingUpdaterUI implements UpdaterUI {
w.write(System.getProperty("java.io.tmpdir"));
w.write("\n\n");
}
- e.printStackTrace(new PrintWriter(w));
- w.append("\n");
myConsole.append(w.getBuffer().toString());
+ myConsole.append(content);
if (!myConsolePane.isVisible()) {
myConsole.setCaretPosition(0);
myConsolePane.setVisible(true);
@@ -341,6 +423,7 @@ public class SwingUpdaterUI implements UpdaterUI {
});
}
+ @Override
public void checkCancelled() throws OperationCancelledException {
if (isCancelled.get()) throw new OperationCancelledException();
}
@@ -354,7 +437,8 @@ public class SwingUpdaterUI implements UpdaterUI {
}
public static void main(String[] args) {
- new SwingUpdaterUI("xxx", "yyy", new InstallOperation() {
+ new SwingUpdaterUI("xxx", "yyy", RESULT_REQUIRES_RESTART, new InstallOperation() {
+ @Override
public boolean execute(UpdaterUI ui) throws OperationCancelledException {
ui.startProcess("Process1");
ui.checkCancelled();
@@ -438,6 +522,7 @@ public class SwingUpdaterUI implements UpdaterUI {
}
}
+ @Override
public int getColumnCount() {
return COLUMNS.length;
}
@@ -464,6 +549,7 @@ public class SwingUpdaterUI implements UpdaterUI {
return super.getColumnClass(columnIndex);
}
+ @Override
public int getRowCount() {
return myItems.size();
}
@@ -480,6 +566,7 @@ public class SwingUpdaterUI implements UpdaterUI {
}
}
+ @Override
public Object getValueAt(int rowIndex, int columnIndex) {
Item item = myItems.get(rowIndex);
switch (columnIndex) {
diff --git a/updater/src/com/intellij/updater/Utils.java b/updater/src/com/intellij/updater/Utils.java
index 959a93cee1c2..b5ad212ac1a9 100644
--- a/updater/src/com/intellij/updater/Utils.java
+++ b/updater/src/com/intellij/updater/Utils.java
@@ -10,10 +10,19 @@ public class Utils {
private static final byte[] BUFFER = new byte[64 * 1024];
private static File myTempDir;
+ public static boolean isWindows() {
+ return System.getProperty("os.name").startsWith("Windows");
+ }
+
public static boolean isZipFile(String fileName) {
return fileName.endsWith(".zip") || fileName.endsWith(".jar");
}
+ /**
+ * Creates a new temp file.
+ * All the temp files created here are located in a unique root temp directory
+ * that is automatically deleted by {@link #cleanup()}.
+ */
@SuppressWarnings({"SSBasedInspection"})
public static File createTempFile() throws IOException {
if (myTempDir == null) {
@@ -26,6 +35,12 @@ public class Utils {
return File.createTempFile("temp.", ".tmp", myTempDir);
}
+
+ /**
+ * Creates a new temp directory.
+ * All the temp directories created here are located in a unique root temp directory
+ * that is automatically deleted by {@link #cleanup()}.
+ */
public static File createTempDir() throws IOException {
File result = createTempFile();
delete(result);
@@ -42,6 +57,15 @@ public class Utils {
myTempDir = null;
}
+ /**
+ * Deletes a file or directory with a default timeout of 100 milliseconds.
+ * Directories are deleted recursively. The timeout occurs on each file.
+ * If one of the files fails to be deleted, the recursive directory deletion
+ * is aborted and not retried.
+ *
+ * @param file The file or directory to delete.
+ * @throws IOException
+ */
public static void delete(File file) throws IOException {
if (file.isDirectory()) {
File[] files = file.listFiles();
@@ -52,16 +76,20 @@ public class Utils {
}
}
}
+
for (int i = 0; i < 10; i++) {
- if (file.delete() || !file.exists()) return;
+ if (file.delete() || !file.exists()) {
+ return;
+ }
try {
Thread.sleep(10);
- }
- catch (InterruptedException ignore) {
+ } catch (InterruptedException ignore) {
Runner.printStackTrace(ignore);
}
}
- if (file.exists()) throw new IOException("Cannot delete file " + file);
+ if (file.exists()) {
+ throw new IOException("Cannot delete file " + file);
+ }
}
public static void setExecutable(File file, boolean executable) throws IOException {
diff --git a/xml/xml-psi-impl/src/com/intellij/embedding/MasqueradingPsiBuilderAdapter.java b/xml/xml-psi-impl/src/com/intellij/embedding/MasqueradingPsiBuilderAdapter.java
index a262c5558e19..ca45d1ecf98e 100644
--- a/xml/xml-psi-impl/src/com/intellij/embedding/MasqueradingPsiBuilderAdapter.java
+++ b/xml/xml-psi-impl/src/com/intellij/embedding/MasqueradingPsiBuilderAdapter.java
@@ -18,6 +18,7 @@ package com.intellij.embedding;
import com.intellij.lang.*;
import com.intellij.lang.impl.PsiBuilderAdapter;
import com.intellij.lang.impl.PsiBuilderImpl;
+import com.intellij.openapi.diagnostic.Logger;
import com.intellij.openapi.project.Project;
import com.intellij.psi.TokenType;
import com.intellij.psi.tree.IElementType;
@@ -26,7 +27,6 @@ import org.jetbrains.annotations.Nullable;
import java.util.ArrayList;
import java.util.List;
-import java.util.logging.Logger;
/**
* A delegate PsiBuilder that hides or substitutes some tokens (namely, the ones provided by {@link MasqueradingLexer})
@@ -68,45 +68,65 @@ public class MasqueradingPsiBuilderAdapter extends PsiBuilderAdapter {
@Override
public void advanceLexer() {
-// logPos();
myLexPosition++;
+ skipWhitespace();
- synchronizePositions();
-// logPos();
+ synchronizePositions(false);
}
- private void synchronizePositions() {
+ /**
+ * @param exact if true then positions should be equal;
+ * else delegate should be behind, not including exactly all foreign (skipped) tokens
+ */
+ private void synchronizePositions(boolean exact) {
final PsiBuilder delegate = getDelegate();
- while (!delegate.eof() || myLexPosition < myShrunkSequence.size()) {
- if (myLexPosition >= myShrunkSequence.size()) {
+
+ if (myLexPosition >= myShrunkSequence.size() || delegate.eof()) {
+ myLexPosition = myShrunkSequence.size();
+ while (!delegate.eof()) {
delegate.advanceLexer();
- continue;
- }
- if (delegate.eof()) {
- myLexPosition = myShrunkSequence.size();
- break;
}
+ return;
+ }
+
+ if (delegate.getCurrentOffset() > myShrunkSequence.get(myLexPosition).realStart) {
+ Logger.getInstance(getClass()).error("delegate is ahead of my builder!");
+ return;
+ }
+
+ final int keepUpPosition = getKeepUpPosition(exact);
+
+ while (!delegate.eof()) {
final int delegatePosition = delegate.getCurrentOffset();
- final int myPosition = myShrunkSequence.get(myLexPosition).realStart;
- if (delegatePosition < myPosition) {
+ if (delegatePosition < keepUpPosition) {
delegate.advanceLexer();
}
- else if (delegatePosition > myPosition) {
- myLexPosition++;
- }
else {
break;
}
}
}
+ private int getKeepUpPosition(boolean exact) {
+ if (exact) {
+ return myShrunkSequence.get(myLexPosition).realStart;
+ }
+
+ int lexPosition = myLexPosition;
+ while (lexPosition > 0 && (myShrunkSequence.get(lexPosition - 1).shrunkStart == myShrunkSequence.get(lexPosition).shrunkStart
+ || isWhiteSpaceOnPos(lexPosition - 1))) {
+ lexPosition--;
+ }
+ if (lexPosition == 0) {
+ return myShrunkSequence.get(lexPosition).realStart;
+ }
+ return myShrunkSequence.get(lexPosition - 1).realStart + 1;
+ }
+
@Override
public IElementType lookAhead(int steps) {
- final PsiBuilderImpl delegate = (PsiBuilderImpl)getDelegate();
- synchronizePositions();
-
if (eof()) { // ensure we skip over whitespace if it's needed
return null;
}
@@ -114,7 +134,7 @@ public class MasqueradingPsiBuilderAdapter extends PsiBuilderAdapter {
while (steps > 0) {
++cur;
- while (cur < myShrunkSequence.size() && delegate.whitespaceOrComment(myShrunkSequence.get(cur).elementType)) {
+ while (cur < myShrunkSequence.size() && isWhiteSpaceOnPos(cur)) {
cur++;
}
@@ -154,7 +174,7 @@ public class MasqueradingPsiBuilderAdapter extends PsiBuilderAdapter {
if (allIsEmpty()) {
return TokenType.DUMMY_HOLDER;
}
- checkWhitespace();
+ skipWhitespace();
return myLexPosition < myShrunkSequence.size() ? myShrunkSequence.get(myLexPosition).elementType : null;
}
@@ -165,7 +185,7 @@ public class MasqueradingPsiBuilderAdapter extends PsiBuilderAdapter {
if (allIsEmpty()) {
return getDelegate().getOriginalText().toString();
}
- checkWhitespace();
+ skipWhitespace();
if (myLexPosition >= myShrunkSequence.size()) {
return null;
@@ -175,8 +195,24 @@ public class MasqueradingPsiBuilderAdapter extends PsiBuilderAdapter {
return myShrunkCharSequence.subSequence(token.shrunkStart, token.shrunkEnd).toString();
}
+ @Override
+ public boolean eof() {
+ boolean isEof = myLexPosition >= myShrunkSequence.size();
+ if (!isEof) {
+ return false;
+ }
+
+ synchronizePositions(true);
+ return true;
+ }
+
@Override
public Marker mark() {
+ // In the case of the topmost node all should be inserted
+ if (myLexPosition != 0) {
+ synchronizePositions(true);
+ }
+
final Marker mark = super.mark();
return new MyMarker(mark, myLexPosition);
}
@@ -185,12 +221,14 @@ public class MasqueradingPsiBuilderAdapter extends PsiBuilderAdapter {
return myShrunkSequence.isEmpty() && getDelegate().getOriginalText().length() != 0;
}
- private void checkWhitespace() {
- while (myLexPosition < myShrunkSequence.size() &&
- ((PsiBuilderImpl)myDelegate).whitespaceOrComment(myShrunkSequence.get(myLexPosition).elementType)) {
+ private void skipWhitespace() {
+ while (myLexPosition < myShrunkSequence.size() && isWhiteSpaceOnPos(myLexPosition)) {
myLexPosition++;
}
- synchronizePositions();
+ }
+
+ private boolean isWhiteSpaceOnPos(int pos) {
+ return ((PsiBuilderImpl)myDelegate).whitespaceOrComment(myShrunkSequence.get(pos).elementType);
}
protected void initShrunkSequence() {
@@ -199,7 +237,6 @@ public class MasqueradingPsiBuilderAdapter extends PsiBuilderAdapter {
initTokenListAndCharSequence(lexer);
myLexPosition = 0;
-// synchronizePositions();
}
private void initTokenListAndCharSequence(MasqueradingLexer lexer) {
@@ -235,7 +272,7 @@ public class MasqueradingPsiBuilderAdapter extends PsiBuilderAdapter {
@SuppressWarnings({"StringConcatenationInsideStringBufferAppend", "UnusedDeclaration"})
private void logPos() {
- final Logger log = Logger.getLogger(this.getClass().getSimpleName());
+ final Logger log = Logger.getInstance(getClass());
StringBuilder sb = new StringBuilder();
sb.append("\nmyLexPosition=" + myLexPosition + "/" + myShrunkSequence.size());
if (myLexPosition < myShrunkSequence.size()) {
@@ -271,6 +308,11 @@ public class MasqueradingPsiBuilderAdapter extends PsiBuilderAdapter {
this.shrunkStart = shrunkStart;
this.shrunkEnd = shrunkEnd;
}
+
+ @Override
+ public String toString() {
+ return "MSTk: [" + realStart + ", " + realEnd + "] -> [" + shrunkStart + ", " + shrunkEnd + "]: " + elementType.toString();
+ }
}
private class MyMarker extends DelegateMarker {