mirror of
https://gitflic.ru/project/openide/openide.git
synced 2026-09-27 10:03:11 +07:00
Merge branch 'master' of git.labs.intellij.net:idea/community
Pull request accepted
This commit is contained in:
+5
-5
@@ -71,7 +71,7 @@ public class JavaWithRuntimeCastSurrounder extends JavaExpressionSurrounder {
|
||||
return null;
|
||||
}
|
||||
|
||||
private class SurroundWithCastWorker extends RuntimeTypeEvaluator {
|
||||
private static class SurroundWithCastWorker extends RuntimeTypeEvaluator {
|
||||
private final Editor myEditor;
|
||||
|
||||
public SurroundWithCastWorker(Editor editor, PsiExpression expression, DebuggerContextImpl context, final ProgressIndicator indicator) {
|
||||
@@ -80,7 +80,7 @@ public class JavaWithRuntimeCastSurrounder extends JavaExpressionSurrounder {
|
||||
}
|
||||
|
||||
@Override
|
||||
protected void typeCalculationFinished(@Nullable final PsiClass type) {
|
||||
protected void typeCalculationFinished(@Nullable final PsiType type) {
|
||||
if (type == null) {
|
||||
return;
|
||||
}
|
||||
@@ -94,9 +94,9 @@ public class JavaWithRuntimeCastSurrounder extends JavaExpressionSurrounder {
|
||||
try {
|
||||
PsiElementFactory factory = JavaPsiFacade.getInstance(myElement.getProject()).getElementFactory();
|
||||
PsiParenthesizedExpression parenth =
|
||||
(PsiParenthesizedExpression)factory.createExpressionFromText("((" + type.getQualifiedName() + ")expr)", null);
|
||||
PsiTypeCastExpression cast = (PsiTypeCastExpression)parenth.getExpression();
|
||||
cast.getOperand().replace(myElement);
|
||||
(PsiParenthesizedExpression)factory.createExpressionFromText("((" + type.getCanonicalText() + ")expr)", null);
|
||||
//noinspection ConstantConditions
|
||||
((PsiTypeCastExpression)parenth.getExpression()).getOperand().replace(myElement);
|
||||
parenth = (PsiParenthesizedExpression)JavaCodeStyleManager.getInstance(project).shortenClassReferences(parenth);
|
||||
PsiExpression expr = (PsiExpression)myElement.replace(parenth);
|
||||
TextRange range = expr.getTextRange();
|
||||
|
||||
+19
-18
@@ -1,5 +1,5 @@
|
||||
/*
|
||||
* Copyright 2000-2009 JetBrains s.r.o.
|
||||
* Copyright 2000-2015 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.
|
||||
@@ -19,6 +19,7 @@ import com.intellij.debugger.DebuggerBundle;
|
||||
import com.intellij.debugger.DebuggerInvocationUtil;
|
||||
import com.intellij.debugger.EvaluatingComputable;
|
||||
import com.intellij.debugger.engine.ContextUtil;
|
||||
import com.intellij.debugger.engine.DebuggerUtils;
|
||||
import com.intellij.debugger.engine.evaluation.EvaluateException;
|
||||
import com.intellij.debugger.engine.evaluation.EvaluateExceptionUtil;
|
||||
import com.intellij.debugger.engine.evaluation.EvaluationContextImpl;
|
||||
@@ -33,7 +34,6 @@ import com.intellij.openapi.progress.ProcessCanceledException;
|
||||
import com.intellij.openapi.progress.ProgressIndicator;
|
||||
import com.intellij.openapi.project.Project;
|
||||
import com.intellij.psi.*;
|
||||
import com.intellij.psi.search.GlobalSearchScope;
|
||||
import com.sun.jdi.ClassType;
|
||||
import com.sun.jdi.InterfaceType;
|
||||
import com.sun.jdi.Type;
|
||||
@@ -43,13 +43,13 @@ import org.jetbrains.annotations.Nullable;
|
||||
/**
|
||||
* @author peter
|
||||
*/
|
||||
public abstract class RuntimeTypeEvaluator extends EditorEvaluationCommand<PsiClass> {
|
||||
public abstract class RuntimeTypeEvaluator extends EditorEvaluationCommand<PsiType> {
|
||||
public RuntimeTypeEvaluator(@Nullable Editor editor, PsiElement expression, DebuggerContextImpl context, final ProgressIndicator indicator) {
|
||||
super(editor, expression, context, indicator);
|
||||
}
|
||||
|
||||
public void threadAction() {
|
||||
PsiClass type = null;
|
||||
PsiType type = null;
|
||||
try {
|
||||
type = evaluate();
|
||||
}
|
||||
@@ -62,10 +62,10 @@ public abstract class RuntimeTypeEvaluator extends EditorEvaluationCommand<PsiCl
|
||||
}
|
||||
}
|
||||
|
||||
protected abstract void typeCalculationFinished(@Nullable PsiClass type);
|
||||
protected abstract void typeCalculationFinished(@Nullable PsiType type);
|
||||
|
||||
@Nullable
|
||||
protected PsiClass evaluate(final EvaluationContextImpl evaluationContext) throws EvaluateException {
|
||||
protected PsiType evaluate(final EvaluationContextImpl evaluationContext) throws EvaluateException {
|
||||
final Project project = evaluationContext.getProject();
|
||||
|
||||
ExpressionEvaluator evaluator = DebuggerInvocationUtil.commitAndRunReadAction(project, new EvaluatingComputable<ExpressionEvaluator>() {
|
||||
@@ -82,36 +82,37 @@ public abstract class RuntimeTypeEvaluator extends EditorEvaluationCommand<PsiCl
|
||||
throw EvaluateExceptionUtil.createEvaluateException(DebuggerBundle.message("evaluation.error.surrounded.expression.null"));
|
||||
}
|
||||
|
||||
public static PsiClass getCastableRuntimeType(Project project, Value value) {
|
||||
@Nullable
|
||||
public static PsiType getCastableRuntimeType(Project project, Value value) {
|
||||
Type type = value.type();
|
||||
PsiClass psiClass = findPsiClass(project, type);
|
||||
if (psiClass != null) {
|
||||
return psiClass;
|
||||
PsiType psiType = findPsiType(project, type);
|
||||
if (psiType != null) {
|
||||
return psiType;
|
||||
}
|
||||
|
||||
if (type instanceof ClassType) {
|
||||
ClassType superclass = ((ClassType)type).superclass();
|
||||
if (superclass != null && !CommonClassNames.JAVA_LANG_OBJECT.equals(superclass.name())) {
|
||||
psiClass = findPsiClass(project, superclass);
|
||||
if (psiClass != null) {
|
||||
return psiClass;
|
||||
psiType = findPsiType(project, superclass);
|
||||
if (psiType != null) {
|
||||
return psiType;
|
||||
}
|
||||
}
|
||||
|
||||
for (InterfaceType interfaceType : ((ClassType)type).interfaces()) {
|
||||
psiClass = findPsiClass(project, interfaceType);
|
||||
if (psiClass != null) {
|
||||
return psiClass;
|
||||
psiType = findPsiType(project, interfaceType);
|
||||
if (psiType != null) {
|
||||
return psiType;
|
||||
}
|
||||
}
|
||||
}
|
||||
return null;
|
||||
}
|
||||
|
||||
private static PsiClass findPsiClass(Project project, Type type) {
|
||||
private static PsiType findPsiType(Project project, Type type) {
|
||||
AccessToken token = ReadAction.start();
|
||||
try {
|
||||
return JavaPsiFacade.getInstance(project).findClass(type.name().replace('$', '.'), GlobalSearchScope.allScope(project));
|
||||
return DebuggerUtils.getType(type.name().replace('$', '.'), project);
|
||||
}
|
||||
finally {
|
||||
token.finish();
|
||||
|
||||
+4
-7
@@ -1,5 +1,5 @@
|
||||
/*
|
||||
* Copyright 2000-2009 JetBrains s.r.o.
|
||||
* Copyright 2000-2015 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.
|
||||
@@ -92,11 +92,11 @@ public class DefaultCodeFragmentFactory extends CodeFragmentFactory {
|
||||
if (debuggerSession != null) {
|
||||
final Semaphore semaphore = new Semaphore();
|
||||
semaphore.down();
|
||||
final AtomicReference<PsiClass> nameRef = new AtomicReference<PsiClass>();
|
||||
final AtomicReference<PsiType> nameRef = new AtomicReference<PsiType>();
|
||||
final RuntimeTypeEvaluator worker =
|
||||
new RuntimeTypeEvaluator(null, expression, debuggerContext, ProgressManager.getInstance().getProgressIndicator()) {
|
||||
@Override
|
||||
protected void typeCalculationFinished(@Nullable PsiClass type) {
|
||||
protected void typeCalculationFinished(@Nullable PsiType type) {
|
||||
nameRef.set(type);
|
||||
semaphore.up();
|
||||
}
|
||||
@@ -106,10 +106,7 @@ public class DefaultCodeFragmentFactory extends CodeFragmentFactory {
|
||||
ProgressManager.checkCanceled();
|
||||
if (semaphore.waitFor(20)) break;
|
||||
}
|
||||
final PsiClass psiClass = nameRef.get();
|
||||
if (psiClass != null) {
|
||||
return JavaPsiFacade.getElementFactory(project).createType(psiClass);
|
||||
}
|
||||
return nameRef.get();
|
||||
}
|
||||
return null;
|
||||
}
|
||||
|
||||
+3
-2
@@ -219,16 +219,17 @@ public class DebuggerTreeNodeExpression {
|
||||
|
||||
Project project = expression.getProject();
|
||||
|
||||
PsiClass type = RuntimeTypeEvaluator.getCastableRuntimeType(project, value);
|
||||
PsiType type = RuntimeTypeEvaluator.getCastableRuntimeType(project, value);
|
||||
if (type == null) {
|
||||
return expression;
|
||||
}
|
||||
|
||||
PsiElementFactory elementFactory = JavaPsiFacade.getElementFactory(project);
|
||||
String typeName = type.getQualifiedName();
|
||||
String typeName = type.getCanonicalText();
|
||||
try {
|
||||
PsiParenthesizedExpression parenthExpression = (PsiParenthesizedExpression)elementFactory.createExpressionFromText(
|
||||
"((" + typeName + ")expression)", null);
|
||||
//noinspection ConstantConditions
|
||||
((PsiTypeCastExpression)parenthExpression.getExpression()).getOperand().replace(expression);
|
||||
Set<String> imports = expression.getUserData(ADDITIONAL_IMPORTS_KEY);
|
||||
if (imports == null) {
|
||||
|
||||
@@ -158,16 +158,21 @@ public class ClassRenderer extends NodeRendererImpl{
|
||||
final ObjectReference objRef = (ObjectReference)value;
|
||||
final ReferenceType refType = objRef.referenceType();
|
||||
// default ObjectReference processing
|
||||
final List<Field> fields = refType.allFields();
|
||||
if (fields.size() > 0) {
|
||||
for (final Field field : fields) {
|
||||
if (!shouldDisplay(evaluationContext, objRef, field)) {
|
||||
continue;
|
||||
List<Field> fields = refType.allFields();
|
||||
if (!fields.isEmpty()) {
|
||||
boolean empty = true;
|
||||
for (Field field : fields) {
|
||||
if (shouldDisplay(evaluationContext, objRef, field)) {
|
||||
children.add(nodeManager.createNode(
|
||||
createFieldDescriptor(parentDescriptor, nodeDescriptorFactory, objRef, field, evaluationContext), evaluationContext));
|
||||
empty = false;
|
||||
}
|
||||
children.add(nodeManager.createNode(createFieldDescriptor(parentDescriptor, nodeDescriptorFactory, objRef, field, evaluationContext), evaluationContext));
|
||||
}
|
||||
|
||||
if (XDebuggerSettingsManager.getInstance().getDataViewSettings().isSortValues()) {
|
||||
if (empty) {
|
||||
children.add(nodeManager.createMessageNode(DebuggerBundle.message("message.node.class.no.fields.to.display")));
|
||||
}
|
||||
else if (XDebuggerSettingsManager.getInstance().getDataViewSettings().isSortValues()) {
|
||||
Collections.sort(children, NodeManagerImpl.getNodeComparator());
|
||||
}
|
||||
}
|
||||
|
||||
+4
-4
@@ -1,5 +1,5 @@
|
||||
/*
|
||||
* Copyright 2000-2014 JetBrains s.r.o.
|
||||
* Copyright 2000-2015 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.
|
||||
@@ -36,15 +36,15 @@ public class GutterIconTooltipHelper {
|
||||
private GutterIconTooltipHelper() {
|
||||
}
|
||||
|
||||
public static String composeText(@NotNull PsiElement[] elements, String start, final String pattern) {
|
||||
public static String composeText(@NotNull PsiElement[] elements, @NotNull String start, @NotNull String pattern) {
|
||||
return composeText(Arrays.asList(elements), start, pattern);
|
||||
}
|
||||
|
||||
public static String composeText(@NotNull Iterable<? extends PsiElement> elements, String start, final String pattern) {
|
||||
public static String composeText(@NotNull Iterable<? extends PsiElement> elements, @NotNull String start, @NotNull String pattern) {
|
||||
return composeText(elements, start, pattern, "");
|
||||
}
|
||||
|
||||
public static String composeText(@NotNull Iterable<? extends PsiElement> elements, String start, final String pattern, String postfix) {
|
||||
public static String composeText(@NotNull Iterable<? extends PsiElement> elements, @NotNull String start, @NotNull String pattern, @NotNull String postfix) {
|
||||
@NonNls StringBuilder result = new StringBuilder();
|
||||
result.append("<html><body>");
|
||||
result.append(start);
|
||||
|
||||
@@ -15,6 +15,8 @@
|
||||
*/
|
||||
package com.intellij.psi.impl;
|
||||
|
||||
import com.intellij.openapi.util.Pair;
|
||||
import com.intellij.openapi.util.Ref;
|
||||
import com.intellij.psi.*;
|
||||
import com.intellij.psi.search.searches.ClassInheritorsSearch;
|
||||
import com.intellij.psi.util.MethodSignature;
|
||||
@@ -64,11 +66,12 @@ public class FindSuperElementsHelper {
|
||||
}
|
||||
|
||||
public static PsiMethod getSiblingInheritedViaSubClass(@NotNull PsiMethod method) {
|
||||
return getSiblingInheritedViaSubClass(method, createSubClassCache());
|
||||
return Pair.getFirst(getSiblingInheritedViaSubClass(method, createSubClassCache()));
|
||||
}
|
||||
|
||||
public static PsiMethod getSiblingInheritedViaSubClass(@NotNull final PsiMethod method,
|
||||
@NotNull Map<PsiClass, PsiClass> subClassCache) {
|
||||
// returns super method, sub class
|
||||
public static Pair<PsiMethod, PsiClass> getSiblingInheritedViaSubClass(@NotNull final PsiMethod method,
|
||||
@NotNull Map<PsiClass, PsiClass> subClassCache) {
|
||||
if (!method.hasModifierProperty(PsiModifier.PUBLIC)) return null;
|
||||
if (method.hasModifierProperty(PsiModifier.STATIC)) return null;
|
||||
final PsiClass containingClass = method.getContainingClass();
|
||||
@@ -77,7 +80,7 @@ public class FindSuperElementsHelper {
|
||||
return null;
|
||||
}
|
||||
final Collection<PsiAnchor> checkedInterfaces = new THashSet<PsiAnchor>();
|
||||
final PsiMethod[] result = new PsiMethod[1];
|
||||
final Ref<Pair<PsiMethod, PsiClass>> result = Ref.create();
|
||||
ClassInheritorsSearch.search(containingClass, containingClass.getUseScope(), true, true, false).forEach(new Processor<PsiClass>() {
|
||||
@Override
|
||||
public boolean process(PsiClass inheritor) {
|
||||
@@ -107,14 +110,14 @@ public class FindSuperElementsHelper {
|
||||
if (!isOverridden) {
|
||||
continue;
|
||||
}
|
||||
result[0] = superMethod;
|
||||
result.set(Pair.create(superMethod, inheritor));
|
||||
return false;
|
||||
}
|
||||
}
|
||||
return true;
|
||||
}
|
||||
});
|
||||
return result[0];
|
||||
return result.get();
|
||||
}
|
||||
|
||||
@NotNull
|
||||
|
||||
@@ -184,12 +184,14 @@ public class JavaLineMarkerProvider implements LineMarkerProvider {
|
||||
boolean canHaveSiblingSuper = !method.hasModifierProperty(PsiModifier.ABSTRACT) && !method.hasModifierProperty(PsiModifier.STATIC) && method.hasModifierProperty(PsiModifier.PUBLIC)&& !method.hasModifierProperty(PsiModifier.FINAL)&& !method.hasModifierProperty(PsiModifier.NATIVE);
|
||||
if (!canHaveSiblingSuper) continue;
|
||||
|
||||
PsiMethod siblingInheritedViaSubClass = FindSuperElementsHelper.getSiblingInheritedViaSubClass(method, subClassCache);
|
||||
PsiMethod siblingInheritedViaSubClass = Pair.getFirst(FindSuperElementsHelper.getSiblingInheritedViaSubClass(method, subClassCache));
|
||||
if (siblingInheritedViaSubClass == null) {
|
||||
continue;
|
||||
}
|
||||
PsiElement range = getMethodRange(method);
|
||||
LineMarkerInfo info = createSuperMethodLineMarkerInfo(range, AllIcons.Gutter.ImplementingMethod, Pass.UPDATE_OVERRIDEN_MARKERS);
|
||||
ArrowUpLineMarkerInfo upInfo = new ArrowUpLineMarkerInfo(range, AllIcons.Gutter.ImplementingMethod, MarkerType.SIBLING_OVERRIDING_METHOD,
|
||||
Pass.UPDATE_OVERRIDEN_MARKERS);
|
||||
LineMarkerInfo info = NavigateAction.setNavigateAction(upInfo, "Go to super method", IdeActions.ACTION_GOTO_SUPER);
|
||||
result.add(info);
|
||||
}
|
||||
}
|
||||
|
||||
@@ -33,8 +33,10 @@ import com.intellij.openapi.progress.ProgressIndicator;
|
||||
import com.intellij.openapi.progress.ProgressManager;
|
||||
import com.intellij.openapi.project.DumbService;
|
||||
import com.intellij.openapi.util.Computable;
|
||||
import com.intellij.openapi.util.Pair;
|
||||
import com.intellij.psi.*;
|
||||
import com.intellij.psi.impl.FindSuperElementsHelper;
|
||||
import com.intellij.psi.presentation.java.ClassPresentationUtil;
|
||||
import com.intellij.psi.search.PsiElementProcessor;
|
||||
import com.intellij.psi.search.PsiElementProcessorAdapter;
|
||||
import com.intellij.psi.search.SearchScope;
|
||||
@@ -54,6 +56,7 @@ import org.jetbrains.annotations.Nullable;
|
||||
|
||||
import javax.swing.*;
|
||||
import java.awt.event.MouseEvent;
|
||||
import java.text.MessageFormat;
|
||||
import java.util.Arrays;
|
||||
import java.util.Comparator;
|
||||
|
||||
@@ -119,6 +122,24 @@ public class MarkerType {
|
||||
navigateToOverridingMethod(e, method, method != element.getParent());
|
||||
}
|
||||
});
|
||||
static final MarkerType SIBLING_OVERRIDING_METHOD = new MarkerType("SIBLING_OVERRIDING_METHOD", new NullableFunction<PsiElement, String>() {
|
||||
@Override
|
||||
public String fun(PsiElement element) {
|
||||
PsiElement parent = getParentMethod(element);
|
||||
if (!(parent instanceof PsiMethod)) return null;
|
||||
PsiMethod method = (PsiMethod)parent;
|
||||
|
||||
return calculateOverridingSiblingMethodTooltip(method);
|
||||
}
|
||||
}, new LineMarkerNavigator() {
|
||||
@Override
|
||||
public void browse(MouseEvent e, PsiElement element) {
|
||||
PsiElement parent = getParentMethod(element);
|
||||
if (!(parent instanceof PsiMethod)) return;
|
||||
PsiMethod method = (PsiMethod)parent;
|
||||
navigateToSiblingOverridingMethod(e, method);
|
||||
}
|
||||
});
|
||||
|
||||
@Nullable
|
||||
private static String calculateOverridingMethodTooltip(@NotNull PsiMethod method, boolean acceptSelf) {
|
||||
@@ -139,6 +160,22 @@ public class MarkerType {
|
||||
}
|
||||
return composeText(superMethods, "", DaemonBundle.message(key), IdeActions.ACTION_GOTO_SUPER);
|
||||
}
|
||||
@Nullable
|
||||
private static String calculateOverridingSiblingMethodTooltip(@NotNull PsiMethod method) {
|
||||
Pair<PsiMethod, PsiClass> pair =
|
||||
FindSuperElementsHelper.getSiblingInheritedViaSubClass(method, FindSuperElementsHelper.createSubClassCache());
|
||||
if (pair == null) return null;
|
||||
PsiMethod superMethod = pair.getFirst();
|
||||
PsiClass subClass = pair.getSecond();
|
||||
boolean isAbstract = method.hasModifierProperty(PsiModifier.ABSTRACT);
|
||||
boolean isSuperAbstract = superMethod.hasModifierProperty(PsiModifier.ABSTRACT);
|
||||
|
||||
String postfix = MessageFormat.format(" via sub-class <a href=\"#javaClass/{0}\">{0}</a>", ClassPresentationUtil.getNameForClass(subClass, false));
|
||||
@NonNls String pattern = DaemonBundle.message(isSuperAbstract && !isAbstract ?
|
||||
"method.implements" :
|
||||
"method.overrides") + postfix;
|
||||
return composeText(new PsiElement[]{superMethod}, "", pattern, IdeActions.ACTION_GOTO_SUPER);
|
||||
}
|
||||
|
||||
@NotNull
|
||||
private static String composeText(@NotNull PsiElement[] methods, @NotNull String start, @NotNull String pattern, @NotNull String actionId) {
|
||||
@@ -159,6 +196,14 @@ public class MarkerType {
|
||||
DaemonBundle.message("navigation.findUsages.title.super.method", method.getName()),
|
||||
new MethodCellRenderer(showMethodNames));
|
||||
}
|
||||
private static void navigateToSiblingOverridingMethod(MouseEvent e, @NotNull PsiMethod method) {
|
||||
PsiMethod superMethod = FindSuperElementsHelper.getSiblingInheritedViaSubClass(method);
|
||||
if (superMethod == null) return;
|
||||
PsiElementListNavigator.openTargets(e, new NavigatablePsiElement[]{superMethod},
|
||||
DaemonBundle.message("navigation.title.super.method", method.getName()),
|
||||
DaemonBundle.message("navigation.findUsages.title.super.method", method.getName()),
|
||||
new MethodCellRenderer(false));
|
||||
}
|
||||
|
||||
@NotNull
|
||||
private static PsiMethod[] composeSuperMethods(@NotNull PsiMethod method, boolean acceptSelf) {
|
||||
|
||||
@@ -702,9 +702,9 @@ public abstract class AbstractJavaBlock extends AbstractBlock implements JavaBlo
|
||||
ASTNode child = node.getFirstChildNode();
|
||||
while (child != null) {
|
||||
if (!FormatterUtil.containsWhiteSpacesOnly(child)) {
|
||||
if (child.getElementType() == JavaElementType.METHOD_CALL_EXPRESSION || child.getElementType() ==
|
||||
JavaElementType
|
||||
.REFERENCE_EXPRESSION) {
|
||||
IElementType type = child.getElementType();
|
||||
if (type == JavaElementType.METHOD_CALL_EXPRESSION ||
|
||||
type == JavaElementType.REFERENCE_EXPRESSION) {
|
||||
collectNodes(nodes, child);
|
||||
}
|
||||
else {
|
||||
@@ -861,10 +861,15 @@ public abstract class AbstractJavaBlock extends AbstractBlock implements JavaBlo
|
||||
@NotNull final List<Block> result,
|
||||
@NotNull ASTNode child,
|
||||
@NotNull final WrappingStrategy wrappingStrategy,
|
||||
final boolean doAlign) {
|
||||
final Indent externalIndent = Indent.getNoneIndent();
|
||||
final Indent internalIndent = Indent.getContinuationWithoutFirstIndent(myIndentSettings.USE_RELATIVE_INDENTS);
|
||||
final Indent internalIndentEnforcedToChildren = Indent.getIndent(Indent.Type.CONTINUATION, myIndentSettings.USE_RELATIVE_INDENTS, true);
|
||||
final boolean doAlign)
|
||||
{
|
||||
Indent externalIndent = Indent.getNoneIndent();
|
||||
Indent internalIndent = Indent.getContinuationWithoutFirstIndent(myIndentSettings.USE_RELATIVE_INDENTS);
|
||||
|
||||
if (isInsideMethodCallParenthesis(child)) {
|
||||
internalIndent = Indent.getSmartIndent(Indent.Type.CONTINUATION);
|
||||
}
|
||||
|
||||
AlignmentStrategy alignmentStrategy = AlignmentStrategy.wrap(createAlignment(doAlign, null), JavaTokenType.COMMA);
|
||||
setChildIndent(internalIndent);
|
||||
setChildAlignment(alignmentStrategy.getAlignment(null));
|
||||
@@ -889,7 +894,6 @@ public abstract class AbstractJavaBlock extends AbstractBlock implements JavaBlo
|
||||
|
||||
ASTNode prev = child;
|
||||
boolean afterAnonymousClass = false;
|
||||
final boolean enforceIndent = shouldEnforceIndentToChildren();
|
||||
while (child != null) {
|
||||
isAfterIncomplete = isAfterIncomplete || child.getElementType() == TokenType.ERROR_ELEMENT ||
|
||||
child.getElementType() == JavaElementType.EMPTY_EXPRESSION;
|
||||
@@ -898,18 +902,17 @@ public abstract class AbstractJavaBlock extends AbstractBlock implements JavaBlo
|
||||
result.add(createJavaBlock(child, mySettings, myJavaSettings, externalIndent, null, bracketAlignment));
|
||||
}
|
||||
else if (child.getElementType() == to) {
|
||||
result.add(createJavaBlock(child, mySettings, myJavaSettings,
|
||||
isAfterIncomplete && !afterAnonymousClass ? internalIndent : externalIndent,
|
||||
null,
|
||||
isAfterIncomplete ? alignmentStrategy.getAlignment(null) : bracketAlignment)
|
||||
);
|
||||
Block block = createJavaBlock(child, mySettings, myJavaSettings,
|
||||
isAfterIncomplete && !afterAnonymousClass ? internalIndent : externalIndent,
|
||||
null,
|
||||
isAfterIncomplete ? alignmentStrategy.getAlignment(null) : bracketAlignment);
|
||||
result.add(block);
|
||||
return child;
|
||||
}
|
||||
else {
|
||||
final IElementType elementType = child.getElementType();
|
||||
Indent indentToUse = enforceIndent ? internalIndentEnforcedToChildren : internalIndent;
|
||||
AlignmentStrategy alignmentStrategyToUse = canUseAnonymousClassAlignment(child) ? anonymousClassStrategy : alignmentStrategy;
|
||||
processChild(result, child, alignmentStrategyToUse.getAlignment(elementType), wrappingStrategy.getWrap(elementType), indentToUse);
|
||||
processChild(result, child, alignmentStrategyToUse.getAlignment(elementType), wrappingStrategy.getWrap(elementType), internalIndent);
|
||||
if (to == null) {//process only one statement
|
||||
return child;
|
||||
}
|
||||
@@ -926,6 +929,15 @@ public abstract class AbstractJavaBlock extends AbstractBlock implements JavaBlo
|
||||
return prev;
|
||||
}
|
||||
|
||||
private boolean isInsideMethodCallParenthesis(ASTNode child) {
|
||||
ASTNode currentPredecessor = child.getTreeParent();
|
||||
if (currentPredecessor != null) {
|
||||
currentPredecessor = currentPredecessor.getTreeParent();
|
||||
return currentPredecessor != null && currentPredecessor.getElementType() == JavaElementType.METHOD_CALL_EXPRESSION;
|
||||
}
|
||||
return false;
|
||||
}
|
||||
|
||||
private static boolean canUseAnonymousClassAlignment(@NotNull ASTNode child) {
|
||||
// The general idea is to handle situations like below:
|
||||
// test(new Runnable() {
|
||||
@@ -967,19 +979,6 @@ public abstract class AbstractJavaBlock extends AbstractBlock implements JavaBlo
|
||||
return true;
|
||||
}
|
||||
|
||||
private boolean shouldEnforceIndentToChildren() {
|
||||
if (myNode.getElementType() != JavaElementType.EXPRESSION_LIST) {
|
||||
return false;
|
||||
}
|
||||
ASTNode parent = myNode.getTreeParent();
|
||||
if (parent == null || parent.getElementType() != JavaElementType.METHOD_CALL_EXPRESSION) {
|
||||
return false;
|
||||
}
|
||||
|
||||
PsiExpression[] arguments = ((PsiExpressionList)myNode.getPsi()).getExpressions();
|
||||
return JavaFormatterUtil.hasMultilineArguments(arguments) && JavaFormatterUtil.isMultilineExceptArguments(arguments);
|
||||
}
|
||||
|
||||
private static boolean isAnonymousClass(@Nullable ASTNode node) {
|
||||
if (node == null || node.getElementType() != JavaElementType.NEW_EXPRESSION) {
|
||||
return false;
|
||||
|
||||
+5
-3
@@ -75,8 +75,10 @@ class ChainMethodCallsBlockBuilder {
|
||||
for (int i = 0; i < methodCall.size(); i++) {
|
||||
ChainedCallChunk currentCallChunk = methodCall.get(i);
|
||||
if (isMethodCall(currentCallChunk)) {
|
||||
if (myWrap == null) myWrap = createCallChunkWrap(i, methodCall);
|
||||
if (myChainedCallsAlignment == null) myChainedCallsAlignment = createCallChunkAlignment(i, methodCall);
|
||||
if (myWrap == null)
|
||||
myWrap = createCallChunkWrap(i, methodCall);
|
||||
if (myChainedCallsAlignment == null)
|
||||
myChainedCallsAlignment = createCallChunkAlignment(i, methodCall);
|
||||
}
|
||||
else {
|
||||
myWrap = null;
|
||||
@@ -137,7 +139,7 @@ class ChainMethodCallsBlockBuilder {
|
||||
|
||||
private boolean isMethodCall(@NotNull ChainedCallChunk callChunk) {
|
||||
List<ASTNode> nodes = callChunk.nodes;
|
||||
return !nodes.isEmpty() && nodes.get(nodes.size() - 1).getElementType() == JavaElementType.EXPRESSION_LIST;
|
||||
return nodes.size() >= 3 && nodes.get(2).getElementType() == JavaElementType.EXPRESSION_LIST;
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
@@ -96,7 +96,7 @@ public class JavaGotoSuperTest extends LightDaemonAnalyzerTestCase {
|
||||
assertSame(MarkerType.OVERRIDDEN_METHOD.getNavigationHandler(), iMarker.getNavigationHandler());
|
||||
|
||||
LineMarkerInfo aMarker = findMarkerWithElement(markers, aRun.getNameIdentifier());
|
||||
assertSame(MarkerType.OVERRIDING_METHOD.getNavigationHandler(), aMarker.getNavigationHandler());
|
||||
assertSame(MarkerType.SIBLING_OVERRIDING_METHOD.getNavigationHandler(), aMarker.getNavigationHandler());
|
||||
}
|
||||
|
||||
private static LineMarkerInfo findMarkerWithElement(List<LineMarkerInfo> markers, PsiElement psiMethod) {
|
||||
|
||||
+38
-3
@@ -48,7 +48,42 @@ public class JavaFormatterAlignmentTest extends AbstractJavaFormatterTest {
|
||||
" .foo();"
|
||||
);
|
||||
}
|
||||
|
||||
public void testChainedMethodWithComments() throws Exception {
|
||||
getSettings().ALIGN_MULTILINE_CHAINED_METHODS = true;
|
||||
doMethodTest("AAAAA.b()\n" +
|
||||
".c() // comment after line\n" +
|
||||
".d()\n" +
|
||||
".e();",
|
||||
|
||||
"AAAAA.b()\n" +
|
||||
" .c() // comment after line\n" +
|
||||
" .d()\n" +
|
||||
" .e();");
|
||||
}
|
||||
|
||||
public void testChainedMethodWithBlockComment() {
|
||||
getSettings().ALIGN_MULTILINE_CHAINED_METHODS = true;
|
||||
doTextTest("class X {\n" +
|
||||
" public void test() {\n" +
|
||||
" AAAAAA.b()\n" +
|
||||
".c()\n" +
|
||||
".d()\n" +
|
||||
" /* simple block comment */\n" +
|
||||
".e();\n" +
|
||||
" }\n" +
|
||||
"}",
|
||||
"class X {\n" +
|
||||
" public void test() {\n" +
|
||||
" AAAAAA.b()\n" +
|
||||
" .c()\n" +
|
||||
" .d()\n" +
|
||||
" /* simple block comment */\n" +
|
||||
" .e();\n" +
|
||||
" }\n" +
|
||||
"}");
|
||||
}
|
||||
|
||||
public void testMultipleMethodAnnotationsCommentedInTheMiddle() throws Exception {
|
||||
getSettings().BLANK_LINES_AFTER_CLASS_HEADER = 1;
|
||||
getSettings().getRootSettings().getIndentOptions(StdFileTypes.JAVA).INDENT_SIZE = 4;
|
||||
@@ -256,7 +291,7 @@ public class JavaFormatterAlignmentTest extends AbstractJavaFormatterTest {
|
||||
"}"
|
||||
);
|
||||
}
|
||||
|
||||
|
||||
public void testAnnotatedAndNonAnnotatedFieldsInColumnsAlignment() {
|
||||
// Inspired by IDEA-60237
|
||||
|
||||
@@ -281,10 +316,10 @@ public class JavaFormatterAlignmentTest extends AbstractJavaFormatterTest {
|
||||
"}"
|
||||
);
|
||||
}
|
||||
|
||||
|
||||
public void testAlignThrowsKeyword() throws Exception {
|
||||
// Inspired by IDEA-63820
|
||||
|
||||
|
||||
getSettings().ALIGN_THROWS_KEYWORD = true;
|
||||
doClassTest(
|
||||
"public void test()\n" +
|
||||
|
||||
+106
@@ -0,0 +1,106 @@
|
||||
/*
|
||||
* Copyright 2000-2015 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.formatter.java;
|
||||
|
||||
public class JavaFormatterMultilineMethodCallParamsTest extends AbstractJavaFormatterTest {
|
||||
|
||||
|
||||
public void testChainedMethodInsideCall() {
|
||||
doMethodTest(
|
||||
"call(new StringBuilder()\n" +
|
||||
".append(\"aaa\")\n" +
|
||||
".append(\"bbbb\"));",
|
||||
"call(new StringBuilder()\n" +
|
||||
" .append(\"aaa\")\n" +
|
||||
" .append(\"bbbb\"));"
|
||||
);
|
||||
}
|
||||
|
||||
public void IGNORED_testChainedMethodInsideCall_WithRParenOnNewLine() {
|
||||
doMethodTest(
|
||||
"call(new StringBuilder()\n" +
|
||||
".append(\"aaa\")\n" +
|
||||
".append(\"bbbb\")\n" +
|
||||
");",
|
||||
"call(new StringBuilder()\n" +
|
||||
" .append(\"aaa\")\n" +
|
||||
" .append(\"bbbb\")\n" +
|
||||
");"
|
||||
);
|
||||
}
|
||||
|
||||
public void testChainedMethodInsideCall_Shifted() {
|
||||
doMethodTest(
|
||||
"call(new StringBuilder()\n" +
|
||||
".append(\"aaa\")\n" +
|
||||
".append(\"bbbb\"),\n" +
|
||||
"\"aaaa\");",
|
||||
"call(new StringBuilder()\n" +
|
||||
" .append(\"aaa\")\n" +
|
||||
" .append(\"bbbb\"),\n" +
|
||||
" \"aaaa\");"
|
||||
);
|
||||
}
|
||||
|
||||
public void testChainedMethodInsideCall_Shifted_WithRParentOnNewLine() {
|
||||
doMethodTest(
|
||||
"call(new StringBuilder()\n" +
|
||||
".append(\"aaa\")\n" +
|
||||
".append(\"bbbb\"),\n" +
|
||||
"\"aaaa\"\n" +
|
||||
");",
|
||||
"call(new StringBuilder()\n" +
|
||||
" .append(\"aaa\")\n" +
|
||||
" .append(\"bbbb\"),\n" +
|
||||
" \"aaaa\"\n" +
|
||||
");"
|
||||
);
|
||||
}
|
||||
|
||||
public void testAnonClassAsParameter() {
|
||||
doMethodTest(
|
||||
"call(new Runnable() {\n" +
|
||||
"@Override\n" +
|
||||
"public void run() {\n" +
|
||||
"}\n" +
|
||||
"});",
|
||||
"call(new Runnable() {\n" +
|
||||
" @Override\n" +
|
||||
" public void run() {\n" +
|
||||
" }\n" +
|
||||
"});"
|
||||
);
|
||||
}
|
||||
|
||||
public void testAnonClassWithRParent_OnNextLine() {
|
||||
doMethodTest(
|
||||
"foo(new Runnable() {\n" +
|
||||
" @Override\n" +
|
||||
" public void run() {\n" +
|
||||
" }\n" +
|
||||
"}\n" +
|
||||
");\n",
|
||||
"foo(new Runnable() {\n" +
|
||||
" @Override\n" +
|
||||
" public void run() {\n" +
|
||||
" }\n" +
|
||||
" }\n" +
|
||||
");\n"
|
||||
);
|
||||
}
|
||||
|
||||
|
||||
}
|
||||
@@ -33,6 +33,7 @@ import com.intellij.openapi.project.Project
|
||||
import com.intellij.openapi.util
|
||||
import com.intellij.openapi.util.*
|
||||
import com.intellij.openapi.util.Pair
|
||||
import com.intellij.openapi.util.registry.Registry
|
||||
import com.intellij.openapi.vfs.VirtualFile
|
||||
import com.intellij.openapi.vfs.newvfs.impl.VfsRootAccess
|
||||
import com.intellij.util.ArrayUtilRt
|
||||
@@ -240,15 +241,14 @@ abstract class ComponentStoreImpl : IComponentStore {
|
||||
|
||||
val defaultState = if (stateSpec.defaultStateAsResource) getDefaultState(component, name, stateClass) else null
|
||||
val storageSpecs = getStorageSpecs(component, stateSpec, StateStorageOperation.READ)
|
||||
val stateStorageChooser = component as? StateStorageChooserEx
|
||||
val storageChooser = component as? StateStorageChooserEx
|
||||
for (storageSpec in storageSpecs) {
|
||||
val resolution = if (stateStorageChooser == null) Resolution.DO else stateStorageChooser.getResolution(storageSpec, StateStorageOperation.READ)
|
||||
if (resolution === Resolution.SKIP) {
|
||||
if (storageChooser?.getResolution(storageSpec, StateStorageOperation.READ) == Resolution.SKIP) {
|
||||
continue
|
||||
}
|
||||
|
||||
val storage = storageManager.getStateStorage(storageSpec)
|
||||
var stateGetter = (storage as? StorageBaseEx<*>)?.createGetSession(component, name, stateClass)
|
||||
var stateGetter = if (isUseLoadedStateAsExisting(storageSpec) && Registry.`is`("use.loaded.state.as.existing", false)) (storage as? StorageBaseEx<*>)?.createGetSession(component, name, stateClass) else null
|
||||
var state = if (stateGetter == null) storage.getState(component, name, stateClass, defaultState, reloadData) else stateGetter.getState(defaultState)
|
||||
if (state == null) {
|
||||
if (changedStorages != null && changedStorages.contains(storage)) {
|
||||
@@ -276,6 +276,8 @@ abstract class ComponentStoreImpl : IComponentStore {
|
||||
return name
|
||||
}
|
||||
|
||||
protected open fun isUseLoadedStateAsExisting(storageSpec: Storage): Boolean = true
|
||||
|
||||
protected open fun getPathMacroManagerForDefaults(): PathMacroManager? = null
|
||||
|
||||
private fun <T : Any> getDefaultState(component: Any, componentName: String, stateClass: Class<T>): T? {
|
||||
|
||||
@@ -62,7 +62,7 @@ open class DirectoryBasedStorage(private val myPathMacroSubstitutor: TrackingPat
|
||||
}
|
||||
}
|
||||
|
||||
override fun getState(storageData: Map<String, StateMap>, component: Any?, componentName: String) = getCompositeStateAndArchive(storageData, componentName, mySplitter)
|
||||
override fun getSerializedState(storageData: Map<String, StateMap>, component: Any?, componentName: String, archive: Boolean) = getCompositeStateAndArchive(storageData, componentName, mySplitter)
|
||||
|
||||
override fun loadData(): MutableMap<String, StateMap> {
|
||||
return fromMap(DirectoryStorageUtil.loadFrom(getVirtualFile(), myPathMacroSubstitutor))
|
||||
@@ -174,7 +174,7 @@ open class DirectoryBasedStorage(private val myPathMacroSubstitutor: TrackingPat
|
||||
writeFile(null, this, file, storeElement, LineSeparator.fromString(if (file.exists()) loadFile(file).second else SystemProperties.getLineSeparator()), false)
|
||||
}
|
||||
catch (e: IOException) {
|
||||
StateStorageBase.LOG.error(e)
|
||||
LOG.error(e)
|
||||
}
|
||||
finally {
|
||||
if (element != null) {
|
||||
|
||||
@@ -288,6 +288,8 @@ open class ProjectStoreImpl(override val project: ProjectImpl, private val pathM
|
||||
}
|
||||
|
||||
override fun selectDefaultStorages(storages: Array<Storage>, operation: StateStorageOperation) = selectDefaultStorages(storages, operation, scheme)
|
||||
|
||||
override fun isUseLoadedStateAsExisting(storageSpec: Storage) = storageSpec.file != StoragePathMacros.WORKSPACE_FILE
|
||||
}
|
||||
|
||||
fun selectDefaultStorages(storages: Array<Storage>, operation: StateStorageOperation, scheme: StorageScheme): Array<Storage> {
|
||||
|
||||
@@ -122,8 +122,6 @@ class StateMap private constructor(private val names: Array<String>, private val
|
||||
|
||||
fun isEmpty() = names.isEmpty()
|
||||
|
||||
fun getState(key: String) = get(key) as? Element
|
||||
|
||||
fun hasState(key: String) = get(key) is Element
|
||||
|
||||
public fun hasStates(): Boolean {
|
||||
@@ -152,14 +150,19 @@ class StateMap private constructor(private val names: Array<String>, private val
|
||||
}
|
||||
}
|
||||
|
||||
public fun getStateAndArchive(key: String): Element? {
|
||||
fun getStateAndArchive(key: String) = getState(key, true)
|
||||
|
||||
fun getState(key: String, archive: Boolean = false): Element? {
|
||||
val index = Arrays.binarySearch(names, key)
|
||||
if (index < 0) {
|
||||
return null
|
||||
}
|
||||
|
||||
val state = states.get(index) as? Element ?: return null
|
||||
return if (states.compareAndSet(index, state, archiveState(state))) state else getStateAndArchive(key)
|
||||
if (!archive) {
|
||||
return state
|
||||
}
|
||||
return if (states.compareAndSet(index, state, archiveState(state))) state else getState(key, true)
|
||||
}
|
||||
|
||||
public fun archive(key: String, state: Element?) {
|
||||
|
||||
@@ -28,22 +28,23 @@ abstract class StorageBaseEx<T : Any> : StateStorageBase<T>() {
|
||||
abstract fun archiveState(storageData: T, componentName: String, serializedState: Element?)
|
||||
}
|
||||
|
||||
class StateGetter<S : Any, T : Any>(private val component: PersistentStateComponent<S>, private val componentName: String, private val storageData: T, private val stateClass: Class<S>, private val storage: StorageBaseEx<T>) {
|
||||
class StateGetter<S : Any, T : Any>(private val component: PersistentStateComponent<S>,
|
||||
private val componentName: String,
|
||||
private val storageData: T,
|
||||
private val stateClass: Class<S>,
|
||||
private val storage: StorageBaseEx<T>) {
|
||||
var serializedState: Element? = null
|
||||
|
||||
fun getState(mergeInto: S? = null): S? {
|
||||
LOG.assertTrue(serializedState == null)
|
||||
|
||||
serializedState = storage.getState(storageData, component, componentName)
|
||||
serializedState = storage.getSerializedState(storageData, component, componentName, false)
|
||||
if (serializedState != null) {
|
||||
//System.out.println("open $componentName to read state, ${hashCode()} $storage, ${Thread.currentThread()}")
|
||||
}
|
||||
return storage.deserializeState(serializedState, stateClass, mergeInto)
|
||||
}
|
||||
|
||||
/**
|
||||
* nullable - because PersistentStateComponent can return nullable state
|
||||
*/
|
||||
fun close() {
|
||||
if (serializedState == null) {
|
||||
return
|
||||
|
||||
@@ -37,7 +37,7 @@ abstract class XmlElementStorage protected constructor(protected val fileSpec: S
|
||||
|
||||
protected abstract fun loadLocalData(): Element?
|
||||
|
||||
override final fun getState(storageData: StateMap, component: Any?, componentName: String) = storageData.getState(componentName)
|
||||
override final fun getSerializedState(storageData: StateMap, component: Any?, componentName: String, archive: Boolean) = storageData.getState(componentName, archive)
|
||||
|
||||
override fun archiveState(storageData: StateMap, componentName: String, serializedState: Element?) {
|
||||
storageData.archive(componentName, serializedState)
|
||||
|
||||
@@ -110,7 +110,7 @@ class ApplicationStoreTest {
|
||||
}
|
||||
|
||||
@State(name = "A", storages = arrayOf(Storage(file = "a.xml")))
|
||||
private class A : PersistentStateComponent<Element> {
|
||||
private open class A : PersistentStateComponent<Element> {
|
||||
data class State(@Attribute var foo: String = "", @Attribute var bar: String = "")
|
||||
|
||||
var state = State()
|
||||
@@ -144,6 +144,24 @@ class ApplicationStoreTest {
|
||||
assertThat(file).hasContent("<application>\n <component name=\"A\" foo=\"1\" bar=\"2\" />\n</application>")
|
||||
}
|
||||
|
||||
@Test fun `do not apply to workspace storage - do not save if only format is changed`() {
|
||||
@State(name = "A", storages = arrayOf(Storage(file = StoragePathMacros.WORKSPACE_FILE)))
|
||||
class AWorkspace : A()
|
||||
|
||||
val oldContent = "<application><component name=\"A\" foo=\"old\" deprecated=\"old\"/></application>"
|
||||
val file = writeConfig("workspace.xml", oldContent)
|
||||
val oldModificationTime = file.getLastModifiedTime()
|
||||
testAppConfig.refreshVfs()
|
||||
|
||||
val component = AWorkspace()
|
||||
componentStore.initComponent(component, false)
|
||||
assertThat(component.state).isEqualTo(A.State("old"))
|
||||
|
||||
saveStore()
|
||||
|
||||
assertThat(file).hasContent("<application>\n <component name=\"A\" foo=\"old\" />\n</application>")
|
||||
}
|
||||
|
||||
private fun saveStore() {
|
||||
runInEdtAndWait { componentStore.save(SmartList()) }
|
||||
}
|
||||
@@ -188,7 +206,10 @@ class ApplicationStoreTest {
|
||||
|
||||
override fun setPath(path: String) {
|
||||
storageManager.addMacro(StoragePathMacros.APP_CONFIG, path)
|
||||
storageManager.addMacro(StoragePathMacros.WORKSPACE_FILE, "$path/workspace.xml")
|
||||
}
|
||||
|
||||
override fun isUseLoadedStateAsExisting(storageSpec: Storage) = storageSpec.file != StoragePathMacros.WORKSPACE_FILE
|
||||
}
|
||||
|
||||
abstract class Foo {
|
||||
|
||||
@@ -24,7 +24,7 @@ import org.junit.Test
|
||||
class XmlElementStorageTest {
|
||||
@Test fun testGetStateSucceeded() {
|
||||
val storage = MyXmlElementStorage(tag("root", tag("component", attr("name", "test"), tag("foo"))))
|
||||
val state = storage.getState(this, "test", javaClass<Element>(), null, false)
|
||||
val state = storage.getState(this, "test", javaClass<Element>())
|
||||
assertThat(state).isNotNull()
|
||||
assertThat(state!!.getName()).isEqualTo("component")
|
||||
assertThat(state.getChild("foo")).isNotNull()
|
||||
@@ -32,7 +32,7 @@ class XmlElementStorageTest {
|
||||
|
||||
@Test fun `get state not succeeded`() {
|
||||
val storage = MyXmlElementStorage(tag("root"))
|
||||
val state = storage.getState(this, "test", javaClass<Element>(), null, false)
|
||||
val state = storage.getState(this, "test", javaClass<Element>())
|
||||
assertThat(state).isNull()
|
||||
}
|
||||
|
||||
|
||||
+20
-16
@@ -360,24 +360,28 @@ public class LexerEditorHighlighter implements EditorHighlighter, PrioritizedDoc
|
||||
// Called to determine visual attributes of inserted character prior to starting a write action.
|
||||
// TODO Should be removed when we implement typing without starting write actions.
|
||||
public TextAttributes getAttributes(DocumentImpl document, int offset, char c) {
|
||||
final int segmentIndex;
|
||||
try {
|
||||
segmentIndex = mySegments.findSegmentIndex(offset) - 2;
|
||||
}
|
||||
catch (IndexOutOfBoundsException ex) {
|
||||
throw new IndexOutOfBoundsException(ex.getMessage() + " Lexer: " + myLexer);
|
||||
}
|
||||
int startIndex = Math.max(0, segmentIndex);
|
||||
int startOffset = 0;
|
||||
|
||||
int data;
|
||||
do {
|
||||
data = mySegments.getSegmentData(startIndex);
|
||||
if (isInitialState(data)|| startIndex == 0) break;
|
||||
startIndex--;
|
||||
}
|
||||
while (true);
|
||||
if (mySegments.getSegmentCount() > 0) {
|
||||
final int segmentIndex;
|
||||
try {
|
||||
segmentIndex = mySegments.findSegmentIndex(offset) - 2;
|
||||
}
|
||||
catch (IndexOutOfBoundsException ex) {
|
||||
throw new IndexOutOfBoundsException(ex.getMessage() + " Lexer: " + myLexer);
|
||||
}
|
||||
int startIndex = Math.max(0, segmentIndex);
|
||||
|
||||
int startOffset = mySegments.getSegmentStart(startIndex);
|
||||
int data;
|
||||
do {
|
||||
data = mySegments.getSegmentData(startIndex);
|
||||
if (isInitialState(data)|| startIndex == 0) break;
|
||||
startIndex--;
|
||||
}
|
||||
while (true);
|
||||
|
||||
startOffset = mySegments.getSegmentStart(startIndex);
|
||||
}
|
||||
|
||||
ImmutableText newText = document.getImmutableText().insert(offset, Character.toString(c));
|
||||
|
||||
|
||||
@@ -269,6 +269,10 @@ public abstract class Indent {
|
||||
return myFactory.getIndent(type, spaces, relativeToDirectParent, enforceIndentToChildren);
|
||||
}
|
||||
|
||||
public static Indent getSmartIndent(Type type) {
|
||||
return myFactory.getSmartIndent(type);
|
||||
}
|
||||
|
||||
public static class Type {
|
||||
private final String myName;
|
||||
|
||||
|
||||
@@ -34,4 +34,5 @@ interface IndentFactory {
|
||||
Indent getSpaceIndent(final int spaces, boolean relativeToDirectParent);
|
||||
Indent getIndent(@NotNull Indent.Type type, boolean relativeToDirectParent, boolean enforceIndentToChildren);
|
||||
Indent getIndent(@NotNull Indent.Type type, int spaces, boolean relativeToDirectParent, boolean enforceIndentToChildren);
|
||||
Indent getSmartIndent(@NotNull Indent.Type type);
|
||||
}
|
||||
|
||||
+3
-2
@@ -61,8 +61,9 @@ public class CommonCodeStyleSettingsManager implements JDOMExternalizable {
|
||||
public CommonCodeStyleSettings getCommonSettings(@Nullable Language lang) {
|
||||
Map<Language, CommonCodeStyleSettings> commonSettingsMap = getCommonSettingsMap();
|
||||
CommonCodeStyleSettings settings = commonSettingsMap.get(lang);
|
||||
if (settings == null && lang != null) {
|
||||
settings = commonSettingsMap.get(lang.getBaseLanguage());
|
||||
while (settings == null && lang != null) {
|
||||
lang = lang.getBaseLanguage();
|
||||
settings = commonSettingsMap.get(lang);
|
||||
}
|
||||
if (settings != null) {
|
||||
return settings;
|
||||
|
||||
@@ -0,0 +1,35 @@
|
||||
/*
|
||||
* Copyright 2000-2015 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.formatting;
|
||||
|
||||
public class ExpandableIndent extends IndentImpl {
|
||||
private boolean myEnforceIndent;
|
||||
|
||||
public ExpandableIndent(Type type) {
|
||||
super(type, false, 0, false, true);
|
||||
myEnforceIndent = false;
|
||||
}
|
||||
|
||||
@Override
|
||||
public boolean isEnforceIndentToChildren() {
|
||||
return myEnforceIndent;
|
||||
}
|
||||
|
||||
void setEnforceIndent(boolean value) {
|
||||
myEnforceIndent = value;
|
||||
}
|
||||
|
||||
}
|
||||
@@ -34,6 +34,7 @@ import com.intellij.psi.PsiFile;
|
||||
import com.intellij.psi.codeStyle.CodeStyleSettings;
|
||||
import com.intellij.psi.codeStyle.CommonCodeStyleSettings;
|
||||
import com.intellij.util.containers.ContainerUtil;
|
||||
import com.intellij.util.containers.MultiMap;
|
||||
import com.intellij.util.ui.UIUtil;
|
||||
import gnu.trove.TIntObjectHashMap;
|
||||
import org.jetbrains.annotations.NotNull;
|
||||
@@ -158,6 +159,7 @@ public class FormatProcessor {
|
||||
|
||||
@NotNull
|
||||
private State myCurrentState;
|
||||
private MultiMap<ExpandableIndent, AbstractBlockWrapper> myExpandableIndents;
|
||||
|
||||
public FormatProcessor(final FormattingDocumentModel docModel,
|
||||
Block rootBlock,
|
||||
@@ -248,7 +250,11 @@ public class FormatProcessor {
|
||||
public void format(FormattingModel model, boolean sequentially) {
|
||||
if (sequentially) {
|
||||
AdjustWhiteSpacesState adjustState = new AdjustWhiteSpacesState();
|
||||
adjustState.setNext(new ApplyChangesState(model));
|
||||
ExpandChildrenIndent expandChildrenIndent = new ExpandChildrenIndent();
|
||||
ApplyChangesState applyChangesState = new ApplyChangesState(model);
|
||||
|
||||
expandChildrenIndent.setNext(applyChangesState);
|
||||
adjustState.setNext(expandChildrenIndent);
|
||||
myCurrentState.setNext(adjustState);
|
||||
}
|
||||
else {
|
||||
@@ -284,7 +290,9 @@ public class FormatProcessor {
|
||||
|
||||
@SuppressWarnings({"WhileLoopSpinsOnField"})
|
||||
public void formatWithoutRealModifications(boolean sequentially) {
|
||||
myCurrentState.setNext(new AdjustWhiteSpacesState());
|
||||
AdjustWhiteSpacesState adjustSpace = new AdjustWhiteSpacesState();
|
||||
adjustSpace.setNext(new ExpandChildrenIndent());
|
||||
myCurrentState.setNext(adjustSpace);
|
||||
|
||||
if (sequentially) {
|
||||
return;
|
||||
@@ -1357,6 +1365,8 @@ public class FormatProcessor {
|
||||
root, model, affectedRanges, mySettings, myDefaultIndentOption, interestingOffset, myProgressCallback
|
||||
);
|
||||
myWrapper.setCollectAlignmentsInsideFormattingRange(myReformatContext);
|
||||
|
||||
myExpandableIndents = myWrapper.getExpandableIndentsBlocks();
|
||||
}
|
||||
|
||||
@Override
|
||||
@@ -1526,24 +1536,24 @@ public class FormatProcessor {
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
private static class CaretOffsetUpdater {
|
||||
private final Map<Editor, Integer> myCaretOffsets = new HashMap<Editor, Integer>();
|
||||
|
||||
|
||||
private CaretOffsetUpdater(@NotNull Document document) {
|
||||
Editor[] editors = EditorFactory.getInstance().getEditors(document);
|
||||
for (Editor editor : editors) {
|
||||
myCaretOffsets.put(editor, editor.getCaretModel().getOffset());
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
private void update(@NotNull List<? extends TextChange> changes) {
|
||||
BulkChangesMerger merger = BulkChangesMerger.INSTANCE;
|
||||
for (Map.Entry<Editor, Integer> entry : myCaretOffsets.entrySet()) {
|
||||
entry.setValue(merger.updateOffset(entry.getValue(), changes));
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
private void restoreCaretLocations() {
|
||||
for (Map.Entry<Editor, Integer> entry : myCaretOffsets.entrySet()) {
|
||||
entry.getKey().getCaretModel().moveToOffset(entry.getValue());
|
||||
@@ -1580,4 +1590,80 @@ public class FormatProcessor {
|
||||
myInterestingOffset = interestingOffset;
|
||||
}
|
||||
}
|
||||
|
||||
private class ExpandChildrenIndent extends State {
|
||||
private Iterator<ExpandableIndent> myIterator;
|
||||
|
||||
public ExpandChildrenIndent() {
|
||||
super(FormattingStateId.EXPANDING_CHILDREN_INDENTS);
|
||||
}
|
||||
|
||||
@Override
|
||||
protected void doIteration() {
|
||||
if (myIterator == null) {
|
||||
myIterator = myExpandableIndents.keySet().iterator();
|
||||
}
|
||||
if (!myIterator.hasNext()) {
|
||||
setDone(true);
|
||||
return;
|
||||
}
|
||||
|
||||
final ExpandableIndent indent = myIterator.next();
|
||||
Collection<AbstractBlockWrapper> blocksToExpandIndent = myExpandableIndents.get(indent);
|
||||
if (shouldExpand(blocksToExpandIndent)) {
|
||||
for (AbstractBlockWrapper block : blocksToExpandIndent) {
|
||||
indent.setEnforceIndent(true);
|
||||
reindentNewLineChildren(block);
|
||||
indent.setEnforceIndent(false);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
private boolean shouldExpand(Collection<AbstractBlockWrapper> blocksToExpandIndent) {
|
||||
AbstractBlockWrapper last = null;
|
||||
for (AbstractBlockWrapper block : blocksToExpandIndent) {
|
||||
if (block.getWhiteSpace().containsLineFeeds()) {
|
||||
return true;
|
||||
}
|
||||
last = block;
|
||||
}
|
||||
|
||||
if (last != null) {
|
||||
AbstractBlockWrapper prev = getPreviousBlock(last);
|
||||
return prev != null && prev.getWhiteSpace().containsLineFeeds();
|
||||
}
|
||||
|
||||
return false;
|
||||
}
|
||||
|
||||
private AbstractBlockWrapper getPreviousBlock(AbstractBlockWrapper block) {
|
||||
List<AbstractBlockWrapper> children = block.getParent().getChildren();
|
||||
int nextBlockIndex = children.indexOf(block) + 1;
|
||||
if (nextBlockIndex < children.size()) {
|
||||
return children.get(nextBlockIndex);
|
||||
}
|
||||
return null;
|
||||
}
|
||||
|
||||
private void reindentNewLineChildren(final @NotNull AbstractBlockWrapper block) {
|
||||
if (block instanceof LeafBlockWrapper) {
|
||||
WhiteSpace space = block.getWhiteSpace();
|
||||
|
||||
if (space.containsLineFeeds()) {
|
||||
myCurrentBlock = (LeafBlockWrapper)block;
|
||||
adjustIndent();
|
||||
}
|
||||
}
|
||||
else if (block instanceof CompositeBlockWrapper) {
|
||||
List<AbstractBlockWrapper> children = ((CompositeBlockWrapper)block).getChildren();
|
||||
for (AbstractBlockWrapper childBlock : children) {
|
||||
reindentNewLineChildren(childBlock);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@Override
|
||||
protected void prepare() {
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@@ -818,6 +818,11 @@ public class FormatterImpl extends FormatterEx
|
||||
return getIndent(type, 0, relativeToDirectParent, enforceIndentToChildren);
|
||||
}
|
||||
|
||||
@Override
|
||||
public Indent getSmartIndent(@NotNull Indent.Type type) {
|
||||
return new ExpandableIndent(type);
|
||||
}
|
||||
|
||||
@Override
|
||||
public Indent getIndent(@NotNull Indent.Type type, int spaces, boolean relativeToDirectParent, boolean enforceIndentToChildren) {
|
||||
return new IndentImpl(type, false, spaces, relativeToDirectParent, enforceIndentToChildren);
|
||||
|
||||
@@ -46,6 +46,8 @@ public enum FormattingStateId {
|
||||
*/
|
||||
PROCESSING_BLOCKS(1),
|
||||
|
||||
EXPANDING_CHILDREN_INDENTS(5),
|
||||
|
||||
/**
|
||||
* This element corresponds to formatting phase when all {@link AbstractBlockWrapper wrapped code blocks} are processed and it's
|
||||
* time to apply the changes to the underlying document.
|
||||
|
||||
@@ -24,21 +24,39 @@ public class IndentInfo {
|
||||
|
||||
private final int mySpaces;
|
||||
private final int myIndentSpaces;
|
||||
private final int myLineFeeds;
|
||||
private final int myHiddenSpaces;
|
||||
|
||||
private final int myLineFeeds;
|
||||
/** @see WhiteSpace#setForceSkipTabulationsUsage(boolean) */
|
||||
private final boolean myForceSkipTabulationsUsage;
|
||||
private boolean myIndentEmptyLines; // Additional indent on empty lines (before the end of code block)
|
||||
|
||||
public IndentInfo(final int lineFeeds, final int indentSpaces, final int spaces) {
|
||||
this(lineFeeds, indentSpaces, spaces, false);
|
||||
this(lineFeeds, indentSpaces, spaces, 0, false);
|
||||
}
|
||||
|
||||
public IndentInfo(final int lineFeeds, final int indentSpaces, final int spaces, final boolean forceSkipTabulationsUsage) {
|
||||
public IndentInfo(final int lineFeeds,
|
||||
final int indentSpaces,
|
||||
final int spaces,
|
||||
final int hiddenSpaces)
|
||||
{
|
||||
this(lineFeeds, indentSpaces, spaces, hiddenSpaces, false);
|
||||
}
|
||||
|
||||
public IndentInfo(final int lineFeeds,
|
||||
final int indentSpaces,
|
||||
final int spaces,
|
||||
final boolean forceSkipTabulationsUsage)
|
||||
{
|
||||
this(lineFeeds, indentSpaces, spaces, 0, forceSkipTabulationsUsage);
|
||||
}
|
||||
|
||||
public IndentInfo(final int lineFeeds, final int indentSpaces, final int spaces, final int hiddenSpaces, final boolean forceSkipTabulationsUsage) {
|
||||
mySpaces = spaces;
|
||||
myIndentSpaces = indentSpaces;
|
||||
myLineFeeds = lineFeeds;
|
||||
myForceSkipTabulationsUsage = forceSkipTabulationsUsage;
|
||||
myHiddenSpaces = hiddenSpaces;
|
||||
}
|
||||
|
||||
public int getSpaces() {
|
||||
|
||||
@@ -29,6 +29,8 @@ import com.intellij.psi.formatter.FormattingDocumentModelImpl;
|
||||
import com.intellij.psi.formatter.ReadOnlyBlockInformationProvider;
|
||||
import com.intellij.psi.impl.DebugUtil;
|
||||
import com.intellij.util.containers.ContainerUtil;
|
||||
import com.intellij.util.containers.LinkedMultiMap;
|
||||
import com.intellij.util.containers.MultiMap;
|
||||
import com.intellij.util.containers.Stack;
|
||||
import gnu.trove.THashMap;
|
||||
import org.jetbrains.annotations.NonNls;
|
||||
@@ -74,6 +76,8 @@ class InitialInfoBuilder {
|
||||
private Set<Alignment> myAlignmentsInsideRangeToModify = ContainerUtil.newHashSet();
|
||||
private boolean myCollectAlignmentsInsideFormattingRange = false;
|
||||
|
||||
private MultiMap<ExpandableIndent, AbstractBlockWrapper> myBlocksToForceChildrenIndent = new LinkedMultiMap<ExpandableIndent, AbstractBlockWrapper>();
|
||||
|
||||
private InitialInfoBuilder(final Block rootBlock,
|
||||
final FormattingDocumentModel model,
|
||||
@Nullable final FormatTextRanges affectedRanges,
|
||||
@@ -285,6 +289,10 @@ class InitialInfoBuilder {
|
||||
return wrappedRootBlock;
|
||||
}
|
||||
|
||||
public MultiMap<ExpandableIndent, AbstractBlockWrapper> getExpandableIndentsBlocks() {
|
||||
return myBlocksToForceChildrenIndent;
|
||||
}
|
||||
|
||||
private void doIteration(@NotNull State state) {
|
||||
List<Block> subBlocks = state.parentBlock.getSubBlocks();
|
||||
final int subBlocksCount = subBlocks.size();
|
||||
@@ -303,6 +311,7 @@ class InitialInfoBuilder {
|
||||
final AbstractBlockWrapper wrapper = buildFrom(
|
||||
block, childBlockIndex, state.wrappedBlock, state.parentBlockWrap, state.parentBlock, childBlockIsRightBlock
|
||||
);
|
||||
registerExpandableIndents(block, wrapper);
|
||||
|
||||
if (wrapper.getIndent() == null) {
|
||||
wrapper.setIndent((IndentImpl)block.getIndent());
|
||||
@@ -321,7 +330,14 @@ class InitialInfoBuilder {
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
private void registerExpandableIndents(@NotNull Block block, @NotNull AbstractBlockWrapper wrapper) {
|
||||
if (block.getIndent() instanceof ExpandableIndent) {
|
||||
ExpandableIndent indent = (ExpandableIndent)block.getIndent();
|
||||
myBlocksToForceChildrenIndent.putValue(indent, wrapper);
|
||||
}
|
||||
}
|
||||
|
||||
private void setDefaultIndents(final List<AbstractBlockWrapper> list) {
|
||||
if (!list.isEmpty()) {
|
||||
for (AbstractBlockWrapper wrapper : list) {
|
||||
|
||||
+4
-1
@@ -25,6 +25,7 @@ import com.intellij.openapi.components.TrackingPathMacroSubstitutor;
|
||||
import com.intellij.openapi.components.impl.stores.StateStorageBase;
|
||||
import com.intellij.openapi.components.impl.stores.StateStorageManager;
|
||||
import com.intellij.openapi.components.impl.stores.StorageManagerListener;
|
||||
import com.intellij.openapi.diagnostic.Logger;
|
||||
import com.intellij.openapi.module.Module;
|
||||
import com.intellij.openapi.roots.ModifiableRootModel;
|
||||
import com.intellij.openapi.roots.ModuleRootModel;
|
||||
@@ -55,6 +56,8 @@ import java.util.Set;
|
||||
|
||||
// Boolean - false as not loaded, true as loaded
|
||||
public class ClasspathStorage extends StateStorageBase<Boolean> {
|
||||
private static final Logger LOG = Logger.getInstance(ClasspathStorage.class);
|
||||
|
||||
@NonNls public static final String SPECIAL_STORAGE = "special";
|
||||
|
||||
private final ClasspathStorageProvider.ClasspathConverter myConverter;
|
||||
@@ -135,7 +138,7 @@ public class ClasspathStorage extends StateStorageBase<Boolean> {
|
||||
|
||||
@Nullable
|
||||
@Override
|
||||
public Element getState(@NotNull Boolean storageData, Object component, @NotNull String componentName) {
|
||||
public Element getSerializedState(@NotNull Boolean storageData, Object component, @NotNull String componentName, boolean archive) {
|
||||
if (storageData) {
|
||||
return null;
|
||||
}
|
||||
|
||||
@@ -29,10 +29,10 @@ import com.intellij.openapi.fileTypes.FileTypeListener;
|
||||
import com.intellij.openapi.fileTypes.FileTypeManager;
|
||||
import com.intellij.openapi.module.Module;
|
||||
import com.intellij.openapi.project.Project;
|
||||
import com.intellij.openapi.project.ProjectManager;
|
||||
import com.intellij.openapi.roots.*;
|
||||
import com.intellij.openapi.roots.impl.PushedFilePropertiesUpdater;
|
||||
import com.intellij.openapi.startup.StartupManager;
|
||||
import com.intellij.openapi.util.io.FileUtilRt;
|
||||
import com.intellij.openapi.util.registry.Registry;
|
||||
import com.intellij.openapi.vfs.*;
|
||||
import com.intellij.openapi.vfs.impl.BulkVirtualFileListenerAdapter;
|
||||
@@ -60,6 +60,30 @@ public class PsiVFSListener extends VirtualFileAdapter {
|
||||
private final Project myProject;
|
||||
private boolean myReportedUnloadedPsiChange;
|
||||
|
||||
static {
|
||||
ApplicationManager.getApplication().getMessageBus().connect().subscribe(VirtualFileManager.VFS_CHANGES, new BulkFileListener() {
|
||||
@Override
|
||||
public void before(@NotNull List<? extends VFileEvent> events) {
|
||||
for (Project project : ProjectManager.getInstance().getOpenProjects()) {
|
||||
PsiVFSListener listener = project.getComponent(PsiVFSListener.class);
|
||||
assert listener != null;
|
||||
new BulkVirtualFileListenerAdapter(listener).before(events);
|
||||
}
|
||||
}
|
||||
|
||||
@Override
|
||||
public void after(@NotNull List<? extends VFileEvent> events) {
|
||||
for (Project project : ProjectManager.getInstance().getOpenProjects()) {
|
||||
PsiVFSListener listener = project.getComponent(PsiVFSListener.class);
|
||||
assert listener != null;
|
||||
listener.myReportedUnloadedPsiChange = false;
|
||||
new BulkVirtualFileListenerAdapter(listener).after(events);
|
||||
listener.myReportedUnloadedPsiChange = false;
|
||||
}
|
||||
}
|
||||
});
|
||||
}
|
||||
|
||||
public PsiVFSListener(Project project) {
|
||||
myProject = project;
|
||||
myFileTypeManager = FileTypeManager.getInstance();
|
||||
@@ -72,20 +96,6 @@ public class PsiVFSListener extends VirtualFileAdapter {
|
||||
StartupManager.getInstance(project).registerPreStartupActivity(new Runnable() {
|
||||
@Override
|
||||
public void run() {
|
||||
final BulkVirtualFileListenerAdapter adapter = new BulkVirtualFileListenerAdapter(PsiVFSListener.this);
|
||||
myConnection.subscribe(VirtualFileManager.VFS_CHANGES, new BulkFileListener() {
|
||||
@Override
|
||||
public void before(@NotNull List<? extends VFileEvent> events) {
|
||||
adapter.before(events);
|
||||
}
|
||||
|
||||
@Override
|
||||
public void after(@NotNull List<? extends VFileEvent> events) {
|
||||
myReportedUnloadedPsiChange = false;
|
||||
adapter.after(events);
|
||||
myReportedUnloadedPsiChange = false;
|
||||
}
|
||||
});
|
||||
myConnection.subscribe(ProjectTopics.PROJECT_ROOTS, new MyModuleRootListener());
|
||||
myConnection.subscribe(FileTypeManager.TOPIC, new FileTypeListener.Adapter() {
|
||||
@Override
|
||||
@@ -595,11 +605,6 @@ public class PsiVFSListener extends VirtualFileAdapter {
|
||||
true, false);
|
||||
}
|
||||
|
||||
// When file is renamed so that extension changes then language dialect might change and thus psiFile should be invalidated
|
||||
private static boolean languageDialectChanged(final PsiFile newPsiFile, String oldFileName) {
|
||||
return newPsiFile != null && !FileUtilRt.extensionEquals(oldFileName, FileUtilRt.getExtension(newPsiFile.getName()));
|
||||
}
|
||||
|
||||
private class MyModuleRootListener implements ModuleRootListener {
|
||||
private VirtualFile[] myOldContentRoots = null;
|
||||
private volatile int depthCounter = 0;
|
||||
|
||||
+9
-7
@@ -22,22 +22,26 @@ import java.util.concurrent.atomic.AtomicReference
|
||||
|
||||
public abstract class StateStorageBase<T : Any> : StateStorage {
|
||||
companion object {
|
||||
protected val LOG: Logger = Logger.getInstance(javaClass<StateStorageBase<Any>>())
|
||||
private val LOG: Logger = Logger.getInstance(javaClass<StateStorageBase<Any>>())
|
||||
}
|
||||
|
||||
private var mySavingDisabled = false
|
||||
|
||||
protected val storageDataRef: AtomicReference<T> = AtomicReference()
|
||||
|
||||
override fun <S> getState(component: Any?, componentName: String, stateClass: Class<S>, mergeInto: S?, reload: Boolean): S? {
|
||||
return deserializeState(getState(getStorageData(reload), component, componentName), stateClass, mergeInto)
|
||||
override final fun <S> getState(component: Any?, componentName: String, stateClass: Class<S>, mergeInto: S?, reload: Boolean): S? {
|
||||
return getState(component, componentName, stateClass, true, reload, mergeInto)
|
||||
}
|
||||
|
||||
fun <S : Any> getState(component: Any?, componentName: String, stateClass: Class<S>, archive: Boolean = true, reload: Boolean = false, mergeInto: S? = null): S? {
|
||||
return deserializeState(getSerializedState(getStorageData(reload), component, componentName, archive), stateClass, mergeInto)
|
||||
}
|
||||
|
||||
open fun <S> deserializeState(serializedState: Element?, stateClass: Class<S>, mergeInto: S?): S? {
|
||||
return DefaultStateSerializer.deserializeState(serializedState, stateClass, mergeInto)
|
||||
}
|
||||
|
||||
abstract fun getState(storageData: T, component: Any?, componentName: String): Element?
|
||||
abstract fun getSerializedState(storageData: T, component: Any?, componentName: String, archive: Boolean = true): Element?
|
||||
|
||||
protected abstract fun hasState(storageData: T, componentName: String): Boolean
|
||||
|
||||
@@ -45,9 +49,7 @@ public abstract class StateStorageBase<T : Any> : StateStorage {
|
||||
return hasState(getStorageData(reloadData), componentName)
|
||||
}
|
||||
|
||||
public fun getStorageData(): T {
|
||||
return getStorageData(false)
|
||||
}
|
||||
public fun getStorageData(): T = getStorageData(false)
|
||||
|
||||
protected fun getStorageData(reload: Boolean): T {
|
||||
val storageData = storageDataRef.get()
|
||||
|
||||
@@ -52,6 +52,8 @@ public abstract class EditorGutterComponentEx extends JComponent implements Edit
|
||||
|
||||
public abstract int getLineMarkerAreaOffset();
|
||||
|
||||
public abstract int getIconAreaOffset();
|
||||
|
||||
public abstract int getLineMarkerFreePaintersAreaOffset();
|
||||
|
||||
public abstract int getIconsAreaWidth();
|
||||
|
||||
+55
-35
@@ -82,8 +82,9 @@ import java.util.List;
|
||||
class EditorGutterComponentImpl extends EditorGutterComponentEx implements MouseListener, MouseMotionListener, DataProvider {
|
||||
private static final Logger LOG = Logger.getInstance("#com.intellij.openapi.editor.impl.EditorGutterComponentImpl");
|
||||
private static final int START_ICON_AREA_WIDTH = 15;
|
||||
private static final int FREE_PAINTERS_AREA_WIDTH = 5;
|
||||
private static final int GAP_BETWEEN_ICONS_AND_FREE_PAINTERS_AREA = 5;
|
||||
private static final int FREE_PAINTERS_LEFT_AREA_WIDTH = 8;
|
||||
private static final int FREE_PAINTERS_RIGHT_AREA_WIDTH = 5;
|
||||
private static final int GAP_BETWEEN_ICONS_AND_RIGHT_FREE_PAINTERS_AREA = 5;
|
||||
private static final int GAP_BETWEEN_ICONS = 3;
|
||||
private static final int GAP_BEFORE_LINE_NUMBERS = 5;
|
||||
private static final int GAP_AFTER_LINE_NUMBERS = 4;
|
||||
@@ -97,7 +98,6 @@ class EditorGutterComponentImpl extends EditorGutterComponentEx implements Mouse
|
||||
|
||||
private final EditorImpl myEditor;
|
||||
private final FoldingAnchorsOverlayStrategy myAnchorsDisplayStrategy;
|
||||
private int myLineMarkerAreaWidth = START_ICON_AREA_WIDTH + GAP_BETWEEN_ICONS_AND_FREE_PAINTERS_AREA + FREE_PAINTERS_AREA_WIDTH;
|
||||
private int myIconsAreaWidth = START_ICON_AREA_WIDTH;
|
||||
private int myLineNumberAreaWidth = 0;
|
||||
private int myAdditionalLineNumberAreaWidth = 0;
|
||||
@@ -116,6 +116,7 @@ class EditorGutterComponentImpl extends EditorGutterComponentEx implements Mouse
|
||||
@Nullable private ActionGroup myCustomGutterPopupGroup;
|
||||
private TIntObjectHashMap<Color> myTextFgColors = new TIntObjectHashMap<Color>();
|
||||
private boolean myPaintBackground = true;
|
||||
private boolean myLeftFreePaintersAreaShown;
|
||||
|
||||
@SuppressWarnings("unchecked")
|
||||
public EditorGutterComponentImpl(EditorImpl editor) {
|
||||
@@ -629,14 +630,14 @@ class EditorGutterComponentImpl extends EditorGutterComponentEx implements Mouse
|
||||
private void updateSizeInner(boolean onLayout) {
|
||||
if (!onLayout) {
|
||||
calcLineNumberAreaWidth();
|
||||
calcIconAreaWidth();
|
||||
calcLineMarkerAreaWidth();
|
||||
calcAnnotationsSize();
|
||||
}
|
||||
calcAnnotationExtraSize();
|
||||
}
|
||||
|
||||
private int sizeHash() {
|
||||
int result = myLineMarkerAreaWidth;
|
||||
int result = getLineMarkerAreaWidth();
|
||||
result = 31 * result + myTextAnnotationGuttersSize;
|
||||
result = 31 * result + myTextAnnotationExtraSize;
|
||||
result = 31 * result + getLineNumberAreaWidth();
|
||||
@@ -682,19 +683,27 @@ class EditorGutterComponentImpl extends EditorGutterComponentEx implements Mouse
|
||||
|
||||
int width = editorLocationX + editorComponent.getWidth();
|
||||
if (rightMarginX < width && editorLocationX < width - rightMarginX) {
|
||||
int centeredSize = (width - rightMarginX - editorLocationX) / 2 - (myLineMarkerAreaWidth + getLineNumberAreaWidth());
|
||||
int centeredSize = (width - rightMarginX - editorLocationX) / 2 - (getLineMarkerAreaWidth() + getLineNumberAreaWidth());
|
||||
myTextAnnotationExtraSize = Math.max(0, centeredSize - myTextAnnotationGuttersSize);
|
||||
}
|
||||
}
|
||||
|
||||
private TIntObjectHashMap<List<GutterMark>> myLineToGutterRenderers;
|
||||
|
||||
private void calcIconAreaWidth() {
|
||||
private void calcLineMarkerAreaWidth() {
|
||||
myLineToGutterRenderers = new TIntObjectHashMap<List<GutterMark>>();
|
||||
myLeftFreePaintersAreaShown = false;
|
||||
|
||||
processRangeHighlighters(0, myEditor.getDocument().getTextLength(), new RangeHighlighterProcessor() {
|
||||
@Override
|
||||
public void process(@NotNull RangeHighlighter highlighter) {
|
||||
LineMarkerRenderer lineMarkerRenderer = highlighter.getLineMarkerRenderer();
|
||||
if (lineMarkerRenderer instanceof LineMarkerRendererEx &&
|
||||
((LineMarkerRendererEx)lineMarkerRenderer).getPosition() == LineMarkerRendererEx.Position.LEFT &&
|
||||
isLineMarkerVisible(highlighter)) {
|
||||
myLeftFreePaintersAreaShown = true;
|
||||
}
|
||||
|
||||
GutterMark renderer = highlighter.getGutterIconRenderer();
|
||||
if (renderer == null) {
|
||||
return;
|
||||
@@ -734,8 +743,6 @@ class EditorGutterComponentImpl extends EditorGutterComponentEx implements Mouse
|
||||
return true;
|
||||
}
|
||||
});
|
||||
|
||||
myLineMarkerAreaWidth = myIconsAreaWidth + GAP_BETWEEN_ICONS_AND_FREE_PAINTERS_AREA + FREE_PAINTERS_AREA_WIDTH;
|
||||
}
|
||||
|
||||
private boolean isHighlighterVisible(RangeHighlighter highlighter) {
|
||||
@@ -791,28 +798,30 @@ class EditorGutterComponentImpl extends EditorGutterComponentEx implements Mouse
|
||||
}
|
||||
|
||||
private void paintLineMarkerRenderer(RangeHighlighter highlighter, Graphics g) {
|
||||
Rectangle rectangle = getLineRendererRectangle(highlighter);
|
||||
|
||||
if (rectangle != null) {
|
||||
final LineMarkerRenderer lineMarkerRenderer = highlighter.getLineMarkerRenderer();
|
||||
assert lineMarkerRenderer != null;
|
||||
lineMarkerRenderer.paint(myEditor, g, rectangle);
|
||||
LineMarkerRenderer lineMarkerRenderer = highlighter.getLineMarkerRenderer();
|
||||
if (lineMarkerRenderer != null) {
|
||||
Rectangle rectangle = getLineRendererRectangle(highlighter);
|
||||
if (rectangle != null) {
|
||||
lineMarkerRenderer.paint(myEditor, g, rectangle);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@Nullable
|
||||
private Rectangle getLineRendererRectangle(RangeHighlighter highlighter) {
|
||||
LineMarkerRenderer renderer = highlighter.getLineMarkerRenderer();
|
||||
if (renderer == null) return null;
|
||||
|
||||
|
||||
private boolean isLineMarkerVisible(RangeHighlighter highlighter) {
|
||||
int startOffset = highlighter.getStartOffset();
|
||||
int endOffset = highlighter.getEndOffset();
|
||||
|
||||
FoldRegion startFoldRegion = myEditor.getFoldingModel().getCollapsedRegionAtOffset(startOffset);
|
||||
FoldRegion endFoldRegion = myEditor.getFoldingModel().getCollapsedRegionAtOffset(endOffset);
|
||||
if (startFoldRegion != null && endFoldRegion != null && startFoldRegion.equals(endFoldRegion)) {
|
||||
return null;
|
||||
}
|
||||
return startFoldRegion == null || endFoldRegion == null || !startFoldRegion.equals(endFoldRegion);
|
||||
}
|
||||
|
||||
@Nullable
|
||||
private Rectangle getLineRendererRectangle(RangeHighlighter highlighter) {
|
||||
if (!isLineMarkerVisible(highlighter)) return null;
|
||||
|
||||
int startOffset = highlighter.getStartOffset();
|
||||
int endOffset = highlighter.getEndOffset();
|
||||
|
||||
int startY = myEditor.visualPositionToXY(myEditor.offsetToVisualPosition(startOffset)).y;
|
||||
|
||||
@@ -825,9 +834,13 @@ class EditorGutterComponentImpl extends EditorGutterComponentEx implements Mouse
|
||||
endY += myEditor.getLineHeight();
|
||||
}
|
||||
|
||||
LineMarkerRenderer renderer = highlighter.getLineMarkerRenderer();
|
||||
boolean leftPosition = renderer instanceof LineMarkerRendererEx &&
|
||||
((LineMarkerRendererEx)renderer).getPosition() == LineMarkerRendererEx.Position.LEFT;
|
||||
|
||||
int height = endY - startY;
|
||||
int w = FREE_PAINTERS_AREA_WIDTH;
|
||||
int x = getLineMarkerFreePaintersAreaOffset() - 1;
|
||||
int w = leftPosition ? FREE_PAINTERS_LEFT_AREA_WIDTH : FREE_PAINTERS_RIGHT_AREA_WIDTH;
|
||||
int x = leftPosition ? getLineMarkerAreaOffset() : getLineMarkerFreePaintersAreaOffset() - 1;
|
||||
return new Rectangle(x, startY, w, height);
|
||||
}
|
||||
|
||||
@@ -845,7 +858,7 @@ class EditorGutterComponentImpl extends EditorGutterComponentEx implements Mouse
|
||||
private void processIconsRow(int line, List<GutterMark> row, LineGutterIconRendererProcessor processor) {
|
||||
int middleCount = 0;
|
||||
int middleSize = 0;
|
||||
int x = getLineMarkerAreaOffset() + 2;
|
||||
int x = getIconAreaOffset() + 2;
|
||||
final int y = myEditor.logicalPositionToXY(new LogicalPosition(line, 0)).y;
|
||||
|
||||
for (GutterMark r : row) {
|
||||
@@ -862,9 +875,9 @@ class EditorGutterComponentImpl extends EditorGutterComponentEx implements Mouse
|
||||
}
|
||||
}
|
||||
|
||||
final int leftSize = x - getLineMarkerAreaOffset();
|
||||
final int leftSize = x - getIconAreaOffset();
|
||||
|
||||
x = getLineMarkerAreaOffset() + myIconsAreaWidth - 2; // because of 2px LineMarkerRenderers
|
||||
x = getIconAreaOffset() + myIconsAreaWidth - 2; // because of 2px LineMarkerRenderers
|
||||
for (GutterMark r : row) {
|
||||
if (!checkDumbAware(r, myEditor.getProject())) continue;
|
||||
if (((GutterIconRenderer)r).getAlignment() == GutterIconRenderer.Alignment.RIGHT) {
|
||||
@@ -875,11 +888,11 @@ class EditorGutterComponentImpl extends EditorGutterComponentEx implements Mouse
|
||||
}
|
||||
}
|
||||
|
||||
int rightSize = myIconsAreaWidth + getLineMarkerAreaOffset() - x + 1;
|
||||
int rightSize = myIconsAreaWidth + getIconAreaOffset() - x + 1;
|
||||
|
||||
if (middleCount > 0) {
|
||||
middleSize -= GAP_BETWEEN_ICONS;
|
||||
x = getLineMarkerAreaOffset() + leftSize + (myIconsAreaWidth - leftSize - rightSize - middleSize) / 2;
|
||||
x = getIconAreaOffset() + leftSize + (myIconsAreaWidth - leftSize - rightSize - middleSize) / 2;
|
||||
for (GutterMark r : row) {
|
||||
if (!checkDumbAware(r, myEditor.getProject())) continue;
|
||||
if (((GutterIconRenderer)r).getAlignment() == GutterIconRenderer.Alignment.CENTER) {
|
||||
@@ -1121,7 +1134,9 @@ class EditorGutterComponentImpl extends EditorGutterComponentEx implements Mouse
|
||||
}
|
||||
|
||||
public int getLineMarkerAreaWidth() {
|
||||
return isLineMarkersShown() ? myLineMarkerAreaWidth : 0;
|
||||
return isLineMarkersShown() ? ((myLeftFreePaintersAreaShown ? FREE_PAINTERS_LEFT_AREA_WIDTH : 0) +
|
||||
myIconsAreaWidth + GAP_BETWEEN_ICONS_AND_RIGHT_FREE_PAINTERS_AREA + FREE_PAINTERS_RIGHT_AREA_WIDTH) :
|
||||
0;
|
||||
}
|
||||
|
||||
public void setLineNumberAreaWidthFunction(@NotNull TIntFunction calculator) {
|
||||
@@ -1200,9 +1215,14 @@ class EditorGutterComponentImpl extends EditorGutterComponentEx implements Mouse
|
||||
return getAnnotationsAreaOffset() + getAnnotationsAreaWidthEx();
|
||||
}
|
||||
|
||||
@Override
|
||||
public int getIconAreaOffset() {
|
||||
return getLineMarkerAreaOffset() + (myLeftFreePaintersAreaShown ? FREE_PAINTERS_LEFT_AREA_WIDTH : 0);
|
||||
}
|
||||
|
||||
@Override
|
||||
public int getLineMarkerFreePaintersAreaOffset() {
|
||||
return getLineMarkerAreaOffset() + myIconsAreaWidth + GAP_BETWEEN_ICONS_AND_FREE_PAINTERS_AREA;
|
||||
return getIconAreaOffset() + myIconsAreaWidth + GAP_BETWEEN_ICONS_AND_RIGHT_FREE_PAINTERS_AREA;
|
||||
}
|
||||
|
||||
@Override
|
||||
@@ -1466,7 +1486,8 @@ class EditorGutterComponentImpl extends EditorGutterComponentEx implements Mouse
|
||||
processRangeHighlighters(firstVisibleOffset, lastVisibleOffset, new RangeHighlighterProcessor() {
|
||||
@Override
|
||||
public void process(@NotNull RangeHighlighter highlighter) {
|
||||
if (gutterRenderer[0] != null) return;
|
||||
LineMarkerRenderer renderer = highlighter.getLineMarkerRenderer();
|
||||
if (renderer == null || gutterRenderer[0] != null) return;
|
||||
Rectangle rectangle = getLineRendererRectangle(highlighter);
|
||||
if (rectangle == null) return;
|
||||
|
||||
@@ -1477,7 +1498,6 @@ class EditorGutterComponentImpl extends EditorGutterComponentEx implements Mouse
|
||||
}
|
||||
|
||||
if (startY < e.getY() && e.getY() <= endY) {
|
||||
final LineMarkerRenderer renderer = highlighter.getLineMarkerRenderer();
|
||||
if (renderer instanceof ActiveGutterRenderer && ((ActiveGutterRenderer)renderer).canDoAction(e)) {
|
||||
gutterRenderer[0] = (ActiveGutterRenderer)renderer;
|
||||
}
|
||||
|
||||
@@ -2186,7 +2186,6 @@ public final class EditorImpl extends UserDataHolderBase implements EditorEx, Hi
|
||||
private boolean canPaintImmediately(char c) {
|
||||
return myDocument instanceof DocumentImpl &&
|
||||
myHighlighter instanceof LexerEditorHighlighter &&
|
||||
myDocument.getTextLength() > 0 &&
|
||||
!mySelectionModel.hasSelection() &&
|
||||
areVisualLinesUnique(myCaretModel.getAllCarets()) &&
|
||||
!isInplaceRenamerActive() &&
|
||||
@@ -2222,8 +2221,10 @@ public final class EditorImpl extends UserDataHolderBase implements EditorEx, Hi
|
||||
TextAttributes attributes = ((LexerEditorHighlighter)myHighlighter).getAttributes((DocumentImpl)myDocument, offset, c);
|
||||
|
||||
int fontType = attributes.getFontType();
|
||||
Font font = fontFor(fontType);
|
||||
FontInfo fontInfo = EditorUtil.fontForChar(c, attributes.getFontType(), this);
|
||||
Font font = fontInfo.getFont();
|
||||
|
||||
// it's more reliable to query actual font metrics
|
||||
FontMetrics fontMetrics = getFontMetrics(fontType);
|
||||
|
||||
int charWidth = fontMetrics.charWidth(c);
|
||||
@@ -2318,7 +2319,10 @@ public final class EditorImpl extends UserDataHolderBase implements EditorEx, Hi
|
||||
|
||||
Point point = newArea.getLocation();
|
||||
int ascent = getAscent();
|
||||
Font font = fontFor(attributes.getFontType());
|
||||
// simplified font selection (based on the first character)
|
||||
FontInfo fontInfo = EditorUtil.fontForChar(newText.charAt(0), attributes.getFontType(), this);
|
||||
Font font = fontInfo.getFont();
|
||||
|
||||
Color color = attributes.getForegroundColor() == null ? getForegroundColor() : attributes.getForegroundColor();
|
||||
|
||||
EditorUIUtil.setupAntialiasing(g);
|
||||
@@ -2350,11 +2354,6 @@ public final class EditorImpl extends UserDataHolderBase implements EditorEx, Hi
|
||||
return color == null ? getBackgroundColor() : color;
|
||||
}
|
||||
|
||||
@NotNull
|
||||
private Font fontFor(int fontType) {
|
||||
return myScheme.getFont(EditorFontType.values()[fontType]);
|
||||
}
|
||||
|
||||
private static void shift(@NotNull Graphics g, @NotNull Rectangle r, int delta) {
|
||||
g.copyArea(r.x, r.y, r.width, r.height, delta, 0);
|
||||
}
|
||||
|
||||
+30
@@ -0,0 +1,30 @@
|
||||
/*
|
||||
* Copyright 2000-2015 JetBrains s.r.o.
|
||||
*
|
||||
* Licensed under the Apache License, Version 2.0 (the "License");
|
||||
* you may not use this file except in compliance with the License.
|
||||
* You may obtain a copy of the License at
|
||||
*
|
||||
* http://www.apache.org/licenses/LICENSE-2.0
|
||||
*
|
||||
* Unless required by applicable law or agreed to in writing, software
|
||||
* distributed under the License is distributed on an "AS IS" BASIS,
|
||||
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
* See the License for the specific language governing permissions and
|
||||
* limitations under the License.
|
||||
*/
|
||||
package com.intellij.openapi.editor.markup;
|
||||
|
||||
import com.intellij.openapi.editor.Editor;
|
||||
|
||||
import java.awt.*;
|
||||
|
||||
public interface LineMarkerRendererEx extends LineMarkerRenderer {
|
||||
enum Position {LEFT, RIGHT}
|
||||
|
||||
/**
|
||||
* Determines whether line marker should be rendered to the left or to the right of icon area in gutter.
|
||||
* Corresponding rectangle will be passed to renderer in {@link #paint(Editor, Graphics, Rectangle)} method.
|
||||
*/
|
||||
Position getPosition();
|
||||
}
|
||||
@@ -30,6 +30,7 @@ progress.reformat.and.optimize.common.command.text=Reformat and Optimize Imports
|
||||
progress.reformat.stage.wrapping.blocks=Preparing...
|
||||
progress.reformat.stage.processing.blocks=Calculating changes...
|
||||
progress.reformat.stage.applying.changes=Storing changes...
|
||||
progress.reformat.stage.expanding.children.indents=Expanding necessary children indents
|
||||
process.rearrange.code=Rearranging code...
|
||||
process.reformat.code=Reformat Code
|
||||
process.reformat.code.before.commit=Reformat Code Before Commit
|
||||
@@ -520,4 +521,4 @@ dialog.edit.template.checkbox.xsl.text=XSL Text
|
||||
highlight.imported.classes.chooser.title=Choose Imported Classes to Highlight
|
||||
highlight.imported.members.chooser.title=Choose Imported Members to Highlight
|
||||
javadoc.resolved.value=Resolved value\:
|
||||
javadoc.error.resolving.url=Couldn''t resolve URL <i>{0}</i> <p>Configuring paths to API docs in <a href="open://Project Settings">project settings</a> might help
|
||||
javadoc.error.resolving.url=Couldn''t resolve URL <i>{0}</i> <p>Configuring paths to API docs in <a href="open://Project Settings">project settings</a> might help
|
||||
|
||||
@@ -652,6 +652,7 @@ testDiscovery.enabled=false
|
||||
ruby.remote.debugger.supports.catchpoint.removal=true
|
||||
|
||||
use.read.action.to.init.service=true
|
||||
use.loaded.state.as.existing=false
|
||||
|
||||
ide.mac.new.color.picker=false
|
||||
|
||||
|
||||
+1
-1
@@ -55,7 +55,7 @@ public class SuperTearDownInFinallyInspection extends BaseInspection {
|
||||
return;
|
||||
}
|
||||
final PsiMethod method = PsiTreeUtil.getParentOfType(expression, PsiMethod.class, true, PsiMember.class, PsiLambdaExpression.class);
|
||||
if (method == null) {
|
||||
if (method == null || !method.getName().equals("tearDown")) {
|
||||
return;
|
||||
}
|
||||
final PsiClass containingClass = method.getContainingClass();
|
||||
|
||||
+17
-3
@@ -1,17 +1,19 @@
|
||||
class SuperTearDownInFinally extends junit.framework.TestCase {
|
||||
import junit.framework.TestCase;
|
||||
|
||||
class SuperTearDownInFinally extends TestCase {
|
||||
|
||||
public void tearDown() throws Exception {
|
||||
super.<warning descr="'tearDown()' not called from 'finally' block">tearDown</warning>();
|
||||
System.out.println();
|
||||
}
|
||||
}
|
||||
class NoProblem extends junit.framework.TestCase {
|
||||
class NoProblem extends TestCase {
|
||||
|
||||
public void tearDown() throws Exception {
|
||||
super.tearDown();
|
||||
}
|
||||
}
|
||||
class CalledInFinally extends junit.framework.TestCase {
|
||||
class CalledInFinally extends TestCase {
|
||||
|
||||
public void tearDown() throws Exception {
|
||||
try {
|
||||
@@ -20,4 +22,16 @@ class CalledInFinally extends junit.framework.TestCase {
|
||||
super.tearDown();
|
||||
}
|
||||
}
|
||||
}
|
||||
class SomeTest extends TestCase {
|
||||
@Override
|
||||
protected void setUp() throws Exception {
|
||||
try {
|
||||
super.setUp();
|
||||
}
|
||||
catch (Throwable t) {
|
||||
super.tearDown(); // yellow code
|
||||
}
|
||||
}
|
||||
public void test_something() {}
|
||||
}
|
||||
@@ -1,5 +1,17 @@
|
||||
/*
|
||||
* Copyright (c) 2000-2006 JetBrains s.r.o. All Rights Reserved.
|
||||
* Copyright 2000-2015 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.coverage;
|
||||
@@ -25,6 +37,7 @@ import com.intellij.openapi.editor.ex.EditorEx;
|
||||
import com.intellij.openapi.editor.ex.EditorGutterComponentEx;
|
||||
import com.intellij.openapi.editor.impl.EditorImpl;
|
||||
import com.intellij.openapi.editor.markup.ActiveGutterRenderer;
|
||||
import com.intellij.openapi.editor.markup.LineMarkerRendererEx;
|
||||
import com.intellij.openapi.editor.markup.TextAttributes;
|
||||
import com.intellij.openapi.options.Configurable;
|
||||
import com.intellij.openapi.options.SearchableConfigurable;
|
||||
@@ -57,7 +70,7 @@ import java.util.TreeMap;
|
||||
/**
|
||||
* @author ven
|
||||
*/
|
||||
public class CoverageLineMarkerRenderer implements ActiveGutterRenderer {
|
||||
public class CoverageLineMarkerRenderer implements LineMarkerRendererEx, ActiveGutterRenderer {
|
||||
private static final int THICKNESS = 8;
|
||||
private final TextAttributesKey myKey;
|
||||
private final String myClassName;
|
||||
@@ -97,10 +110,10 @@ public class CoverageLineMarkerRenderer implements ActiveGutterRenderer {
|
||||
if (bgColor != null) {
|
||||
g.setColor(bgColor);
|
||||
}
|
||||
g.fillRect(0, r.y, THICKNESS, r.height);
|
||||
g.fillRect(r.x, r.y, r.width, r.height);
|
||||
final LineData lineData = getLineData(editor.xyToLogicalPosition(new Point(0, r.y)).line);
|
||||
if (lineData != null && lineData.isCoveredByOneTest()) {
|
||||
g.drawImage( ImageLoader.loadFromResource("/gutter/unique.png"), 0, r.y, 8, 8, editor.getComponent());
|
||||
g.drawImage( ImageLoader.loadFromResource("/gutter/unique.png"), r.x, r.y, 8, 8, editor.getComponent());
|
||||
}
|
||||
}
|
||||
|
||||
@@ -135,7 +148,12 @@ public class CoverageLineMarkerRenderer implements ActiveGutterRenderer {
|
||||
}
|
||||
|
||||
public boolean canDoAction(final MouseEvent e) {
|
||||
return e.getX() < THICKNESS;
|
||||
Component component = e.getComponent();
|
||||
if (component instanceof EditorGutterComponentEx) {
|
||||
EditorGutterComponentEx gutter = (EditorGutterComponentEx)component;
|
||||
return e.getX() > gutter.getLineMarkerAreaOffset() && e.getX() < gutter.getIconAreaOffset();
|
||||
}
|
||||
return false;
|
||||
}
|
||||
|
||||
public void doAction(final Editor editor, final MouseEvent e) {
|
||||
@@ -253,6 +271,11 @@ public class CoverageLineMarkerRenderer implements ActiveGutterRenderer {
|
||||
return editor.getColorsScheme().getAttributes(myKey).getErrorStripeColor();
|
||||
}
|
||||
|
||||
@Override
|
||||
public Position getPosition() {
|
||||
return Position.LEFT;
|
||||
}
|
||||
|
||||
private class GotoPreviousCoveredLineAction extends BaseGotoCoveredLineAction {
|
||||
|
||||
public GotoPreviousCoveredLineAction(final Editor editor, final int lineNumber) {
|
||||
|
||||
@@ -40,7 +40,7 @@
|
||||
<deadCode implementation="com.intellij.execution.junit2.inspection.JUnitEntryPoint"/>
|
||||
<cantBeStatic implementation="com.intellij.execution.junit2.inspection.JUnitCantBeStaticExtension" />
|
||||
<testFramework implementation="com.intellij.execution.junit.JUnit3Framework"/>
|
||||
<testFramework implementation="com.intellij.execution.junit.JUnit4Framework"/>
|
||||
<testFramework implementation="com.intellij.execution.junit.JUnit4Framework" id="junit4"/>
|
||||
<configurationType implementation="com.intellij.execution.junit.JUnitConfigurationType"/>
|
||||
<library.dependencyScopeSuggester implementation="com.intellij.execution.junit.JUnitDependencyScopeSuggester"/>
|
||||
|
||||
|
||||
+9
@@ -17,6 +17,7 @@
|
||||
package com.intellij.execution.junit;
|
||||
|
||||
import com.intellij.execution.actions.ConfigurationContext;
|
||||
import com.intellij.execution.configurations.ConfigurationType;
|
||||
import com.intellij.execution.junit2.info.LocationUtil;
|
||||
import com.intellij.openapi.module.Module;
|
||||
import com.intellij.openapi.module.ModuleUtilCore;
|
||||
@@ -31,6 +32,14 @@ import org.jetbrains.jps.model.java.JavaSourceRootType;
|
||||
|
||||
|
||||
public class AllInDirectoryConfigurationProducer extends JUnitConfigurationProducer {
|
||||
|
||||
protected AllInDirectoryConfigurationProducer(ConfigurationType configurationType) {
|
||||
super(configurationType);
|
||||
}
|
||||
|
||||
public AllInDirectoryConfigurationProducer() {
|
||||
}
|
||||
|
||||
@Override
|
||||
protected boolean setupConfigurationFromContext(JUnitConfiguration configuration,
|
||||
ConfigurationContext context,
|
||||
|
||||
@@ -18,6 +18,7 @@ package com.intellij.execution.junit;
|
||||
|
||||
import com.intellij.execution.actions.ConfigurationContext;
|
||||
import com.intellij.execution.actions.ConfigurationFromContext;
|
||||
import com.intellij.execution.configurations.ConfigurationType;
|
||||
import com.intellij.execution.junit2.info.LocationUtil;
|
||||
import com.intellij.openapi.util.Ref;
|
||||
import com.intellij.psi.PsiElement;
|
||||
@@ -25,6 +26,14 @@ import com.intellij.psi.PsiPackage;
|
||||
|
||||
|
||||
public class AllInPackageConfigurationProducer extends JUnitConfigurationProducer {
|
||||
|
||||
public AllInPackageConfigurationProducer() {
|
||||
}
|
||||
|
||||
protected AllInPackageConfigurationProducer(ConfigurationType configurationType) {
|
||||
super(configurationType);
|
||||
}
|
||||
|
||||
@Override
|
||||
protected boolean setupConfigurationFromContext(JUnitConfiguration configuration,
|
||||
ConfigurationContext context,
|
||||
|
||||
@@ -23,6 +23,7 @@ import com.intellij.execution.RunnerAndConfigurationSettings;
|
||||
import com.intellij.execution.actions.ConfigurationContext;
|
||||
import com.intellij.execution.actions.ConfigurationFromContext;
|
||||
import com.intellij.execution.actions.RunConfigurationProducer;
|
||||
import com.intellij.execution.configurations.ConfigurationType;
|
||||
import com.intellij.execution.configurations.RunConfiguration;
|
||||
import com.intellij.execution.junit2.PsiMemberParameterizedLocation;
|
||||
import com.intellij.openapi.module.Module;
|
||||
@@ -36,6 +37,10 @@ public abstract class JUnitConfigurationProducer extends JavaRunConfigurationPro
|
||||
super(JUnitConfigurationType.getInstance());
|
||||
}
|
||||
|
||||
protected JUnitConfigurationProducer(ConfigurationType configurationType) {
|
||||
super(configurationType);
|
||||
}
|
||||
|
||||
@Override
|
||||
public boolean isPreferredConfiguration(ConfigurationFromContext self, ConfigurationFromContext other) {
|
||||
return !other.isProducedBy(TestMethodConfigurationProducer.class);
|
||||
|
||||
@@ -21,6 +21,7 @@ import com.intellij.execution.Location;
|
||||
import com.intellij.execution.actions.ConfigurationContext;
|
||||
import com.intellij.execution.actions.ConfigurationFromContext;
|
||||
import com.intellij.execution.actions.RunConfigurationProducer;
|
||||
import com.intellij.execution.configurations.ConfigurationType;
|
||||
import com.intellij.execution.junit2.PsiMemberParameterizedLocation;
|
||||
import com.intellij.openapi.module.Module;
|
||||
import com.intellij.openapi.util.Ref;
|
||||
@@ -31,6 +32,13 @@ import com.intellij.psi.PsiMethod;
|
||||
import java.util.List;
|
||||
|
||||
public class TestClassConfigurationProducer extends JUnitConfigurationProducer {
|
||||
public TestClassConfigurationProducer() {
|
||||
}
|
||||
|
||||
protected TestClassConfigurationProducer(ConfigurationType configurationType) {
|
||||
super(configurationType);
|
||||
}
|
||||
|
||||
@Override
|
||||
protected boolean setupConfigurationFromContext(JUnitConfiguration configuration,
|
||||
ConfigurationContext context,
|
||||
|
||||
@@ -22,6 +22,7 @@ import com.intellij.execution.PsiLocation;
|
||||
import com.intellij.execution.actions.ConfigurationContext;
|
||||
import com.intellij.execution.actions.ConfigurationFromContext;
|
||||
import com.intellij.execution.actions.RunConfigurationProducer;
|
||||
import com.intellij.execution.configurations.ConfigurationType;
|
||||
import com.intellij.execution.junit2.PsiMemberParameterizedLocation;
|
||||
import com.intellij.execution.junit2.info.MethodLocation;
|
||||
import com.intellij.openapi.module.Module;
|
||||
@@ -35,6 +36,13 @@ import java.util.Iterator;
|
||||
import java.util.List;
|
||||
|
||||
public class TestMethodConfigurationProducer extends JUnitConfigurationProducer {
|
||||
public TestMethodConfigurationProducer() {
|
||||
}
|
||||
|
||||
protected TestMethodConfigurationProducer(ConfigurationType configurationType) {
|
||||
super(configurationType);
|
||||
}
|
||||
|
||||
@Override
|
||||
protected boolean setupConfigurationFromContext(JUnitConfiguration configuration,
|
||||
ConfigurationContext context,
|
||||
|
||||
+26
-3
@@ -1,5 +1,5 @@
|
||||
/*
|
||||
* Copyright 2000-2013 JetBrains s.r.o.
|
||||
* Copyright 2000-2015 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.
|
||||
@@ -92,6 +92,7 @@ public class MavenProjectsNavigator extends MavenSimpleProjectComponent implemen
|
||||
myShortcutsManager = shortcutsManager;
|
||||
}
|
||||
|
||||
@Override
|
||||
public MavenProjectsNavigatorState getState() {
|
||||
ApplicationManager.getApplication().assertIsDispatchThread();
|
||||
if (myStructure != null) {
|
||||
@@ -106,6 +107,7 @@ public class MavenProjectsNavigator extends MavenSimpleProjectComponent implemen
|
||||
return myState;
|
||||
}
|
||||
|
||||
@Override
|
||||
public void loadState(MavenProjectsNavigatorState state) {
|
||||
myState = state;
|
||||
scheduleStructureUpdate();
|
||||
@@ -183,6 +185,7 @@ public class MavenProjectsNavigator extends MavenSimpleProjectComponent implemen
|
||||
listenForProjectsChanges();
|
||||
if (isUnitTestMode()) return;
|
||||
MavenUtil.runWhenInitialized(myProject, new DumbAwareRunnable() {
|
||||
@Override
|
||||
public void run() {
|
||||
if (myProject.isDisposed()) return;
|
||||
initToolWindow();
|
||||
@@ -200,8 +203,10 @@ public class MavenProjectsNavigator extends MavenSimpleProjectComponent implemen
|
||||
myProjectsManager.addProjectsTreeListener(new MyProjectsListener());
|
||||
|
||||
myShortcutsManager.addListener(new MavenShortcutsManager.Listener() {
|
||||
@Override
|
||||
public void shortcutsUpdated() {
|
||||
scheduleStructureRequest(new Runnable() {
|
||||
@Override
|
||||
public void run() {
|
||||
myStructure.updateGoals();
|
||||
}
|
||||
@@ -210,8 +215,10 @@ public class MavenProjectsNavigator extends MavenSimpleProjectComponent implemen
|
||||
});
|
||||
|
||||
myTasksManager.addListener(new MavenTasksManager.Listener() {
|
||||
@Override
|
||||
public void compileTasksChanged() {
|
||||
scheduleStructureRequest(new Runnable() {
|
||||
@Override
|
||||
public void run() {
|
||||
myStructure.updateGoals();
|
||||
}
|
||||
@@ -220,8 +227,10 @@ public class MavenProjectsNavigator extends MavenSimpleProjectComponent implemen
|
||||
});
|
||||
|
||||
RunManagerEx.getInstanceEx(myProject).addRunManagerListener(new RunManagerAdapter() {
|
||||
@Override
|
||||
public void beforeRunTasksChanged() {
|
||||
scheduleStructureRequest(new Runnable() {
|
||||
@Override
|
||||
public void run() {
|
||||
myStructure.updateGoals();
|
||||
}
|
||||
@@ -233,6 +242,7 @@ public class MavenProjectsNavigator extends MavenSimpleProjectComponent implemen
|
||||
@Override
|
||||
public void skipTestsChanged() {
|
||||
scheduleStructureRequest(new Runnable() {
|
||||
@Override
|
||||
public void run() {
|
||||
myStructure.updateGoals();
|
||||
}
|
||||
@@ -243,6 +253,7 @@ public class MavenProjectsNavigator extends MavenSimpleProjectComponent implemen
|
||||
((RunManagerEx)RunManager.getInstance(myProject)).addRunManagerListener(new RunManagerAdapter() {
|
||||
private void changed() {
|
||||
scheduleStructureRequest(new Runnable() {
|
||||
@Override
|
||||
public void run() {
|
||||
myStructure.updateRunConfigurations();
|
||||
}
|
||||
@@ -291,9 +302,11 @@ public class MavenProjectsNavigator extends MavenSimpleProjectComponent implemen
|
||||
public void stateChanged() {
|
||||
if (myToolWindow.isDisposed()) return;
|
||||
boolean visible = myToolWindow.isVisible();
|
||||
if (!visible || visible == wasVisible) return;
|
||||
if (!visible || wasVisible) {
|
||||
return;
|
||||
}
|
||||
scheduleStructureUpdate();
|
||||
wasVisible = visible;
|
||||
wasVisible = true;
|
||||
}
|
||||
};
|
||||
manager.addToolWindowManagerListener(listener, myProject);
|
||||
@@ -350,6 +363,7 @@ public class MavenProjectsNavigator extends MavenSimpleProjectComponent implemen
|
||||
|
||||
public void selectInTree(final MavenProject project) {
|
||||
scheduleStructureRequest(new Runnable() {
|
||||
@Override
|
||||
public void run() {
|
||||
myStructure.select(project);
|
||||
}
|
||||
@@ -364,6 +378,7 @@ public class MavenProjectsNavigator extends MavenSimpleProjectComponent implemen
|
||||
|
||||
if (myToolWindow == null) return;
|
||||
MavenUtil.invokeLater(myProject, new Runnable() {
|
||||
@Override
|
||||
public void run() {
|
||||
if (!myToolWindow.isVisible()) return;
|
||||
|
||||
@@ -396,6 +411,7 @@ public class MavenProjectsNavigator extends MavenSimpleProjectComponent implemen
|
||||
|
||||
private void scheduleStructureUpdate() {
|
||||
scheduleStructureRequest(new Runnable() {
|
||||
@Override
|
||||
public void run() {
|
||||
myStructure.update();
|
||||
}
|
||||
@@ -403,10 +419,12 @@ public class MavenProjectsNavigator extends MavenSimpleProjectComponent implemen
|
||||
}
|
||||
|
||||
private class MyProjectsListener extends MavenProjectsTree.ListenerAdapter implements MavenProjectsManager.Listener {
|
||||
@Override
|
||||
public void activated() {
|
||||
scheduleStructureUpdate();
|
||||
}
|
||||
|
||||
@Override
|
||||
public void projectsScheduled() {
|
||||
}
|
||||
|
||||
@@ -417,6 +435,7 @@ public class MavenProjectsNavigator extends MavenSimpleProjectComponent implemen
|
||||
@Override
|
||||
public void projectsIgnoredStateChanged(final List<MavenProject> ignored, final List<MavenProject> unignored, boolean fromImport) {
|
||||
scheduleStructureRequest(new Runnable() {
|
||||
@Override
|
||||
public void run() {
|
||||
myStructure.updateIgnored(ContainerUtil.concat(ignored, unignored));
|
||||
}
|
||||
@@ -426,6 +445,7 @@ public class MavenProjectsNavigator extends MavenSimpleProjectComponent implemen
|
||||
@Override
|
||||
public void profilesChanged() {
|
||||
scheduleStructureRequest(new Runnable() {
|
||||
@Override
|
||||
public void run() {
|
||||
myStructure.updateProfiles();
|
||||
}
|
||||
@@ -437,17 +457,20 @@ public class MavenProjectsNavigator extends MavenSimpleProjectComponent implemen
|
||||
scheduleUpdateProjects(MavenUtil.collectFirsts(updated), deleted);
|
||||
}
|
||||
|
||||
@Override
|
||||
public void projectResolved(Pair<MavenProject, MavenProjectChanges> projectWithChanges,
|
||||
NativeMavenProjectHolder nativeMavenProject) {
|
||||
scheduleUpdateProjects(Collections.singletonList(projectWithChanges.first), Collections.<MavenProject>emptyList());
|
||||
}
|
||||
|
||||
@Override
|
||||
public void pluginsResolved(MavenProject project) {
|
||||
scheduleUpdateProjects(Collections.singletonList(project), Collections.<MavenProject>emptyList());
|
||||
}
|
||||
|
||||
private void scheduleUpdateProjects(final List<MavenProject> projects, final List<MavenProject> deleted) {
|
||||
scheduleStructureRequest(new Runnable() {
|
||||
@Override
|
||||
public void run() {
|
||||
myStructure.updateProjects(projects, deleted);
|
||||
}
|
||||
|
||||
@@ -57,7 +57,7 @@
|
||||
groupName="TestNG" enabledByDefault="true" level="ERROR"
|
||||
implementationClass="com.theoryinpractice.testng.inspection.DataProviderReturnTypeInspection"/>
|
||||
|
||||
<testFramework implementation="com.theoryinpractice.testng.TestNGFramework"/>
|
||||
<testFramework implementation="com.theoryinpractice.testng.TestNGFramework" id="testNG"/>
|
||||
<codeInsight.externalLibraryResolver implementation="com.theoryinpractice.testng.intention.TestNGExternalLibraryResolver"/>
|
||||
<standardResource url="http://testng.org/testng-1.0.dtd" path="resources/standardSchemas/testng-1.0.dtd"/>
|
||||
<overrideImplementsAnnotationsHandler implementation="com.theoryinpractice.testng.intention.OverrideImplementsTestNGAnnotationsHandler"/>
|
||||
|
||||
@@ -15,6 +15,8 @@
|
||||
*/
|
||||
package com.intellij.uiDesigner.designSurface;
|
||||
|
||||
import com.intellij.ide.ui.UISettings;
|
||||
import com.intellij.ui.JBColor;
|
||||
import com.intellij.ui.LightColors;
|
||||
import com.intellij.uiDesigner.FormEditingUtil;
|
||||
import com.intellij.uiDesigner.SwingProperties;
|
||||
@@ -457,7 +459,8 @@ public final class Painter {
|
||||
Graphics2D g2d = (Graphics2D)g;
|
||||
g2d.setColor(PlatformColors.BLUE);
|
||||
g2d.fillRect(0, 0, (int)stringBounds.getWidth(), (int)stringBounds.getHeight());
|
||||
g2d.setColor(Color.WHITE);
|
||||
g2d.setColor(JBColor.WHITE);
|
||||
UISettings.setupAntialiasing(g);
|
||||
g.drawString(tagBuilder.toString(), 0, g.getFontMetrics().getAscent());
|
||||
}
|
||||
}
|
||||
|
||||
@@ -393,6 +393,7 @@ message.node.all.array.elements.null=All elements in range ({0}, {1}) are null
|
||||
message.node.all.elements.null=All elements are null
|
||||
message.node.empty.array=Empty
|
||||
message.node.class.has.no.fields=Class has no fields
|
||||
message.node.class.no.fields.to.display=No fields to display
|
||||
message.node.object.collected=Object has been garbage collected during method invocation
|
||||
message.node.thread.running=Thread is running
|
||||
message.node.thread.has.no.frames=Thread has no frames
|
||||
|
||||
@@ -115,7 +115,7 @@
|
||||
<attribute name="usemap" type="%URL" />
|
||||
</control>
|
||||
<control name="ol" type="HtmlGenericControl" startTag="required" endTag="required" emptyAllowed="false"/>
|
||||
<control name="option" type="HtmlGenericControl" startTag="required" endTag="optional" emptyAllowed="false" autoClosedBy="option"/>
|
||||
<control name="option" type="HtmlGenericControl" startTag="required" endTag="optional" emptyAllowed="false" autoClosedBy="option,optgroup"/>
|
||||
|
||||
<control name="P" type="HtmlGenericControl" startTag="required" endTag="optional" emptyAllowed="false" autoClosedBy="p"/>
|
||||
<control name="param" type="HtmlGenericControl" startTag="required" endTag="forbidden" emptyAllowed="true"/>
|
||||
|
||||
Reference in New Issue
Block a user