mirror of
https://gitflic.ru/project/openide/openide.git
synced 2026-09-27 10:03:11 +07:00
Merge remote-tracking branch 'origin/master'
This commit is contained in:
@@ -12,6 +12,7 @@
|
||||
<fileset dir="${project.home}/build/lib/jps">
|
||||
<include name="*.jar"/>
|
||||
</fileset>
|
||||
<fileset file="${project.home}/jps/lib/optimizedFileManager.jar"/>
|
||||
<fileset dir="${project.home}/build/kotlinc/jps" erroronmissingdir="false">
|
||||
<include name="*.jar"/>
|
||||
</fileset>
|
||||
|
||||
@@ -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")
|
||||
|
||||
+20
-1
@@ -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);
|
||||
|
||||
+4
-2
@@ -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<PsiMethod> methods = new ArrayList<PsiMethod>();
|
||||
for (HierarchicalMethodSignature methodSignature : aClass.getVisibleSignatures()) {
|
||||
|
||||
+2
-1
@@ -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();
|
||||
|
||||
+2
-1
@@ -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
|
||||
|
||||
|
||||
+4
-5
@@ -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);
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
@@ -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();
|
||||
}
|
||||
|
||||
+65
@@ -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<Person> test() {
|
||||
return repository.all()
|
||||
.flatMap(foo -> {
|
||||
|
||||
class AB {
|
||||
List<String> a() {
|
||||
return <warning descr="Unchecked assignment: 'java.util.ArrayList' to 'java.util.List<java.lang.String>'">new ArrayList()</warning>;
|
||||
}
|
||||
}
|
||||
|
||||
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<Person> all() {
|
||||
return Stream.empty();
|
||||
}
|
||||
|
||||
public Stream<UpdateResult> 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;
|
||||
}
|
||||
}
|
||||
}
|
||||
+4
@@ -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);
|
||||
}
|
||||
|
||||
+2
-2
@@ -24,10 +24,10 @@ public class JavaBraceMatcherTest extends LightCodeInsightFixtureTestCase {
|
||||
public void testGenerics() {
|
||||
myFixture.configureByText("a.java", "import java.util.ArrayList;" +
|
||||
"class A {" +
|
||||
" ArrayList<caret><? extends String[]> f;" +
|
||||
" ArrayList<caret><? extends @Anno String[]> f;" +
|
||||
"}");
|
||||
final int offset = BraceMatchingUtil.getMatchedBraceOffset(myFixture.getEditor(), true, myFixture.getFile());
|
||||
assertEquals(66, offset);
|
||||
assertEquals(72, offset);
|
||||
}
|
||||
|
||||
public void testBrokenText() {
|
||||
|
||||
+6
-1
@@ -86,7 +86,12 @@ public class GeneralHighlightingPass extends ProgressableTextEditorHighlightingP
|
||||
private static final Comparator<HighlightVisitor> VISITOR_ORDER_COMPARATOR = new Comparator<HighlightVisitor>() {
|
||||
@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;
|
||||
|
||||
@@ -87,8 +87,7 @@ public abstract class DvcsBranchPopup<Repo extends Repository> {
|
||||
@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;
|
||||
|
||||
@@ -918,7 +918,15 @@ public class CommonCodeStyleSettings {
|
||||
|
||||
@Override
|
||||
public void writeExternal(Element element) throws WriteExternalException {
|
||||
DefaultJDOMExternalizer.writeExternal(this, element, new DifferenceFilter<IndentOptions>(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) {
|
||||
|
||||
@@ -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());
|
||||
|
||||
+13
-4
@@ -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<ArrangementSettingsToken> myModifiers = ContainerUtilRt.newHashSet();
|
||||
@NotNull private final Set<ArrangementAtomMatchCondition> myModifiers = ContainerUtilRt.newHashSet();
|
||||
|
||||
public ByModifierArrangementEntryMatcher(@NotNull ArrangementSettingsToken interestedModifier) {
|
||||
public ByModifierArrangementEntryMatcher(@NotNull ArrangementAtomMatchCondition interestedModifier) {
|
||||
myModifiers.add(interestedModifier);
|
||||
}
|
||||
|
||||
public ByModifierArrangementEntryMatcher(@NotNull Collection<ArrangementSettingsToken> interestedModifiers) {
|
||||
public ByModifierArrangementEntryMatcher(@NotNull Collection<ArrangementAtomMatchCondition> interestedModifiers) {
|
||||
myModifiers.addAll(interestedModifiers);
|
||||
}
|
||||
|
||||
@Override
|
||||
public boolean isMatched(@NotNull ArrangementEntry entry) {
|
||||
if (entry instanceof ModifierAwareArrangementEntry) {
|
||||
return ((ModifierAwareArrangementEntry)entry).getModifiers().containsAll(myModifiers);
|
||||
final Set<ArrangementSettingsToken> 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;
|
||||
}
|
||||
|
||||
+14
-5
@@ -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<ArrangementSettingsToken> myTypes = ContainerUtilRt.newHashSet();
|
||||
@NotNull private final Set<ArrangementAtomMatchCondition> myTypes = ContainerUtilRt.newHashSet();
|
||||
|
||||
public ByTypeArrangementEntryMatcher(@NotNull ArrangementSettingsToken interestedType) {
|
||||
public ByTypeArrangementEntryMatcher(@NotNull ArrangementAtomMatchCondition interestedType) {
|
||||
myTypes.add(interestedType);
|
||||
}
|
||||
|
||||
public ByTypeArrangementEntryMatcher(@NotNull Collection<ArrangementSettingsToken> interestedTypes) {
|
||||
public ByTypeArrangementEntryMatcher(@NotNull Collection<ArrangementAtomMatchCondition> interestedTypes) {
|
||||
myTypes.addAll(interestedTypes);
|
||||
}
|
||||
|
||||
@Override
|
||||
public boolean isMatched(@NotNull ArrangementEntry entry) {
|
||||
if (entry instanceof TypeAwareArrangementEntry) {
|
||||
return ((TypeAwareArrangementEntry)entry).getTypes().containsAll(myTypes);
|
||||
final Set<ArrangementSettingsToken> 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<ArrangementSettingsToken> getTypes() {
|
||||
public Set<ArrangementAtomMatchCondition> getTypes() {
|
||||
return myTypes;
|
||||
}
|
||||
|
||||
|
||||
+22
-1
@@ -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);
|
||||
}
|
||||
|
||||
|
||||
+11
-14
@@ -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<StdArrangementTokenType, ArrangementSettingsToken > context =
|
||||
new MultiValuesMap<StdArrangementTokenType, ArrangementSettingsToken>();
|
||||
@NotNull protected final MultiValuesMap<StdArrangementTokenType, ArrangementAtomMatchCondition> context =
|
||||
new MultiValuesMap<StdArrangementTokenType, ArrangementAtomMatchCondition>();
|
||||
@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<ArrangementEntryMatcher> buildMatchers() {
|
||||
List<ArrangementEntryMatcher> result = ContainerUtilRt.newArrayList(myMatchers);
|
||||
Collection<ArrangementSettingsToken> entryTokens = context.get(StdArrangementTokenType.ENTRY_TYPE);
|
||||
Collection<ArrangementAtomMatchCondition> entryTokens = context.get(StdArrangementTokenType.ENTRY_TYPE);
|
||||
if (entryTokens!= null) {
|
||||
result.add(new ByTypeArrangementEntryMatcher(entryTokens));
|
||||
}
|
||||
Collection<ArrangementSettingsToken> modifierTokens = context.get(StdArrangementTokenType.MODIFIER);
|
||||
Collection<ArrangementAtomMatchCondition> modifierTokens = context.get(StdArrangementTokenType.MODIFIER);
|
||||
if (modifierTokens != null) {
|
||||
result.add(new ByModifierArrangementEntryMatcher(modifierTokens));
|
||||
}
|
||||
|
||||
+15
-9
@@ -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<ArrangementSettingsToken> tokens = ArrangementUtil.extractTokens(getMatcher().getCondition()).keySet();
|
||||
final Set<ArrangementSettingsToken> tokens1 = ArrangementUtil.extractTokens(o.getMatcher().getCondition()).keySet();
|
||||
final Map<ArrangementSettingsToken, Object> tokenValues = ArrangementUtil.extractTokens(getMatcher().getCondition());
|
||||
final Map<ArrangementSettingsToken, Object> tokenValues1 = ArrangementUtil.extractTokens(o.getMatcher().getCondition());
|
||||
final Set<ArrangementSettingsToken> tokens = tokenValues.keySet();
|
||||
final Set<ArrangementSettingsToken> 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<ArrangementSettingsToken> tokens) {
|
||||
for (ArrangementSettingsToken token : tokens) {
|
||||
if (StdArrangementTokenType.ENTRY_TYPE.is(token)) {
|
||||
return token.getId();
|
||||
private static String getEntryType(@NotNull Map<ArrangementSettingsToken, Object> tokens) {
|
||||
for (Map.Entry<ArrangementSettingsToken, Object> 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;
|
||||
|
||||
+6
-17
@@ -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());
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
+11
-4
@@ -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<ArrangementSettingsToken> sort(@NotNull Collection<ArrangementSettingsToken> tokens) {
|
||||
List<ArrangementSettingsToken> result = ContainerUtilRt.newArrayList(tokens);
|
||||
|
||||
+15
-2
@@ -36,7 +36,7 @@ import java.util.Set;
|
||||
* @since 3/11/13 10:22 AM
|
||||
*/
|
||||
public interface ArrangementUiComponent {
|
||||
|
||||
|
||||
@Nullable ArrangementSettingsToken getToken();
|
||||
|
||||
@NotNull Set<ArrangementSettingsToken> 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<Factory> EP_NAME = ExtensionPointName.create("com.intellij.rearranger.ui");
|
||||
|
||||
|
||||
+33
@@ -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();
|
||||
}
|
||||
+3
-3
@@ -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;
|
||||
}
|
||||
|
||||
+34
-25
@@ -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<Set<ArrangementSettingsToken>> TOKENS = collectFields(Modifier.class);
|
||||
|
||||
private Modifier() {
|
||||
|
||||
+44
@@ -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();
|
||||
}
|
||||
}
|
||||
@@ -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();
|
||||
|
||||
+5
@@ -175,4 +175,9 @@ public abstract class AbstractArrangementUiComponent implements ArrangementUiCom
|
||||
}
|
||||
|
||||
protected abstract void doReset();
|
||||
|
||||
@Override
|
||||
public boolean alwaysCanBeActive() {
|
||||
return false;
|
||||
}
|
||||
}
|
||||
|
||||
+13
-3
@@ -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 "));
|
||||
|
||||
+54
-6
@@ -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);
|
||||
|
||||
+6
-1
@@ -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);
|
||||
}
|
||||
}
|
||||
|
||||
+5
@@ -123,4 +123,9 @@ public class ArrangementComboBoxUiComponent extends AbstractArrangementUiCompone
|
||||
public int getBaselineToUse(int width, int height) {
|
||||
return -1;
|
||||
}
|
||||
|
||||
@Override
|
||||
public void handleMouseClickOnSelected() {
|
||||
setSelected(false);
|
||||
}
|
||||
}
|
||||
|
||||
+5
@@ -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);
|
||||
}
|
||||
}
|
||||
|
||||
+8
-1
@@ -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);
|
||||
}
|
||||
}
|
||||
|
||||
+4
-2
@@ -378,7 +378,8 @@ public class ArrangementMatchingRuleEditor extends JPanel implements Arrangement
|
||||
// don't allow to remove start/end section indication
|
||||
final Set<ArrangementSettingsToken> 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();
|
||||
}
|
||||
|
||||
|
||||
+10
@@ -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();
|
||||
|
||||
@@ -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<Pair<PsiElement, Boolean>> 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();
|
||||
|
||||
@@ -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;
|
||||
|
||||
@@ -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();
|
||||
|
||||
@@ -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 {
|
||||
|
||||
+9
-11
@@ -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();
|
||||
|
||||
+4
@@ -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);
|
||||
|
||||
@@ -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;
|
||||
|
||||
@@ -2220,7 +2220,7 @@ public class ContainerUtil extends ContainerUtilRt {
|
||||
@NotNull
|
||||
@Contract(pure=true)
|
||||
public static <V> ConcurrentIntObjectMap<V> createConcurrentIntObjectMap() {
|
||||
return new ConcurrentIntObjectHashMap<V>();
|
||||
return new StripedLockIntObjectConcurrentHashMap<V>();
|
||||
}
|
||||
|
||||
@NotNull
|
||||
|
||||
@@ -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));
|
||||
}
|
||||
}
|
||||
|
||||
+9
@@ -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);
|
||||
}
|
||||
|
||||
@@ -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<String> list = new ArrayList<String>(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());
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@@ -310,7 +310,7 @@ public class JUnitConfiguration extends ModuleBasedConfiguration<JavaRunConfigur
|
||||
EnvironmentVariablesComponent.readExternal(element, getPersistentData().getEnvs());
|
||||
final Element patternsElement = element.getChild(PATTERNS_EL_NAME);
|
||||
if (patternsElement != null) {
|
||||
final Set<String> tests = new LinkedHashSet<String>();
|
||||
final LinkedHashSet<String> tests = new LinkedHashSet<String>();
|
||||
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<JavaRunConfigur
|
||||
|
||||
public void bePatternConfiguration(List<PsiClass> classes, PsiMethod method) {
|
||||
myData.TEST_OBJECT = TEST_PATTERN;
|
||||
final Set<String> patterns = new HashSet<String>();
|
||||
final LinkedHashSet<String> patterns = new LinkedHashSet<String>();
|
||||
final String methodSufiix;
|
||||
if (method != null) {
|
||||
myData.METHOD_NAME = method.getName();
|
||||
@@ -437,7 +437,7 @@ public class JUnitConfiguration extends ModuleBasedConfiguration<JavaRunConfigur
|
||||
public String WORKING_DIRECTORY;
|
||||
private String FORK_MODE = "none";
|
||||
|
||||
private Set<String> myPattern = new LinkedHashSet<String>();
|
||||
private LinkedHashSet<String> myPattern = new LinkedHashSet<String>();
|
||||
//iws/ipr compatibility
|
||||
public String ENV_VARIABLES;
|
||||
private Map<String, String> myEnvs = new LinkedHashMap<String, String>();
|
||||
@@ -581,7 +581,7 @@ public class JUnitConfiguration extends ModuleBasedConfiguration<JavaRunConfigur
|
||||
return StringUtil.join(enabledTests, "||");
|
||||
}
|
||||
|
||||
public void setPatterns(Set<String> pattern) {
|
||||
public void setPatterns(LinkedHashSet<String> pattern) {
|
||||
myPattern = pattern;
|
||||
}
|
||||
|
||||
|
||||
@@ -509,18 +509,18 @@ public abstract class TestObject implements JavaCommandLine {
|
||||
testNames.add(name);
|
||||
}
|
||||
}
|
||||
final JUnitConfiguration.Data data = myConfiguration.getPersistentData();
|
||||
if (perModule != null) {
|
||||
for (List<String> 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) {
|
||||
|
||||
+6
-6
@@ -83,7 +83,7 @@ public class SearchingForTestsTask extends Task.Backgroundable {
|
||||
myServerSocket = serverSocket;
|
||||
myConfig = config;
|
||||
myTempFile = tempFile;
|
||||
myClasses = new HashMap<PsiClass, Collection<PsiMethod>>();
|
||||
myClasses = new LinkedHashMap<PsiClass, Collection<PsiMethod>>();
|
||||
}
|
||||
|
||||
public void run(@NotNull ProgressIndicator indicator) {
|
||||
@@ -190,13 +190,13 @@ public class SearchingForTestsTask extends Task.Backgroundable {
|
||||
}
|
||||
|
||||
private void composeTestSuiteFromClasses() {
|
||||
Map<String, Collection<String>> map = new HashMap<String, Collection<String>>();
|
||||
Map<String, Collection<String>> map = new LinkedHashMap<String, Collection<String>>();
|
||||
|
||||
final boolean findTestMethodsForClass = shouldSearchForTestMethods();
|
||||
|
||||
for (final Map.Entry<PsiClass, Collection<PsiMethod>> entry : myClasses.entrySet()) {
|
||||
final Collection<PsiMethod> depMethods = entry.getValue();
|
||||
Collection<String> methods = new HashSet<String>(depMethods.size());
|
||||
Collection<String> methods = new LinkedHashSet<String>(depMethods.size());
|
||||
for (PsiMethod method : depMethods) {
|
||||
methods.add(method.getName());
|
||||
}
|
||||
@@ -523,7 +523,7 @@ public class SearchingForTestsTask extends Task.Backgroundable {
|
||||
final Set<PsiMember> alreadyMarkedToBeChecked,
|
||||
@Nullable final PsiClass... classes) {
|
||||
if (classes != null && classes.length > 0) {
|
||||
final Set<String> groupDependencies = new HashSet<String>();
|
||||
final Set<String> groupDependencies = new LinkedHashSet<String>();
|
||||
TestNGUtil.collectAnnotationValues(groupDependencies, "dependsOnGroups", methods, classes);
|
||||
final Set<PsiMember> membersToCheckNow = new LinkedHashSet<PsiMember>();
|
||||
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<PsiClass> containingClasses = new HashSet<PsiClass>();
|
||||
final Set<PsiClass> containingClasses = new LinkedHashSet<PsiClass>();
|
||||
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<String> testMethodDependencies = new HashSet<String>();
|
||||
final Set<String> testMethodDependencies = new LinkedHashSet<String>();
|
||||
TestNGUtil.collectAnnotationValues(testMethodDependencies, "dependsOnMethods", methods, containingClass);
|
||||
if (!testMethodDependencies.isEmpty()) {
|
||||
ApplicationManager.getApplication().runReadAction(new Runnable() {
|
||||
|
||||
+2
-2
@@ -269,7 +269,7 @@ public class TestNGConfiguration extends ModuleBasedConfiguration<JavaRunConfigu
|
||||
} else {
|
||||
suffix = "";
|
||||
}
|
||||
Set<String> patterns = new LinkedHashSet<String>();
|
||||
LinkedHashSet<String> patterns = new LinkedHashSet<String>();
|
||||
for (PsiClass pattern : classes) {
|
||||
patterns.add(JavaExecutionUtil.getRuntimeQualifiedName(pattern) + suffix);
|
||||
}
|
||||
@@ -373,7 +373,7 @@ public class TestNGConfiguration extends ModuleBasedConfiguration<JavaRunConfigu
|
||||
}
|
||||
final Element patternsElement = element.getChild(PATTERNS_EL_NAME);
|
||||
if (patternsElement != null) {
|
||||
final Set<String> tests = new LinkedHashSet<String>();
|
||||
final LinkedHashSet<String> tests = new LinkedHashSet<String>();
|
||||
for (Object o : patternsElement.getChildren(PATTERN_EL_NAME)) {
|
||||
Element patternElement = (Element)o;
|
||||
tests.add(patternElement.getAttributeValue(TEST_CLASS_ATT_NAME));
|
||||
|
||||
@@ -57,7 +57,7 @@ public class TestData implements Cloneable
|
||||
public List<String> TEST_LISTENERS = new ArrayList<String>();
|
||||
public boolean USE_DEFAULT_REPORTERS = false;
|
||||
public String PROPERTIES_FILE;
|
||||
private Set<String> myPatterns = new LinkedHashSet<String>();
|
||||
private LinkedHashSet<String> myPatterns = new LinkedHashSet<String>();
|
||||
|
||||
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<String, String>(ENVS);
|
||||
data.myPatterns = new HashSet<String>();
|
||||
data.myPatterns = new LinkedHashSet<String>();
|
||||
data.myPatterns.addAll(myPatterns);
|
||||
data.setScope(getScope());
|
||||
return data;
|
||||
@@ -251,7 +251,7 @@ public class TestData implements Cloneable
|
||||
return myPatterns;
|
||||
}
|
||||
|
||||
public void setPatterns(Set<String> set) {
|
||||
public void setPatterns(LinkedHashSet<String> set) {
|
||||
myPatterns = set;
|
||||
}
|
||||
}
|
||||
|
||||
@@ -4,7 +4,7 @@
|
||||
|
||||
<id>PythonCore</id>
|
||||
<name>Python Community Edition</name>
|
||||
<idea-version since-build="138.0" until-build="138.*"/>
|
||||
<idea-version since-build="138.0" until-build="140.*"/>
|
||||
|
||||
<description><![CDATA[
|
||||
The Python plug-in provides smart editing for Python scripts. The feature set of the plugin
|
||||
|
||||
@@ -35,7 +35,13 @@ public abstract class BaseUpdateAction extends PatchAction {
|
||||
|
||||
protected void replaceUpdated(File from, File dest) throws IOException {
|
||||
// on OS X code signing caches seem to be associated with specific file ids, so we need to remove the original file.
|
||||
if (!dest.delete()) throw new IOException("Cannot delete file " + dest);
|
||||
if (!dest.delete()) {
|
||||
if (Utils.isWindows()) {
|
||||
throw new RetryException("Cannot delete file " + dest);
|
||||
} else {
|
||||
throw new IOException("Cannot delete file " + dest);
|
||||
}
|
||||
}
|
||||
Utils.copy(from, dest);
|
||||
}
|
||||
|
||||
|
||||
@@ -59,7 +59,15 @@ public class CreateAction extends PatchAction {
|
||||
|
||||
private static void prepareToWriteFile(File file) throws IOException {
|
||||
if (file.exists()) {
|
||||
Utils.delete(file);
|
||||
try {
|
||||
Utils.delete(file);
|
||||
} catch (IOException e) {
|
||||
if (Utils.isWindows() && file.exists()) {
|
||||
throw new RetryException(e);
|
||||
} else {
|
||||
throw e;
|
||||
}
|
||||
}
|
||||
return;
|
||||
}
|
||||
|
||||
|
||||
@@ -43,13 +43,23 @@ public class DeleteAction extends PatchAction {
|
||||
|
||||
@Override
|
||||
protected void doApply(ZipFile patchFile, File toFile) throws IOException {
|
||||
Utils.delete(toFile);
|
||||
try {
|
||||
Utils.delete(toFile);
|
||||
} catch (IOException e) {
|
||||
if (Utils.isWindows() && toFile.exists()) {
|
||||
throw new RetryException(e);
|
||||
} else {
|
||||
throw e;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@Override
|
||||
protected void doBackup(File toFile, File backupFile) throws IOException {
|
||||
Utils.copy(toFile, backupFile);
|
||||
}
|
||||
|
||||
@Override
|
||||
protected void doRevert(File toFile, File backupFile) throws IOException {
|
||||
if (!toFile.exists() || isModified(toFile)) {
|
||||
Utils.delete(toFile); // make sure there is no directory remained on this path (may remain from previous 'create' actions
|
||||
|
||||
@@ -28,7 +28,8 @@ public class Digester {
|
||||
zipFile = new ZipFile(file);
|
||||
}
|
||||
catch (IOException e) {
|
||||
Runner.printStackTrace(e);
|
||||
// If this isn't a zip file, this isn't really an error, merely an info.
|
||||
Runner.infoStackTrace("Can't open file as zip file: " + file.getPath() + "\n", e);
|
||||
return doDigestRegularFile(file);
|
||||
}
|
||||
|
||||
|
||||
@@ -0,0 +1,39 @@
|
||||
/*
|
||||
* Copyright (C) 2014 The Android Open Source Project
|
||||
*
|
||||
* 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.updater;
|
||||
|
||||
import java.io.IOException;
|
||||
|
||||
/**
|
||||
* Exception thrown when an IOException arises when performing a patch
|
||||
* action and it's likely that retrying will be successful.
|
||||
*/
|
||||
public class RetryException extends IOException {
|
||||
public RetryException() {
|
||||
}
|
||||
|
||||
public RetryException(String message) {
|
||||
super(message);
|
||||
}
|
||||
|
||||
public RetryException(String message, Throwable cause) {
|
||||
super(message, cause);
|
||||
}
|
||||
|
||||
public RetryException(Throwable cause) {
|
||||
super(cause);
|
||||
}
|
||||
}
|
||||
@@ -38,11 +38,22 @@ public class Runner {
|
||||
create(oldVersionDesc, newVersionDesc, oldFolder, newFolder, patchFile, ignoredFiles, criticalFiles, optionalFiles);
|
||||
}
|
||||
else if (args.length >= 2 && "install".equals(args[0])) {
|
||||
String destFolder = args[1];
|
||||
// install [--exit0] <destination_folder>
|
||||
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 <old_version_description> <new_version_description> <old_version_folder> <new_version_folder>" +
|
||||
" <patch_file_name> [ignored=file1;file2;...] [critical=file1;file2;...] [optional=file1;file2;...]\n" +
|
||||
"install <destination_folder> [log_directory]\n");
|
||||
" <patch_file_name> <log_directory> [ignored=file1;file2;...] [critical=file1;file2;...] [optional=file1;file2;...]\n" +
|
||||
"install [--exit0] <destination_folder> [log_directory]\n");
|
||||
}
|
||||
|
||||
private static void create(String oldBuildDesc,
|
||||
@@ -127,9 +142,31 @@ public class Runner {
|
||||
List<String> ignoredFiles,
|
||||
List<String> criticalFiles,
|
||||
List<String> 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<String> ignoredFiles,
|
||||
List<String> criticalFiles,
|
||||
List<String> 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...");
|
||||
|
||||
@@ -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<UpdateRequest> myQueue = new ConcurrentLinkedQueue<UpdateRequest>();
|
||||
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("<html>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<String, ValidationResult.Option> askUser(final List<ValidationResult> validationResults) throws OperationCancelledException {
|
||||
if (validationResults.isEmpty()) return Collections.emptyMap();
|
||||
|
||||
final Map<String, ValidationResult.Option> result = new HashMap<String, ValidationResult.Option>();
|
||||
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) {
|
||||
|
||||
@@ -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. <br/>
|
||||
* 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. <br/>
|
||||
* 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 {
|
||||
|
||||
@@ -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 {
|
||||
|
||||
Reference in New Issue
Block a user