mirror of
https://gitflic.ru/project/openide/openide.git
synced 2026-09-27 10:03:11 +07:00
Merge remote-tracking branch 'origin/master'
This commit is contained in:
@@ -329,18 +329,10 @@ public class JavaDebugProcess extends XDebugProcess {
|
||||
private volatile boolean myAutoModeEnabled;
|
||||
|
||||
public AutoVarsSwitchAction() {
|
||||
super("", "", AllIcons.Debugger.AutoVariablesMode);
|
||||
super(DebuggerBundle.message("action.auto.variables.mode"), DebuggerBundle.message("action.auto.variables.mode.description"), null);
|
||||
myAutoModeEnabled = DebuggerSettings.getInstance().AUTO_VARIABLES_MODE;
|
||||
}
|
||||
|
||||
@Override
|
||||
public void update(@NotNull final AnActionEvent e) {
|
||||
super.update(e);
|
||||
final Presentation presentation = e.getPresentation();
|
||||
final boolean autoModeEnabled = Boolean.TRUE.equals(presentation.getClientProperty(SELECTED_PROPERTY));
|
||||
presentation.setText(autoModeEnabled ? "All-Variables Mode" : "Auto-Variables Mode");
|
||||
}
|
||||
|
||||
@Override
|
||||
public boolean isSelected(AnActionEvent e) {
|
||||
return myAutoModeEnabled;
|
||||
@@ -356,15 +348,13 @@ public class JavaDebugProcess extends XDebugProcess {
|
||||
|
||||
private static class WatchLastMethodReturnValueAction extends ToggleAction {
|
||||
private volatile boolean myWatchesReturnValues;
|
||||
private final String myTextEnable;
|
||||
private final String myText;
|
||||
private final String myTextUnavailable;
|
||||
private final String myMyTextDisable;
|
||||
|
||||
public WatchLastMethodReturnValueAction() {
|
||||
super("", DebuggerBundle.message("action.watch.method.return.value.description"), null);
|
||||
myWatchesReturnValues = DebuggerSettings.getInstance().WATCH_RETURN_VALUES;
|
||||
myTextEnable = DebuggerBundle.message("action.watches.method.return.value.enable");
|
||||
myMyTextDisable = DebuggerBundle.message("action.watches.method.return.value.disable");
|
||||
myText = DebuggerBundle.message("action.watches.method.return.value.enable");
|
||||
myTextUnavailable = DebuggerBundle.message("action.watches.method.return.value.unavailable.reason");
|
||||
}
|
||||
|
||||
@@ -372,12 +362,10 @@ public class JavaDebugProcess extends XDebugProcess {
|
||||
public void update(@NotNull final AnActionEvent e) {
|
||||
super.update(e);
|
||||
final Presentation presentation = e.getPresentation();
|
||||
final boolean watchValues = Boolean.TRUE.equals(presentation.getClientProperty(SELECTED_PROPERTY));
|
||||
DebugProcessImpl process = getCurrentDebugProcess(e.getProject());
|
||||
final String actionText = watchValues ? myMyTextDisable : myTextEnable;
|
||||
if (process == null || process.canGetMethodReturnValue()) {
|
||||
presentation.setEnabled(true);
|
||||
presentation.setText(actionText);
|
||||
presentation.setText(myText);
|
||||
}
|
||||
else {
|
||||
presentation.setEnabled(false);
|
||||
|
||||
@@ -27,7 +27,7 @@ import com.intellij.debugger.engine.events.DebuggerCommandImpl;
|
||||
import com.intellij.debugger.engine.events.SuspendContextCommandImpl;
|
||||
import com.intellij.debugger.impl.DebuggerContextImpl;
|
||||
import com.intellij.debugger.impl.DebuggerUtilsEx;
|
||||
import com.intellij.debugger.settings.ToStringBasedRenderer;
|
||||
import com.intellij.debugger.ui.tree.render.ToStringBasedRenderer;
|
||||
import com.intellij.debugger.ui.impl.DebuggerTreeRenderer;
|
||||
import com.intellij.debugger.ui.impl.watch.*;
|
||||
import com.intellij.debugger.ui.tree.*;
|
||||
|
||||
+5
-5
@@ -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.
|
||||
@@ -20,13 +20,13 @@
|
||||
*/
|
||||
package com.intellij.debugger.engine.evaluation.expression;
|
||||
|
||||
import com.intellij.debugger.DebuggerBundle;
|
||||
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;
|
||||
import com.intellij.debugger.impl.DebuggerUtilsEx;
|
||||
import com.intellij.debugger.ui.impl.watch.NodeDescriptorImpl;
|
||||
import com.intellij.debugger.ui.impl.watch.ArrayElementDescriptorImpl;
|
||||
import com.intellij.debugger.DebuggerBundle;
|
||||
import com.intellij.debugger.ui.impl.watch.NodeDescriptorImpl;
|
||||
import com.intellij.openapi.project.Project;
|
||||
import com.sun.jdi.*;
|
||||
|
||||
@@ -50,7 +50,7 @@ class ArrayAccessEvaluator implements Evaluator {
|
||||
throw EvaluateExceptionUtil.createEvaluateException(DebuggerBundle.message("evaluation.error.array.reference.expected"));
|
||||
}
|
||||
myEvaluatedArrayReference = (ArrayReference)arrayValue;
|
||||
if (!DebuggerUtilsEx.isInteger(indexValue)) {
|
||||
if (!DebuggerUtils.isInteger(indexValue)) {
|
||||
throw EvaluateExceptionUtil.createEvaluateException(DebuggerBundle.message("evaluation.error.invalid.index.expression"));
|
||||
}
|
||||
myEvaluatedIndex = ((PrimitiveValue)indexValue).intValue();
|
||||
|
||||
+2
-1
@@ -20,6 +20,7 @@
|
||||
*/
|
||||
package com.intellij.debugger.engine.evaluation.expression;
|
||||
|
||||
import com.intellij.Patches;
|
||||
import com.intellij.debugger.DebuggerBundle;
|
||||
import com.intellij.debugger.engine.DebugProcess;
|
||||
import com.intellij.debugger.engine.DebugProcessImpl;
|
||||
@@ -180,7 +181,7 @@ public class MethodEvaluator implements Evaluator {
|
||||
return debugProcess.invokeInstanceMethod(context, objRef, jdiMethod, args, ObjectReference.INVOKE_NONVIRTUAL);
|
||||
}
|
||||
// fix for default methods in interfaces, see IDEA-124066
|
||||
if (myCheckDefaultInterfaceMethod && jdiMethod.declaringType() instanceof InterfaceType) {
|
||||
if (Patches.JDK_BUG_ID_8042123 && myCheckDefaultInterfaceMethod && jdiMethod.declaringType() instanceof InterfaceType) {
|
||||
try {
|
||||
return invokeDefaultMethod(debugProcess, context, objRef, myMethodName);
|
||||
} catch (EvaluateException e) {
|
||||
|
||||
@@ -361,7 +361,8 @@ public class NodeRendererSettings implements PersistentStateComponent<Element> {
|
||||
return renderer;
|
||||
}
|
||||
|
||||
private ExpressionChildrenRenderer createExpressionChildrenRenderer(@NonNls String expressionText, @NonNls String childrenExpandableText) {
|
||||
public static ExpressionChildrenRenderer createExpressionChildrenRenderer(@NonNls String expressionText,
|
||||
@NonNls String childrenExpandableText) {
|
||||
final ExpressionChildrenRenderer childrenRenderer = new ExpressionChildrenRenderer();
|
||||
childrenRenderer.setChildrenExpression(new TextWithImportsImpl(CodeFragmentKind.EXPRESSION, expressionText, "", StdFileTypes.JAVA));
|
||||
if (childrenExpandableText != null) {
|
||||
@@ -370,7 +371,7 @@ public class NodeRendererSettings implements PersistentStateComponent<Element> {
|
||||
return childrenRenderer;
|
||||
}
|
||||
|
||||
private EnumerationChildrenRenderer createEnumerationChildrenRenderer(@NonNls String[][] expressions) {
|
||||
private static EnumerationChildrenRenderer createEnumerationChildrenRenderer(@NonNls String[][] expressions) {
|
||||
final EnumerationChildrenRenderer childrenRenderer = new EnumerationChildrenRenderer();
|
||||
if (expressions != null && expressions.length > 0) {
|
||||
final ArrayList<Pair<String, TextWithImports>> childrenList = new ArrayList<Pair<String, TextWithImports>>(expressions.length);
|
||||
|
||||
+1
-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.
|
||||
@@ -20,7 +20,6 @@ import com.intellij.debugger.engine.evaluation.EvaluateException;
|
||||
import com.intellij.debugger.engine.evaluation.EvaluateExceptionUtil;
|
||||
import com.intellij.debugger.engine.evaluation.EvaluationContextImpl;
|
||||
import com.intellij.debugger.ui.tree.ArrayElementDescriptor;
|
||||
import com.intellij.openapi.diagnostic.Logger;
|
||||
import com.intellij.openapi.project.Project;
|
||||
import com.intellij.psi.JavaPsiFacade;
|
||||
import com.intellij.psi.PsiElementFactory;
|
||||
@@ -31,8 +30,6 @@ import com.sun.jdi.ObjectCollectedException;
|
||||
import com.sun.jdi.Value;
|
||||
|
||||
public class ArrayElementDescriptorImpl extends ValueDescriptorImpl implements ArrayElementDescriptor{
|
||||
private static final Logger LOG = Logger.getInstance("#com.intellij.debugger.ui.impl.watch.ArrayElementDescriptorImpl");
|
||||
|
||||
private final int myIndex;
|
||||
private final ArrayReference myArray;
|
||||
|
||||
|
||||
+2
-2
@@ -13,12 +13,12 @@
|
||||
* See the License for the specific language governing permissions and
|
||||
* limitations under the License.
|
||||
*/
|
||||
package com.intellij.debugger.settings;
|
||||
package com.intellij.debugger.ui.tree.render;
|
||||
|
||||
import com.intellij.debugger.engine.evaluation.EvaluateException;
|
||||
import com.intellij.debugger.engine.evaluation.EvaluationContext;
|
||||
import com.intellij.debugger.settings.NodeRendererSettings;
|
||||
import com.intellij.debugger.ui.tree.ValueDescriptor;
|
||||
import com.intellij.debugger.ui.tree.render.DescriptorLabelListener;
|
||||
import com.intellij.util.ui.ColorIcon;
|
||||
import com.sun.jdi.*;
|
||||
|
||||
+4
-5
@@ -33,6 +33,7 @@ import com.intellij.openapi.util.DefaultJDOMExternalizer;
|
||||
import com.intellij.openapi.util.InvalidDataException;
|
||||
import com.intellij.openapi.util.Key;
|
||||
import com.intellij.openapi.util.WriteExternalException;
|
||||
import com.intellij.openapi.util.text.StringUtil;
|
||||
import com.intellij.psi.PsiExpression;
|
||||
import com.sun.jdi.BooleanValue;
|
||||
import com.sun.jdi.Value;
|
||||
@@ -148,7 +149,7 @@ public class ExpressionChildrenRenderer extends ReferenceRenderer implements Chi
|
||||
expressionValue, context);
|
||||
}
|
||||
|
||||
private NodeRenderer getChildrenRenderer(Value childrenValue, ValueDescriptor parentDescriptor) {
|
||||
private static NodeRenderer getChildrenRenderer(Value childrenValue, ValueDescriptor parentDescriptor) {
|
||||
NodeRenderer renderer = getLastChildrenRenderer(parentDescriptor);
|
||||
if (renderer == null || childrenValue == null || !renderer.isApplicable(childrenValue.type())) {
|
||||
renderer = DebugProcessImpl.getDefaultRenderer(childrenValue != null ? childrenValue.type() : null);
|
||||
@@ -160,7 +161,7 @@ public class ExpressionChildrenRenderer extends ReferenceRenderer implements Chi
|
||||
public boolean isExpandable(Value value, final EvaluationContext context, NodeDescriptor parentDescriptor) {
|
||||
final EvaluationContext evaluationContext = context.createEvaluationContext(value);
|
||||
|
||||
if(!"".equals(myChildrenExpandable.getReferenceExpression().getText())) {
|
||||
if(!StringUtil.isEmpty(myChildrenExpandable.getReferenceExpression().getText())) {
|
||||
try {
|
||||
Value expanded = myChildrenExpandable.getEvaluator(evaluationContext.getProject()).evaluate(evaluationContext);
|
||||
if(expanded instanceof BooleanValue) {
|
||||
@@ -174,9 +175,7 @@ public class ExpressionChildrenRenderer extends ReferenceRenderer implements Chi
|
||||
|
||||
try {
|
||||
Value children = evaluateChildren(evaluationContext, parentDescriptor);
|
||||
|
||||
ChildrenRenderer defaultChildrenRenderer = ((DebugProcessImpl)evaluationContext.getDebugProcess()).getDefaultRenderer(value.type());
|
||||
|
||||
ChildrenRenderer defaultChildrenRenderer = DebugProcessImpl.getDefaultRenderer(value.type());
|
||||
return defaultChildrenRenderer.isExpandable(children, evaluationContext, parentDescriptor);
|
||||
}
|
||||
catch (EvaluateException e) {
|
||||
|
||||
@@ -0,0 +1,29 @@
|
||||
/*
|
||||
* 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.debugger.ui.tree.render;
|
||||
|
||||
import com.intellij.debugger.settings.NodeRendererSettings;
|
||||
|
||||
/**
|
||||
* @author egor
|
||||
*/
|
||||
public class FileObjectRenderer extends ToStringBasedRenderer {
|
||||
public FileObjectRenderer(final NodeRendererSettings rendererSettings) {
|
||||
super(rendererSettings, "File", null, NodeRendererSettings.createExpressionChildrenRenderer("listFiles()", null));
|
||||
setClassName("java.io.File");
|
||||
setEnabled(true);
|
||||
}
|
||||
}
|
||||
+2
-1
@@ -13,12 +13,13 @@
|
||||
* See the License for the specific language governing permissions and
|
||||
* limitations under the License.
|
||||
*/
|
||||
package com.intellij.debugger.settings;
|
||||
package com.intellij.debugger.ui.tree.render;
|
||||
|
||||
import com.intellij.debugger.DebuggerBundle;
|
||||
import com.intellij.debugger.engine.DebuggerUtils;
|
||||
import com.intellij.debugger.engine.FullValueEvaluatorProvider;
|
||||
import com.intellij.debugger.engine.evaluation.EvaluationContextImpl;
|
||||
import com.intellij.debugger.settings.NodeRendererSettings;
|
||||
import com.intellij.debugger.ui.impl.watch.ValueDescriptorImpl;
|
||||
import com.intellij.xdebugger.frame.XFullValueEvaluator;
|
||||
import com.sun.jdi.*;
|
||||
+2
-2
@@ -13,7 +13,7 @@
|
||||
* See the License for the specific language governing permissions and
|
||||
* limitations under the License.
|
||||
*/
|
||||
package com.intellij.debugger.settings;
|
||||
package com.intellij.debugger.ui.tree.render;
|
||||
|
||||
import com.intellij.debugger.DebuggerBundle;
|
||||
import com.intellij.debugger.engine.FullValueEvaluatorProvider;
|
||||
@@ -21,9 +21,9 @@ import com.intellij.debugger.engine.evaluation.EvaluateException;
|
||||
import com.intellij.debugger.engine.evaluation.EvaluationContext;
|
||||
import com.intellij.debugger.engine.evaluation.EvaluationContextImpl;
|
||||
import com.intellij.debugger.impl.DebuggerUtilsImpl;
|
||||
import com.intellij.debugger.settings.NodeRendererSettings;
|
||||
import com.intellij.debugger.ui.impl.watch.ValueDescriptorImpl;
|
||||
import com.intellij.debugger.ui.tree.ValueDescriptor;
|
||||
import com.intellij.debugger.ui.tree.render.DescriptorLabelListener;
|
||||
import com.intellij.icons.AllIcons;
|
||||
import com.intellij.xdebugger.frame.XFullValueEvaluator;
|
||||
import org.jetbrains.annotations.Nullable;
|
||||
+3
-1
@@ -13,7 +13,7 @@
|
||||
* See the License for the specific language governing permissions and
|
||||
* limitations under the License.
|
||||
*/
|
||||
package com.intellij.debugger.settings;
|
||||
package com.intellij.debugger.ui.tree.render;
|
||||
|
||||
import com.intellij.debugger.DebuggerBundle;
|
||||
import com.intellij.debugger.engine.DebugProcess;
|
||||
@@ -22,6 +22,8 @@ import com.intellij.debugger.engine.evaluation.EvaluateException;
|
||||
import com.intellij.debugger.engine.evaluation.EvaluationContext;
|
||||
import com.intellij.debugger.engine.evaluation.EvaluationContextImpl;
|
||||
import com.intellij.debugger.impl.ClassLoadingUtils;
|
||||
import com.intellij.debugger.settings.CustomPopupFullValueEvaluator;
|
||||
import com.intellij.debugger.settings.NodeRendererSettings;
|
||||
import com.intellij.debugger.ui.impl.watch.ValueDescriptorImpl;
|
||||
import com.intellij.openapi.diagnostic.Logger;
|
||||
import com.intellij.rt.debugger.ImageSerializer;
|
||||
+2
-1
@@ -13,11 +13,12 @@
|
||||
* See the License for the specific language governing permissions and
|
||||
* limitations under the License.
|
||||
*/
|
||||
package com.intellij.debugger.settings;
|
||||
package com.intellij.debugger.ui.tree.render;
|
||||
|
||||
import com.intellij.debugger.DebuggerManagerEx;
|
||||
import com.intellij.debugger.engine.evaluation.EvaluateException;
|
||||
import com.intellij.debugger.engine.evaluation.EvaluationContext;
|
||||
import com.intellij.debugger.settings.NodeRendererSettings;
|
||||
import com.intellij.debugger.ui.tree.ValueDescriptor;
|
||||
import com.intellij.debugger.ui.tree.render.*;
|
||||
|
||||
@@ -25,6 +25,7 @@ import com.intellij.util.concurrency.AtomicFieldUpdater;
|
||||
import gnu.trove.TLongHashSet;
|
||||
import org.jetbrains.annotations.NonNls;
|
||||
import org.jetbrains.annotations.NotNull;
|
||||
import org.jetbrains.annotations.Nullable;
|
||||
|
||||
import java.lang.ref.ReferenceQueue;
|
||||
import java.lang.ref.WeakReference;
|
||||
@@ -42,7 +43,7 @@ import java.util.concurrent.locks.ReentrantReadWriteLock;
|
||||
*/
|
||||
abstract class IntervalTreeImpl<T extends MutableInterval> extends RedBlackTree<T> implements IntervalTree<T> {
|
||||
private int keySize; // number of all intervals, counting all duplicates, some of them maybe gced
|
||||
protected final ReadWriteLock l = new ReentrantReadWriteLock();
|
||||
final ReadWriteLock l = new ReentrantReadWriteLock();
|
||||
|
||||
protected abstract int compareEqualStartIntervals(@NotNull IntervalNode<T> i1, @NotNull IntervalNode<T> i2);
|
||||
private final ReferenceQueue<T> myReferenceQueue = new ReferenceQueue<T>();
|
||||
@@ -52,9 +53,9 @@ abstract class IntervalTreeImpl<T extends MutableInterval> extends RedBlackTree<
|
||||
private volatile int myStart;
|
||||
private volatile int myEnd;
|
||||
private static final byte ATTACHED_TO_TREE_FLAG = COLOR_MASK <<1; // true if the node is inserted to the tree
|
||||
protected final List<Getter<E>> intervals;
|
||||
final List<Getter<E>> intervals;
|
||||
int maxEnd; // max of all intervalEnd()s among all children.
|
||||
protected int delta; // delta of startOffset. getStartOffset() = myStartOffset + Sum of deltas up to root
|
||||
int delta; // delta of startOffset. getStartOffset() = myStartOffset + Sum of deltas up to root
|
||||
|
||||
private volatile long cachedDeltaUpToRoot; // field (packed to long for atomicity) containing deltaUpToRoot, node modCount and allDeltasUpAreNull flag
|
||||
// fields are packed as following
|
||||
@@ -62,6 +63,7 @@ abstract class IntervalTreeImpl<T extends MutableInterval> extends RedBlackTree<
|
||||
// private int deltaUpToRoot; // sum of all deltas up to the root (including this node' delta). Has valid value only if modCount == IntervalTreeImpl.this.modCount
|
||||
// private boolean allDeltasUpAreNull; // true if all deltas up the tree (including this node) are 0. Has valid value only if modCount == IntervalTreeImpl.this.modCount
|
||||
|
||||
@NotNull
|
||||
private final IntervalTreeImpl<E> myIntervalTree;
|
||||
|
||||
public IntervalNode(@NotNull IntervalTreeImpl<E> intervalTree, @NotNull E key, int start, int end) {
|
||||
@@ -170,7 +172,7 @@ abstract class IntervalTreeImpl<T extends MutableInterval> extends RedBlackTree<
|
||||
}
|
||||
|
||||
private static class WeakReferencedGetter<T> extends WeakReference<T> implements Getter<T> {
|
||||
private WeakReferencedGetter(T referent, ReferenceQueue<? super T> q) {
|
||||
private WeakReferencedGetter(@NotNull T referent, @NotNull ReferenceQueue<? super T> q) {
|
||||
super(referent, q);
|
||||
}
|
||||
|
||||
@@ -290,6 +292,7 @@ abstract class IntervalTreeImpl<T extends MutableInterval> extends RedBlackTree<
|
||||
return myEnd;
|
||||
}
|
||||
|
||||
@NotNull
|
||||
public IntervalTreeImpl<E> getTree() {
|
||||
return myIntervalTree;
|
||||
}
|
||||
@@ -373,12 +376,12 @@ abstract class IntervalTreeImpl<T extends MutableInterval> extends RedBlackTree<
|
||||
private void assertUnderWriteLock() {
|
||||
assert isAcquired(l.writeLock()) : l.writeLock();
|
||||
}
|
||||
private static boolean isAcquired(Lock l) {
|
||||
private static boolean isAcquired(@NotNull Lock l) {
|
||||
String s = l.toString();
|
||||
return s.contains("Locked by thread");
|
||||
}
|
||||
|
||||
private void pushDeltaFromRoot(IntervalNode<T> node) {
|
||||
private void pushDeltaFromRoot(@Nullable IntervalNode<T> node) {
|
||||
if (node != null) {
|
||||
long packedOffsets = node.cachedDeltaUpToRoot;
|
||||
if (IntervalNode.allDeltasUpAreNull(packedOffsets) && node.isValid() && IntervalNode.modCount(packedOffsets) == modCount) return;
|
||||
@@ -390,7 +393,7 @@ abstract class IntervalTreeImpl<T extends MutableInterval> extends RedBlackTree<
|
||||
@NotNull
|
||||
protected abstract IntervalNode<T> createNewNode(@NotNull T key, int start, int end, boolean greedyToLeft, boolean greedyToRight, int layer);
|
||||
protected abstract IntervalNode<T> lookupNode(@NotNull T key);
|
||||
protected abstract void setNode(@NotNull T key, IntervalNode<T> node);
|
||||
protected abstract void setNode(@NotNull T key, @Nullable IntervalNode<T> node);
|
||||
|
||||
private int compareNodes(@NotNull IntervalNode<T> i1, int delta1, @NotNull IntervalNode<T> i2, int delta2, @NotNull List<IntervalNode<T>> invalid) {
|
||||
if (!i2.hasAliveKey(false)) {
|
||||
@@ -411,14 +414,16 @@ abstract class IntervalTreeImpl<T extends MutableInterval> extends RedBlackTree<
|
||||
try {
|
||||
l.readLock().lock();
|
||||
checkMax(true);
|
||||
return process(getRoot(), processor, modCount);
|
||||
return process(getRoot(), modCount, processor);
|
||||
}
|
||||
finally {
|
||||
l.readLock().unlock();
|
||||
}
|
||||
}
|
||||
|
||||
private boolean process(final IntervalNode<T> root, final Processor<? super T> processor, final int modCountBefore) {
|
||||
private boolean process(@Nullable IntervalNode<T> root,
|
||||
final int modCountBefore,
|
||||
@NotNull final Processor<? super T> processor) {
|
||||
if (root == null) return true;
|
||||
|
||||
WalkingState.TreeGuide<IntervalNode<T>> guide = getGuide();
|
||||
@@ -437,19 +442,19 @@ abstract class IntervalTreeImpl<T extends MutableInterval> extends RedBlackTree<
|
||||
try {
|
||||
l.readLock().lock();
|
||||
checkMax(true);
|
||||
return processOverlappingWith(getRoot(), start, end, processor, modCount, 0);
|
||||
return processOverlappingWith(getRoot(), start, end, modCount, 0, processor);
|
||||
}
|
||||
finally {
|
||||
l.readLock().unlock();
|
||||
}
|
||||
}
|
||||
|
||||
private boolean processOverlappingWith(IntervalNode<T> root,
|
||||
private boolean processOverlappingWith(@Nullable IntervalNode<T> root,
|
||||
int start,
|
||||
int end,
|
||||
Processor<? super T> processor,
|
||||
int modCountBefore,
|
||||
int deltaUpToRootExclusive) {
|
||||
int deltaUpToRootExclusive,
|
||||
@NotNull Processor<? super T> processor) {
|
||||
if (root == null) {
|
||||
return true;
|
||||
}
|
||||
@@ -460,7 +465,7 @@ abstract class IntervalTreeImpl<T extends MutableInterval> extends RedBlackTree<
|
||||
return true; // right of the rightmost interval in the subtree
|
||||
}
|
||||
|
||||
if (!processOverlappingWith(root.getLeft(), start, end, processor, modCountBefore, delta)) return false;
|
||||
if (!processOverlappingWith(root.getLeft(), start, end, modCountBefore, delta, processor)) return false;
|
||||
int myStartOffset = root.intervalStart() + delta;
|
||||
int myEndOffset = root.intervalEnd() + delta;
|
||||
boolean overlaps = Math.max(myStartOffset, start) <= Math.min(myEndOffset, end);
|
||||
@@ -473,25 +478,25 @@ abstract class IntervalTreeImpl<T extends MutableInterval> extends RedBlackTree<
|
||||
return true; // left of the root, cant be in the right subtree
|
||||
}
|
||||
|
||||
return processOverlappingWith(root.getRight(), start, end, processor, modCountBefore, delta);
|
||||
return processOverlappingWith(root.getRight(), start, end, modCountBefore, delta, processor);
|
||||
}
|
||||
|
||||
boolean processOverlappingWithOutside(int start, int end, @NotNull Processor<? super T> processor) {
|
||||
try {
|
||||
l.readLock().lock();
|
||||
checkMax(true);
|
||||
return processOverlappingWithOutside(getRoot(), start, end, processor, modCount, 0);
|
||||
return processOverlappingWithOutside(getRoot(), start, end, modCount, 0, processor);
|
||||
}
|
||||
finally {
|
||||
l.readLock().unlock();
|
||||
}
|
||||
}
|
||||
private boolean processOverlappingWithOutside(IntervalNode<T> root,
|
||||
private boolean processOverlappingWithOutside(@Nullable IntervalNode<T> root,
|
||||
int start,
|
||||
int end,
|
||||
@NotNull Processor<? super T> processor,
|
||||
int modCountBefore,
|
||||
int deltaUpToRootExclusive) {
|
||||
int deltaUpToRootExclusive,
|
||||
@NotNull Processor<? super T> processor) {
|
||||
if (root == null) {
|
||||
return true;
|
||||
}
|
||||
@@ -502,7 +507,7 @@ abstract class IntervalTreeImpl<T extends MutableInterval> extends RedBlackTree<
|
||||
int rootStartOffset = root.intervalStart() + delta;
|
||||
int rootEndOffset = root.intervalEnd() + delta;
|
||||
|
||||
if (!processOverlappingWithOutside(root.getLeft(), start, end, processor, modCountBefore, delta)) return false;
|
||||
if (!processOverlappingWithOutside(root.getLeft(), start, end, modCountBefore, delta, processor)) return false;
|
||||
|
||||
boolean toProcess = rootStartOffset < start || rootEndOffset > end;
|
||||
if (toProcess) {
|
||||
@@ -512,7 +517,7 @@ abstract class IntervalTreeImpl<T extends MutableInterval> extends RedBlackTree<
|
||||
|
||||
if (rootStartOffset >= start && rootMaxEnd <= end) return true; // cant intersect outside
|
||||
|
||||
return processOverlappingWithOutside(root.getRight(), start, end, processor, modCountBefore, delta);
|
||||
return processOverlappingWithOutside(root.getRight(), start, end, modCountBefore, delta, processor);
|
||||
}
|
||||
|
||||
|
||||
@@ -521,17 +526,17 @@ abstract class IntervalTreeImpl<T extends MutableInterval> extends RedBlackTree<
|
||||
try {
|
||||
l.readLock().lock();
|
||||
checkMax(true);
|
||||
return processContaining(getRoot(), offset, processor, modCount, 0);
|
||||
return processContaining(getRoot(), offset, modCount, 0, processor);
|
||||
}
|
||||
finally {
|
||||
l.readLock().unlock();
|
||||
}
|
||||
}
|
||||
private boolean processContaining(IntervalNode<T> root,
|
||||
private boolean processContaining(@Nullable IntervalNode<T> root,
|
||||
int offset,
|
||||
Processor<? super T> processor,
|
||||
int modCountBefore,
|
||||
int deltaUpToRootExclusive) {
|
||||
int deltaUpToRootExclusive,
|
||||
@NotNull Processor<? super T> processor) {
|
||||
if (root == null) {
|
||||
return true;
|
||||
}
|
||||
@@ -541,7 +546,7 @@ abstract class IntervalTreeImpl<T extends MutableInterval> extends RedBlackTree<
|
||||
return true; // right of the rightmost interval in the subtree
|
||||
}
|
||||
|
||||
if (!processContaining(root.getLeft(), offset, processor, modCountBefore, delta)) return false;
|
||||
if (!processContaining(root.getLeft(), offset, modCountBefore, delta, processor)) return false;
|
||||
int myStartOffset = root.intervalStart() + delta;
|
||||
int myEndOffset = root.intervalEnd() + delta;
|
||||
boolean overlaps = myStartOffset <= offset && offset < myEndOffset;
|
||||
@@ -555,7 +560,7 @@ abstract class IntervalTreeImpl<T extends MutableInterval> extends RedBlackTree<
|
||||
return true; // left of the root, cant be in the right subtree
|
||||
}
|
||||
|
||||
return processContaining(root.getRight(), offset, processor, modCountBefore, delta);
|
||||
return processContaining(root.getRight(), offset, modCountBefore, delta, processor);
|
||||
}
|
||||
|
||||
interface PeekableIterator<T> extends DisposableIterator<T> {
|
||||
@@ -608,7 +613,7 @@ abstract class IntervalTreeImpl<T extends MutableInterval> extends RedBlackTree<
|
||||
return new PeekableIterator<T>() {
|
||||
private IntervalNode<T> currentNode = firstOverlap;
|
||||
private int deltaUpToRootExclusive = firstOverlapDelta-firstOverlap.delta;
|
||||
private int indexInCurrentList = 0;
|
||||
private int indexInCurrentList;
|
||||
private T current;
|
||||
|
||||
@Override
|
||||
@@ -717,7 +722,7 @@ abstract class IntervalTreeImpl<T extends MutableInterval> extends RedBlackTree<
|
||||
}
|
||||
}
|
||||
|
||||
private boolean overlaps(IntervalNode<T> root, @NotNull TextRangeInterval rangeInterval, int deltaUpToRootExclusive) {
|
||||
private boolean overlaps(@Nullable IntervalNode<T> root, @NotNull TextRangeInterval rangeInterval, int deltaUpToRootExclusive) {
|
||||
if (root == null) return false;
|
||||
int delta = root.delta + deltaUpToRootExclusive;
|
||||
int start = root.intervalStart() + delta;
|
||||
@@ -725,6 +730,7 @@ abstract class IntervalTreeImpl<T extends MutableInterval> extends RedBlackTree<
|
||||
return rangeInterval.intersects(start, end);
|
||||
}
|
||||
|
||||
@NotNull
|
||||
IntervalNode<T> findOrInsert(@NotNull IntervalNode<T> node) {
|
||||
assertUnderWriteLock();
|
||||
node.setRed();
|
||||
@@ -789,7 +795,11 @@ abstract class IntervalTreeImpl<T extends MutableInterval> extends RedBlackTree<
|
||||
}
|
||||
}
|
||||
|
||||
@NotNull
|
||||
public IntervalTreeImpl.IntervalNode<T> addInterval(@NotNull T interval, int start, int end, boolean greedyToLeft, boolean greedyToRight, int layer) {
|
||||
if (firingBeforeRemove) {
|
||||
throw new IncorrectOperationException("Must not add rangemarker from within beforeRemoved listener");
|
||||
}
|
||||
try {
|
||||
l.writeLock().lock();
|
||||
checkMax(true);
|
||||
@@ -852,13 +862,13 @@ abstract class IntervalTreeImpl<T extends MutableInterval> extends RedBlackTree<
|
||||
}
|
||||
|
||||
// returns real (minStart, maxStart, maxEnd)
|
||||
private IntTrinity checkMax(IntervalNode<T> root,
|
||||
private IntTrinity checkMax(@Nullable IntervalNode<T> root,
|
||||
int deltaUpToRootExclusive,
|
||||
boolean assertInvalid,
|
||||
AtomicBoolean allValid,
|
||||
int[] keyCounter,
|
||||
int[] nodeCounter,
|
||||
TLongHashSet ids,
|
||||
@NotNull AtomicBoolean allValid,
|
||||
@NotNull int[] keyCounter,
|
||||
@NotNull int[] nodeCounter,
|
||||
@NotNull TLongHashSet ids,
|
||||
boolean allDeltasUpAreNull) {
|
||||
if (root == null) return new IntTrinity(Integer.MAX_VALUE,Integer.MIN_VALUE,Integer.MIN_VALUE);
|
||||
long packedOffsets = root.cachedDeltaUpToRoot;
|
||||
@@ -914,8 +924,9 @@ abstract class IntervalTreeImpl<T extends MutableInterval> extends RedBlackTree<
|
||||
return new IntTrinity(minStart, maxStart, root.maxEnd + delta);
|
||||
}
|
||||
|
||||
@NotNull
|
||||
@Override
|
||||
protected Node<T> maximumNode(Node<T> n) {
|
||||
protected Node<T> maximumNode(@NotNull Node<T> n) {
|
||||
IntervalNode<T> root = (IntervalNode<T>)n;
|
||||
pushDelta(root.getParent());
|
||||
pushDelta(root);
|
||||
@@ -926,7 +937,7 @@ abstract class IntervalTreeImpl<T extends MutableInterval> extends RedBlackTree<
|
||||
return root;
|
||||
}
|
||||
|
||||
protected void checkBelongsToTheTree(T interval, boolean assertInvalid) {
|
||||
protected void checkBelongsToTheTree(@NotNull T interval, boolean assertInvalid) {
|
||||
IntervalNode<T> root = lookupNode(interval);
|
||||
if (root == null) return;
|
||||
assert root.getTree() == this : root.getTree() +"; this: "+this;
|
||||
@@ -966,7 +977,7 @@ abstract class IntervalTreeImpl<T extends MutableInterval> extends RedBlackTree<
|
||||
IntervalNode<T> node = lookupNode(interval);
|
||||
if (node == null) return false;
|
||||
|
||||
reportInvalidation(interval, "Explicit Dispose");
|
||||
beforeRemove(interval, "Explicit Dispose");
|
||||
|
||||
node.removeInterval(interval);
|
||||
setNode(interval, null);
|
||||
@@ -1005,7 +1016,7 @@ abstract class IntervalTreeImpl<T extends MutableInterval> extends RedBlackTree<
|
||||
}
|
||||
|
||||
// returns true if all deltas involved are still 0
|
||||
boolean pushDelta(IntervalNode<T> root) {
|
||||
boolean pushDelta(@Nullable IntervalNode<T> root) {
|
||||
if (root == null || !root.isValid()) return true;
|
||||
IntervalNode<T> parent = root.getParent();
|
||||
assertAllDeltasAreNull(parent);
|
||||
@@ -1026,7 +1037,7 @@ abstract class IntervalTreeImpl<T extends MutableInterval> extends RedBlackTree<
|
||||
}
|
||||
|
||||
// returns true if all deltas involved are still 0
|
||||
private boolean incDelta(IntervalNode<T> root, int delta) {
|
||||
private boolean incDelta(@Nullable IntervalNode<T> root, int delta) {
|
||||
if (root == null) return true;
|
||||
if (root.isValid()) {
|
||||
int newDelta = root.changeDelta(delta);
|
||||
@@ -1041,7 +1052,8 @@ abstract class IntervalTreeImpl<T extends MutableInterval> extends RedBlackTree<
|
||||
}
|
||||
|
||||
@Override
|
||||
protected IntervalNode<T> swapWithMaxPred(Node<T> root, Node<T> maxPred) {
|
||||
@NotNull
|
||||
protected IntervalNode<T> swapWithMaxPred(@NotNull Node<T> root, @NotNull Node<T> maxPred) {
|
||||
checkMax(false);
|
||||
IntervalNode<T> a = (IntervalNode<T>)root;
|
||||
IntervalNode<T> d = (IntervalNode<T>)maxPred;
|
||||
@@ -1068,7 +1080,7 @@ abstract class IntervalTreeImpl<T extends MutableInterval> extends RedBlackTree<
|
||||
assert d.delta == 0 : d.delta;
|
||||
return a;
|
||||
}
|
||||
private void swapNodes(IntervalNode<T> n1, IntervalNode<T> n2) {
|
||||
private void swapNodes(@NotNull IntervalNode<T> n1, @NotNull IntervalNode<T> n2) {
|
||||
IntervalNode<T> l1 = n1.getLeft();
|
||||
IntervalNode<T> r1 = n1.getRight();
|
||||
IntervalNode<T> p1 = n1.getParent();
|
||||
@@ -1102,7 +1114,7 @@ abstract class IntervalTreeImpl<T extends MutableInterval> extends RedBlackTree<
|
||||
}
|
||||
|
||||
// returns real max endOffset of all intervals below
|
||||
private int maxEndOf(IntervalNode<T> node, int deltaUpToRootExclusive) {
|
||||
private int maxEndOf(@Nullable IntervalNode<T> node, int deltaUpToRootExclusive) {
|
||||
if (node == null) {
|
||||
return 0;
|
||||
}
|
||||
@@ -1121,7 +1133,7 @@ abstract class IntervalTreeImpl<T extends MutableInterval> extends RedBlackTree<
|
||||
node.maxEnd = realMax - deltaUpToRoot;
|
||||
}
|
||||
|
||||
private void correctMaxUp(IntervalNode<T> node) {
|
||||
private void correctMaxUp(@Nullable IntervalNode<T> node) {
|
||||
int delta = node == null ? 0 : node.computeDeltaUpToRoot();
|
||||
assert delta == 0 : delta;
|
||||
while (node != null) {
|
||||
@@ -1136,7 +1148,7 @@ abstract class IntervalTreeImpl<T extends MutableInterval> extends RedBlackTree<
|
||||
}
|
||||
|
||||
@Override
|
||||
protected void rotateRight(Node<T> n) {
|
||||
protected void rotateRight(@NotNull Node<T> n) {
|
||||
checkMax(false);
|
||||
IntervalNode<T> node1 = (IntervalNode<T>)n;
|
||||
IntervalNode<T> node2 = node1.getLeft();
|
||||
@@ -1162,7 +1174,7 @@ abstract class IntervalTreeImpl<T extends MutableInterval> extends RedBlackTree<
|
||||
}
|
||||
|
||||
@Override
|
||||
protected void rotateLeft(Node<T> n) {
|
||||
protected void rotateLeft(@NotNull Node<T> n) {
|
||||
checkMax(false);
|
||||
IntervalNode<T> node1 = (IntervalNode<T>)n;
|
||||
IntervalNode<T> node2 = node1.getLeft();
|
||||
@@ -1201,7 +1213,7 @@ abstract class IntervalTreeImpl<T extends MutableInterval> extends RedBlackTree<
|
||||
}
|
||||
}
|
||||
|
||||
private void assertAllDeltasAreNull(IntervalNode<T> node) {
|
||||
private void assertAllDeltasAreNull(@Nullable IntervalNode<T> node) {
|
||||
if (node == null) return;
|
||||
if (!node.isValid()) return;
|
||||
assert node.delta == 0;
|
||||
@@ -1209,7 +1221,7 @@ abstract class IntervalTreeImpl<T extends MutableInterval> extends RedBlackTree<
|
||||
assert IntervalNode.modCount(packedOffsets) != modCount || IntervalNode.allDeltasUpAreNull(packedOffsets);
|
||||
}
|
||||
|
||||
private IntervalNode<T> findMinOverlappingWith(IntervalNode<T> root, Interval interval, int modCountBefore, int deltaUpToRootExclusive) {
|
||||
private IntervalNode<T> findMinOverlappingWith(@Nullable IntervalNode<T> root, @NotNull Interval interval, int modCountBefore, int deltaUpToRootExclusive) {
|
||||
if (root == null) {
|
||||
return null;
|
||||
}
|
||||
@@ -1235,7 +1247,7 @@ abstract class IntervalTreeImpl<T extends MutableInterval> extends RedBlackTree<
|
||||
return findMinOverlappingWith(root.getRight(), interval, modCountBefore, delta);
|
||||
}
|
||||
|
||||
void changeData(T interval, int start, int end, boolean greedyToLeft, boolean greedyToRight, int layer) {
|
||||
void changeData(@NotNull T interval, int start, int end, boolean greedyToLeft, boolean greedyToRight, int layer) {
|
||||
try {
|
||||
l.writeLock().lock();
|
||||
|
||||
@@ -1284,14 +1296,14 @@ abstract class IntervalTreeImpl<T extends MutableInterval> extends RedBlackTree<
|
||||
|
||||
@Override
|
||||
public void clear() {
|
||||
l.writeLock().lock();
|
||||
process(new Processor<T>() {
|
||||
@Override
|
||||
public boolean process(T t) {
|
||||
reportInvalidation(t, "Clear all");
|
||||
beforeRemove(t, "Clear all");
|
||||
return true;
|
||||
}
|
||||
});
|
||||
l.writeLock().lock();
|
||||
try {
|
||||
super.clear();
|
||||
keySize = 0;
|
||||
@@ -1301,23 +1313,39 @@ abstract class IntervalTreeImpl<T extends MutableInterval> extends RedBlackTree<
|
||||
}
|
||||
}
|
||||
|
||||
private void collectGced(IntervalNode<T> root, List<IntervalNode<T>> gced) {
|
||||
private void collectGced(@Nullable IntervalNode<T> root, @NotNull List<IntervalNode<T>> gced) {
|
||||
if (root == null) return;
|
||||
if (!root.hasAliveKey(true)) gced.add(root);
|
||||
if (!root.hasAliveKey(true)) {
|
||||
gced.add(root);
|
||||
}
|
||||
collectGced(root.getLeft(), gced);
|
||||
collectGced(root.getRight(), gced);
|
||||
}
|
||||
|
||||
|
||||
private void printSorted() { printSorted(getRoot());}
|
||||
private void printSorted(IntervalNode<T> root) {
|
||||
private void printSorted(@Nullable IntervalNode<T> root) {
|
||||
if (root == null) return;
|
||||
printSorted(root.getLeft());
|
||||
System.out.println(root);
|
||||
printSorted(root.getRight());
|
||||
}
|
||||
|
||||
void reportInvalidation(T markerEx, @NonNls Object reason) {
|
||||
void fireBeforeRemoved(@NotNull T markerEx, @NotNull @NonNls Object reason) {
|
||||
}
|
||||
|
||||
private boolean firingBeforeRemove; // accessed under l.writeLock() only
|
||||
void beforeRemove(@NotNull T markerEx, @NonNls @NotNull Object reason) {
|
||||
if (firingBeforeRemove) {
|
||||
throw new IllegalStateException();
|
||||
}
|
||||
firingBeforeRemove = true;
|
||||
try {
|
||||
fireBeforeRemoved(markerEx, reason);
|
||||
}
|
||||
finally {
|
||||
firingBeforeRemove = false;
|
||||
}
|
||||
}
|
||||
|
||||
private static class IntervalTreeGuide<T extends MutableInterval> implements WalkingState.TreeGuide<IntervalNode<T>> {
|
||||
@@ -1348,6 +1376,7 @@ abstract class IntervalTreeImpl<T extends MutableInterval> extends RedBlackTree<
|
||||
}
|
||||
|
||||
private static final IntervalTreeGuide INTERVAL_TREE_GUIDE_INSTANCE = new IntervalTreeGuide();
|
||||
@NotNull
|
||||
private static <T extends MutableInterval> WalkingState.TreeGuide<IntervalNode<T>> getGuide() {
|
||||
//noinspection unchecked
|
||||
return (WalkingState.TreeGuide)INTERVAL_TREE_GUIDE_INSTANCE;
|
||||
@@ -1358,7 +1387,7 @@ abstract class IntervalTreeImpl<T extends MutableInterval> extends RedBlackTree<
|
||||
return maxHeight(root);
|
||||
}
|
||||
|
||||
private int maxHeight(Node<T> root) {
|
||||
private int maxHeight(@Nullable Node<T> root) {
|
||||
return root == null ? 0 : 1 + Math.max(maxHeight(root.left), maxHeight(root.right));
|
||||
}
|
||||
|
||||
|
||||
@@ -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.
|
||||
@@ -15,6 +15,7 @@
|
||||
*/
|
||||
package com.intellij.openapi.editor.impl;
|
||||
|
||||
import com.intellij.openapi.editor.Document;
|
||||
import com.intellij.openapi.editor.event.DocumentEvent;
|
||||
import com.intellij.openapi.editor.ex.DocumentEx;
|
||||
import com.intellij.openapi.editor.impl.event.DocumentEventImpl;
|
||||
@@ -43,6 +44,7 @@ class PersistentRangeMarker extends RangeMarkerImpl {
|
||||
private void storeLinesAndCols(DocumentEvent e) {
|
||||
// document might have been changed already
|
||||
int startOffset = getStartOffset();
|
||||
Document myDocument = getDocument();
|
||||
if (startOffset <= myDocument.getTextLength()) {
|
||||
myStartLine = myDocument.getLineNumber(startOffset);
|
||||
myStartColumn = startOffset - myDocument.getLineStartOffset(myStartLine);
|
||||
|
||||
@@ -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.
|
||||
@@ -27,8 +27,8 @@ import org.jetbrains.annotations.NotNull;
|
||||
public class RangeMarkerImpl extends UserDataHolderBase implements RangeMarkerEx, MutableInterval {
|
||||
private static final Logger LOG = Logger.getInstance("#com.intellij.openapi.editor.impl.RangeMarkerImpl");
|
||||
|
||||
protected final DocumentEx myDocument;
|
||||
protected RangeMarkerTree.RMNode<RangeMarkerEx> myNode;
|
||||
private final DocumentEx myDocument;
|
||||
RangeMarkerTree.RMNode<RangeMarkerEx> myNode;
|
||||
|
||||
private final long myId;
|
||||
private static final StripedIDGenerator counter = new StripedIDGenerator();
|
||||
@@ -89,7 +89,7 @@ public class RangeMarkerImpl extends UserDataHolderBase implements RangeMarkerEx
|
||||
return intervalEnd() + (node == null ? 0 : node.computeDeltaUpToRoot());
|
||||
}
|
||||
|
||||
public void invalidate(@NotNull final Object reason) {
|
||||
void invalidate(@NotNull final Object reason) {
|
||||
setValid(false);
|
||||
RangeMarkerTree.RMNode<RangeMarkerEx> node = myNode;
|
||||
|
||||
@@ -97,7 +97,7 @@ public class RangeMarkerImpl extends UserDataHolderBase implements RangeMarkerEx
|
||||
node.processAliveKeys(new Processor<RangeMarkerEx>() {
|
||||
@Override
|
||||
public boolean process(RangeMarkerEx markerEx) {
|
||||
myNode.getTree().reportInvalidation(markerEx, reason);
|
||||
myNode.getTree().beforeRemove(markerEx, reason);
|
||||
return true;
|
||||
}
|
||||
});
|
||||
|
||||
@@ -29,6 +29,7 @@ import com.intellij.openapi.util.Segment;
|
||||
import com.intellij.util.Processor;
|
||||
import com.intellij.util.SmartList;
|
||||
import org.jetbrains.annotations.NotNull;
|
||||
import org.jetbrains.annotations.Nullable;
|
||||
|
||||
import java.util.*;
|
||||
import java.util.concurrent.atomic.AtomicInteger;
|
||||
@@ -88,16 +89,16 @@ public class RangeMarkerTree<T extends RangeMarkerEx> extends IntervalTreeImpl<T
|
||||
return 0;
|
||||
}
|
||||
|
||||
public void dispose() {
|
||||
void dispose() {
|
||||
myDocument.removeDocumentListener(myListener);
|
||||
}
|
||||
|
||||
private static final int DUPLICATE_LIMIT = 30; // assertion: no more than DUPLICATE_LIMIT range markers are allowed to be registered at given (start, end)
|
||||
@NotNull
|
||||
@Override
|
||||
public RMNode<T> addInterval(@NotNull T interval, int start, int end, boolean greedyToLeft, boolean greedyToRight, int layer) {
|
||||
RangeMarkerImpl marker = (RangeMarkerImpl)interval;
|
||||
marker.setValid(true);
|
||||
RMNode<T> node = (RMNode)super.addInterval(interval, start, end, greedyToLeft, greedyToRight, layer);
|
||||
interval.setValid(true);
|
||||
RMNode<T> node = (RMNode<T>)super.addInterval(interval, start, end, greedyToLeft, greedyToRight, layer);
|
||||
|
||||
if (DEBUG && !ApplicationInfoImpl.isInPerformanceTest() && node.intervals.size() > DUPLICATE_LIMIT) {
|
||||
l.readLock().lock();
|
||||
@@ -136,18 +137,20 @@ public class RangeMarkerTree<T extends RangeMarkerEx> extends IntervalTreeImpl<T
|
||||
}
|
||||
|
||||
@Override
|
||||
protected void checkBelongsToTheTree(T interval, boolean assertInvalid) {
|
||||
assert ((RangeMarkerImpl)interval).myDocument == myDocument;
|
||||
protected void checkBelongsToTheTree(@NotNull T interval, boolean assertInvalid) {
|
||||
assert interval.getDocument() == myDocument;
|
||||
super.checkBelongsToTheTree(interval, assertInvalid);
|
||||
}
|
||||
|
||||
@Override
|
||||
protected RMNode<T> lookupNode(@NotNull T key) {
|
||||
//noinspection unchecked
|
||||
return (RMNode<T>)((RangeMarkerImpl)key).myNode;
|
||||
}
|
||||
|
||||
@Override
|
||||
protected void setNode(@NotNull T key, IntervalNode<T> intervalNode) {
|
||||
//noinspection unchecked
|
||||
((RangeMarkerImpl)key).myNode = (RMNode)intervalNode;
|
||||
}
|
||||
|
||||
@@ -166,11 +169,11 @@ public class RangeMarkerTree<T extends RangeMarkerEx> extends IntervalTreeImpl<T
|
||||
setFlag(EXPAND_TO_RIGHT_FLAG, greedyToRight);
|
||||
}
|
||||
|
||||
public boolean isGreedyToLeft() {
|
||||
boolean isGreedyToLeft() {
|
||||
return isFlagSet(EXPAND_TO_LEFT_FLAG);
|
||||
}
|
||||
|
||||
public boolean isGreedyToRight() {
|
||||
boolean isGreedyToRight() {
|
||||
return isFlagSet(EXPAND_TO_RIGHT_FLAG);
|
||||
}
|
||||
|
||||
@@ -256,7 +259,7 @@ public class RangeMarkerTree<T extends RangeMarkerEx> extends IntervalTreeImpl<T
|
||||
}
|
||||
|
||||
// returns true if all deltas involved are still 0
|
||||
private boolean collectAffectedMarkersAndShiftSubtrees(IntervalNode<T> root,
|
||||
private boolean collectAffectedMarkersAndShiftSubtrees(@Nullable IntervalNode<T> root,
|
||||
@NotNull DocumentEvent e,
|
||||
@NotNull List<IntervalNode<T>> affected) {
|
||||
if (root == null) return true;
|
||||
@@ -303,7 +306,7 @@ public class RangeMarkerTree<T extends RangeMarkerEx> extends IntervalTreeImpl<T
|
||||
return norm;
|
||||
}
|
||||
|
||||
public boolean sweep(final int start, final int end, @NotNull final SweepProcessor<T> sweepProcessor) {
|
||||
public boolean sweep(final int start, final int end, @NotNull SweepProcessor<T> sweepProcessor) {
|
||||
return sweep(new Generator<T>() {
|
||||
@Override
|
||||
public boolean generateInStartOffsetOrder(@NotNull Processor<T> processor) {
|
||||
@@ -319,7 +322,7 @@ public class RangeMarkerTree<T extends RangeMarkerEx> extends IntervalTreeImpl<T
|
||||
public static <T extends Segment> boolean sweep(@NotNull Generator<T> generator, @NotNull final SweepProcessor<T> sweepProcessor) {
|
||||
final Queue<T> ends = new PriorityQueue<T>(5, new Comparator<T>() {
|
||||
@Override
|
||||
public int compare(T o1, T o2) {
|
||||
public int compare(@NotNull T o1, @NotNull T o2) {
|
||||
return o1.getEndOffset() - o2.getEndOffset();
|
||||
}
|
||||
});
|
||||
@@ -391,7 +394,7 @@ public class RangeMarkerTree<T extends RangeMarkerEx> extends IntervalTreeImpl<T
|
||||
}
|
||||
}
|
||||
|
||||
private void collectNodesToRetarget(IntervalNode<T> root,
|
||||
private void collectNodesToRetarget(@Nullable IntervalNode<T> root,
|
||||
int start, int end,
|
||||
@NotNull List<IntervalNode<T>> affected) {
|
||||
if (root == null) return;
|
||||
|
||||
@@ -36,7 +36,7 @@ public abstract class RedBlackTree<K> {
|
||||
verifyProperties();
|
||||
}
|
||||
|
||||
protected void rotateLeft(Node<K> n) {
|
||||
protected void rotateLeft(@NotNull Node<K> n) {
|
||||
Node<K> r = n.getRight();
|
||||
replaceNode(n, r);
|
||||
n.setRight(r.getLeft());
|
||||
@@ -47,7 +47,7 @@ public abstract class RedBlackTree<K> {
|
||||
n.setParent(r);
|
||||
}
|
||||
|
||||
protected void rotateRight(Node<K> n) {
|
||||
protected void rotateRight(@NotNull Node<K> n) {
|
||||
Node<K> l = n.getLeft();
|
||||
replaceNode(n, l);
|
||||
n.setLeft(l.getRight());
|
||||
@@ -177,10 +177,11 @@ public abstract class RedBlackTree<K> {
|
||||
verifyProperties();
|
||||
}
|
||||
|
||||
protected abstract Node<K> swapWithMaxPred(Node<K> nowAscendant, Node<K> nowDescendant);
|
||||
@NotNull
|
||||
protected abstract Node<K> swapWithMaxPred(@NotNull Node<K> nowAscendant, @NotNull Node<K> nowDescendant);
|
||||
|
||||
protected Node<K> maximumNode(Node<K> n) {
|
||||
assert n != null;
|
||||
@NotNull
|
||||
protected Node<K> maximumNode(@NotNull Node<K> n) {
|
||||
while (n.getRight() != null) {
|
||||
n = n.getRight();
|
||||
}
|
||||
|
||||
+3
-3
@@ -1,5 +1,5 @@
|
||||
/*
|
||||
* Copyright 2000-2010 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.
|
||||
@@ -66,13 +66,13 @@ public class RangeHighlighterTree extends RangeMarkerTree<RangeHighlighterEx> {
|
||||
//range highlighters are strongly referenced
|
||||
@Override
|
||||
protected Getter<RangeHighlighterEx> createGetter(@NotNull RangeHighlighterEx interval) {
|
||||
//noinspection unchecked
|
||||
return (Getter<RangeHighlighterEx>)interval;
|
||||
}
|
||||
}
|
||||
|
||||
@Override
|
||||
void reportInvalidation(RangeHighlighterEx markerEx, Object reason) {
|
||||
super.reportInvalidation(markerEx, reason);
|
||||
void fireBeforeRemoved(@NotNull RangeHighlighterEx markerEx, @NotNull Object reason) {
|
||||
myMarkupModel.fireBeforeRemoved(markerEx);
|
||||
}
|
||||
}
|
||||
|
||||
@@ -20,8 +20,6 @@ import com.intellij.openapi.actionSystem.DataContext;
|
||||
import com.intellij.openapi.editor.Editor;
|
||||
import com.intellij.openapi.editor.LogicalPosition;
|
||||
import com.intellij.openapi.editor.ex.util.EditorUtil;
|
||||
import com.intellij.openapi.project.Project;
|
||||
import com.intellij.openapi.wm.ToolWindowManager;
|
||||
import org.jetbrains.annotations.Nullable;
|
||||
|
||||
/**
|
||||
@@ -48,13 +46,9 @@ public abstract class EditorMacro extends Macro {
|
||||
|
||||
@Override
|
||||
public final String expand(DataContext dataContext) throws ExecutionCancelledException {
|
||||
Project project = CommonDataKeys.PROJECT.getData(dataContext);
|
||||
if (project == null) return null;
|
||||
if (ToolWindowManager.getInstance(project).isEditorComponentActive()) {
|
||||
Editor editor = CommonDataKeys.EDITOR.getData(dataContext);
|
||||
if (editor != null){
|
||||
return expand(editor);
|
||||
}
|
||||
Editor editor = CommonDataKeys.EDITOR.getData(dataContext);
|
||||
if (editor != null){
|
||||
return expand(editor);
|
||||
}
|
||||
return null;
|
||||
}
|
||||
|
||||
@@ -27,6 +27,7 @@ import com.intellij.psi.PsiDocumentManager;
|
||||
import com.intellij.psi.PsiElement;
|
||||
import com.intellij.psi.PsiFile;
|
||||
import com.intellij.psi.TokenType;
|
||||
import com.intellij.psi.codeStyle.CodeStyleManager;
|
||||
import com.intellij.psi.impl.source.SourceTreeToPsiMap;
|
||||
import com.intellij.psi.impl.source.tree.injected.InjectedLanguageUtil;
|
||||
import org.jetbrains.annotations.NotNull;
|
||||
@@ -36,18 +37,19 @@ public class PsiBasedFormattingModel implements FormattingModelEx {
|
||||
|
||||
private static final Logger LOG = Logger.getInstance("#com.intellij.psi.formatter.PsiBasedFormattingModel");
|
||||
|
||||
private final Project myProject;
|
||||
private final ASTNode myASTNode;
|
||||
private final FormattingDocumentModelImpl myDocumentModel;
|
||||
@NotNull private final Block myRootBlock;
|
||||
protected boolean myCanModifyAllWhiteSpaces = false;
|
||||
|
||||
|
||||
public PsiBasedFormattingModel(final PsiFile file,
|
||||
@NotNull final Block rootBlock,
|
||||
final FormattingDocumentModelImpl documentModel) {
|
||||
myASTNode = SourceTreeToPsiMap.psiElementToTree(file);
|
||||
myDocumentModel = documentModel;
|
||||
myRootBlock = rootBlock;
|
||||
|
||||
myProject = file.getProject();
|
||||
}
|
||||
|
||||
|
||||
@@ -81,7 +83,7 @@ public class PsiBasedFormattingModel implements FormattingModelEx {
|
||||
|
||||
|
||||
@Nullable
|
||||
private String replaceWithPSI(final TextRange textRange, String whiteSpace) {
|
||||
private String replaceWithPSI(final TextRange textRange, final String whiteSpace) {
|
||||
final int offset = textRange.getEndOffset();
|
||||
ASTNode leafElement = findElementAt(offset);
|
||||
|
||||
@@ -101,7 +103,14 @@ public class PsiBasedFormattingModel implements FormattingModelEx {
|
||||
return replaceWithPsiInLeaf(textRange, whiteSpace, leafElement);
|
||||
}
|
||||
} else if (textRange.getEndOffset() == myASTNode.getTextLength()){
|
||||
FormatterUtil.replaceLastWhiteSpace(myASTNode, whiteSpace, textRange);
|
||||
|
||||
CodeStyleManager.getInstance(myProject).performActionWithFormatterDisabled(new Runnable() {
|
||||
@Override
|
||||
public void run() {
|
||||
FormatterUtil.replaceLastWhiteSpace(myASTNode, whiteSpace, textRange);
|
||||
}
|
||||
});
|
||||
|
||||
return whiteSpace;
|
||||
} else {
|
||||
return null;
|
||||
@@ -109,12 +118,18 @@ public class PsiBasedFormattingModel implements FormattingModelEx {
|
||||
}
|
||||
|
||||
@Nullable
|
||||
protected String replaceWithPsiInLeaf(final TextRange textRange, String whiteSpace, ASTNode leafElement) {
|
||||
protected String replaceWithPsiInLeaf(final TextRange textRange, final String whiteSpace, final ASTNode leafElement) {
|
||||
if (!myCanModifyAllWhiteSpaces) {
|
||||
if (leafElement.getElementType() == TokenType.WHITE_SPACE) return null;
|
||||
}
|
||||
|
||||
FormatterUtil.replaceWhiteSpace(whiteSpace, leafElement, TokenType.WHITE_SPACE, textRange);
|
||||
CodeStyleManager.getInstance(myProject).performActionWithFormatterDisabled(new Runnable() {
|
||||
@Override
|
||||
public void run() {
|
||||
FormatterUtil.replaceWhiteSpace(whiteSpace, leafElement, TokenType.WHITE_SPACE, textRange);
|
||||
}
|
||||
});
|
||||
|
||||
return whiteSpace;
|
||||
}
|
||||
|
||||
|
||||
+1
-1
@@ -77,7 +77,7 @@ public class DocumentFragmentTooltipRenderer implements TooltipRenderer {
|
||||
FoldingModelEx foldingModel = (FoldingModelEx)editor.getFoldingModel();
|
||||
foldingModel.setFoldingEnabled(false);
|
||||
TextRange textRange = new TextRange(startOffset, endOffset);
|
||||
hint = EditorFragmentComponent.showEditorFragmentHintAt(editor, textRange, p.y, false, false, true);
|
||||
hint = EditorFragmentComponent.showEditorFragmentHintAt(editor, textRange, p.y, false, false, true, true, true);
|
||||
foldingModel.setFoldingEnabled(true);
|
||||
return hint;
|
||||
}
|
||||
|
||||
+3
-16
@@ -150,21 +150,6 @@ public class EditorFragmentComponent extends JPanel {
|
||||
|
||||
/**
|
||||
* @param y <code>y</code> coordinate in layered pane coordinate system.
|
||||
* @param hideByAnyKey
|
||||
*/
|
||||
@Nullable
|
||||
public static LightweightHint showEditorFragmentHintAt(Editor editor,
|
||||
TextRange range,
|
||||
int y,
|
||||
boolean showUpward,
|
||||
boolean showFolding,
|
||||
boolean hideByAnyKey) {
|
||||
return showEditorFragmentHintAt(editor, range, y, showUpward, showFolding, hideByAnyKey, true);
|
||||
}
|
||||
|
||||
/**
|
||||
* @param y <code>y</code> coordinate in layered pane coordinate system.
|
||||
* @param hideByAnyKey
|
||||
*/
|
||||
@Nullable
|
||||
public static LightweightHint showEditorFragmentHintAt(Editor editor,
|
||||
@@ -173,6 +158,7 @@ public class EditorFragmentComponent extends JPanel {
|
||||
boolean showUpward,
|
||||
boolean showFolding,
|
||||
boolean hideByAnyKey,
|
||||
boolean hideByScrolling,
|
||||
boolean useCaretRowBackground) {
|
||||
if (ApplicationManager.getApplication().isUnitTestMode()) return null;
|
||||
Document document = editor.getDocument();
|
||||
@@ -215,6 +201,7 @@ public class EditorFragmentComponent extends JPanel {
|
||||
Point p = new Point(x, y);
|
||||
LightweightHint hint = new MyComponentHint(fragmentComponent);
|
||||
HintManagerImpl.getInstanceImpl().showEditorHint(hint, editor, p, (hideByAnyKey ? HintManager.HIDE_BY_ANY_KEY : 0) |
|
||||
(hideByScrolling ? HintManager.HIDE_BY_SCROLLING : 0) |
|
||||
HintManager.HIDE_BY_TEXT_CHANGE | HintManager.HIDE_BY_MOUSEOVER,
|
||||
0, false, new HintHint(editor, p));
|
||||
return hint;
|
||||
@@ -252,7 +239,7 @@ public class EditorFragmentComponent extends JPanel {
|
||||
if (rootPane == null) return null;
|
||||
JLayeredPane layeredPane = rootPane.getLayeredPane();
|
||||
Point point = SwingUtilities.convertPoint(editorComponent, -2, 0, layeredPane);
|
||||
return showEditorFragmentHintAt(editor, range, point.y, true, showFolding, hideByAnyKey, false);
|
||||
return showEditorFragmentHintAt(editor, range, point.y, true, showFolding, hideByAnyKey, true, false);
|
||||
}
|
||||
|
||||
public static Color getBackgroundColor(Editor editor){
|
||||
|
||||
@@ -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.
|
||||
@@ -15,6 +15,8 @@
|
||||
*/
|
||||
package com.intellij.help.impl;
|
||||
|
||||
import com.intellij.openapi.actionSystem.ActionManager;
|
||||
import com.intellij.openapi.actionSystem.AnAction;
|
||||
import com.intellij.openapi.actionSystem.Shortcut;
|
||||
import com.intellij.openapi.application.ApplicationStarter;
|
||||
import com.intellij.openapi.application.PathManager;
|
||||
@@ -45,15 +47,17 @@ public class KeymapGenerator implements ApplicationStarter {
|
||||
|
||||
@Override
|
||||
public void main(String[] args) {
|
||||
ActionManager actionManager = ActionManager.getInstance();
|
||||
StringBuilder xml = new StringBuilder();
|
||||
xml.append("<Keymaps>\n");
|
||||
|
||||
for (Keymap keymap : KeymapManagerEx.getInstanceEx().getAllKeymaps()) {
|
||||
|
||||
|
||||
xml.append(" <Keymap name=\"").append(keymap.getPresentableName()).append("\">\n");
|
||||
for (String id : keymap.getActionIds()) {
|
||||
String shortcuts = KeymapUtil.getShortcutsText(keymap.getShortcuts(id));
|
||||
if (!StringUtil.isEmpty(shortcuts)) {
|
||||
AnAction action = actionManager.getAction(id);
|
||||
xml.append(" <Action id=\"").append(id).append("\">\n");
|
||||
Set<String> addedShortcuts = new THashSet<String>();
|
||||
for (Shortcut shortcut : keymap.getShortcuts(id)) {
|
||||
@@ -64,6 +68,12 @@ public class KeymapGenerator implements ApplicationStarter {
|
||||
xml.append(" <Shortcut>").append(shortcutText).append("</Shortcut>\n");
|
||||
}
|
||||
}
|
||||
if (action != null) {
|
||||
String text = action.getTemplatePresentation().getText();
|
||||
if (text != null) {
|
||||
xml.append(" <Text>").append(StringUtil.escapeXml(text)).append("</Text>\n");
|
||||
}
|
||||
}
|
||||
xml.append(" </Action>\n");
|
||||
}
|
||||
}
|
||||
|
||||
@@ -410,7 +410,8 @@ public class IdeEventQueue extends EventQueue {
|
||||
//private static boolean altGrIsPressed = false;
|
||||
|
||||
private static AWTEvent fixNonEnglishKeyboardLayouts(AWTEvent e) {
|
||||
if (!KeyboardSettingsExternalizable.getInstance().isNonEnglishKeyboardSupportEnabled()) return e;
|
||||
KeyboardSettingsExternalizable externalizable = KeyboardSettingsExternalizable.getInstance();
|
||||
if (externalizable == null || !externalizable.isNonEnglishKeyboardSupportEnabled()) return e;
|
||||
|
||||
if (e instanceof KeyEvent) {
|
||||
KeyEvent ke = (KeyEvent)e;
|
||||
|
||||
+2
-1
@@ -26,13 +26,14 @@ import com.intellij.openapi.util.registry.Registry;
|
||||
import com.intellij.ui.KeyStrokeAdapter;
|
||||
|
||||
import javax.swing.*;
|
||||
import java.awt.*;
|
||||
import java.awt.event.KeyEvent;
|
||||
|
||||
public class ShortcutTextField extends JTextField {
|
||||
private KeyStroke myKeyStroke;
|
||||
|
||||
public ShortcutTextField() {
|
||||
enableEvents(KeyEvent.KEY_EVENT_MASK);
|
||||
enableEvents(AWTEvent.KEY_EVENT_MASK);
|
||||
setFocusTraversalKeysEnabled(false);
|
||||
}
|
||||
|
||||
|
||||
@@ -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.
|
||||
@@ -108,4 +108,10 @@ public class Patches {
|
||||
* fixed in JDK8
|
||||
*/
|
||||
public static final boolean JDK_BUG_ID_7103570 = true;
|
||||
|
||||
/**
|
||||
* Support default methods in JDI
|
||||
* See <a href="https://bugs.openjdk.java.net/browse/JDK-8042123">JDK-8042123</a>
|
||||
*/
|
||||
public static final boolean JDK_BUG_ID_8042123 = !SystemInfo.isJavaVersionAtLeast("1.8.0_40");
|
||||
}
|
||||
|
||||
@@ -23,12 +23,13 @@ import org.jetbrains.annotations.Nullable;
|
||||
import org.jetbrains.annotations.TestOnly;
|
||||
|
||||
public class UserDataHolderBase implements UserDataHolderEx, Cloneable {
|
||||
public static final Key<KeyFMap> COPYABLE_USER_MAP_KEY = Key.create("COPYABLE_USER_MAP_KEY");
|
||||
private static final Key<KeyFMap> COPYABLE_USER_MAP_KEY = Key.create("COPYABLE_USER_MAP_KEY");
|
||||
|
||||
/**
|
||||
* Concurrent writes to this field are via CASes only, using the {@link #updater}
|
||||
*/
|
||||
@NotNull private volatile KeyFMap myUserMap = KeyFMap.EMPTY_MAP;
|
||||
@NotNull
|
||||
private volatile KeyFMap myUserMap = KeyFMap.EMPTY_MAP;
|
||||
|
||||
@Override
|
||||
protected Object clone() {
|
||||
@@ -47,10 +48,10 @@ public class UserDataHolderBase implements UserDataHolderEx, Cloneable {
|
||||
public String getUserDataString() {
|
||||
final KeyFMap userMap = getUserMap();
|
||||
final KeyFMap copyableMap = getUserData(COPYABLE_USER_MAP_KEY);
|
||||
return userMap.toString() + (copyableMap == null ? "" : copyableMap.toString());
|
||||
return userMap + (copyableMap == null ? "" : copyableMap.toString());
|
||||
}
|
||||
|
||||
public void copyUserDataTo(UserDataHolderBase other) {
|
||||
public void copyUserDataTo(@NotNull UserDataHolderBase other) {
|
||||
other.setUserMap(getUserMap());
|
||||
}
|
||||
|
||||
|
||||
@@ -2086,6 +2086,15 @@ public class StringUtil extends StringUtilRt {
|
||||
return replace(text, REPLACES_DISP, REPLACES_REFS);
|
||||
}
|
||||
|
||||
@NonNls private static final String[] MN_QUOTED = {"&&", "__"};
|
||||
@NonNls private static final String[] MN_CHARS = {"&", "_"};
|
||||
|
||||
@Contract(value = "null -> null; !null -> !null", pure = true)
|
||||
public static String escapeMnemonics(@Nullable String text) {
|
||||
if (text == null) return null;
|
||||
return replace(text, MN_CHARS, MN_QUOTED);
|
||||
}
|
||||
|
||||
@NotNull
|
||||
@Contract(pure = true)
|
||||
public static String htmlEmphasize(@NotNull String text) {
|
||||
|
||||
@@ -414,6 +414,7 @@ public class ArrayUtil extends ArrayUtilRt {
|
||||
return result;
|
||||
}
|
||||
|
||||
@NotNull
|
||||
@Contract(pure=true)
|
||||
public static <T> T[] append(@NotNull final T[] src, final T element, @NotNull ArrayFactory<T> factory) {
|
||||
int length = src.length;
|
||||
|
||||
@@ -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.
|
||||
@@ -47,6 +47,11 @@ public class MultiMap<K, V> implements Serializable {
|
||||
putAllValues(toCopy);
|
||||
}
|
||||
|
||||
@NotNull
|
||||
public MultiMap<K, V> copy() {
|
||||
return new MultiMap<K, V>(this);
|
||||
}
|
||||
|
||||
public MultiMap(int i, float v) {
|
||||
myMap = createMap(i, v);
|
||||
}
|
||||
|
||||
@@ -22,6 +22,7 @@ import com.intellij.openapi.actionSystem.CommonDataKeys;
|
||||
import com.intellij.openapi.application.ApplicationManager;
|
||||
import com.intellij.openapi.project.DumbAware;
|
||||
import com.intellij.openapi.project.Project;
|
||||
import com.intellij.openapi.util.text.StringUtil;
|
||||
import com.intellij.openapi.vcs.changes.VcsDirtyScopeManager;
|
||||
import com.intellij.openapi.vfs.VirtualFile;
|
||||
import com.intellij.openapi.vfs.newvfs.NewVirtualFile;
|
||||
@@ -42,7 +43,7 @@ public class SynchronizeCurrentFileAction extends AnAction implements DumbAware
|
||||
|
||||
String message = getMessage(files);
|
||||
e.getPresentation().setEnabledAndVisible(true);
|
||||
e.getPresentation().setText(message.replace("_", "__").replace("&", "&&"));
|
||||
e.getPresentation().setText(StringUtil.escapeMnemonics(message));
|
||||
}
|
||||
|
||||
private static String getMessage(VirtualFile[] files) {
|
||||
|
||||
@@ -23,10 +23,10 @@ import org.jetbrains.annotations.Nullable;
|
||||
import java.util.List;
|
||||
|
||||
/**
|
||||
* Collects incoming requests into a list, and provides them to an underlying background task via {@link #popRequests()}. <br/>
|
||||
* Collects incoming requests into a list, and provides them to the underlying background task via {@link #popRequests()}. <br/>
|
||||
* Such task is started immediately after the first request arrives, if no other task is currently running. <br/>
|
||||
* A task indicates its completion by calling {@link #taskCompleted(Object)} and providing a result which is immediately passed to the
|
||||
* result handler.
|
||||
* A task reports its completion by calling {@link #taskCompleted(Object)} and providing a result which is immediately passed to the
|
||||
* result handler (unless it is null in which case the task is stopped but the result is not passed to the handler).
|
||||
* <p/>
|
||||
* The purpose of this class is to provide a single thread, which processes incoming requests in the background and continues to process
|
||||
* new ones if they arrive while the previous ones were processed. An alternative would be a long living thread which always checks some
|
||||
|
||||
@@ -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.
|
||||
@@ -73,6 +73,7 @@ public class XVariablesView extends XVariablesViewBase {
|
||||
tree.getProject().putUserData(DEBUG_VARIABLES, null);
|
||||
tree.getProject().putUserData(DEBUG_VARIABLES_TIMESTAMPS, null);
|
||||
tree.setSourcePosition(null);
|
||||
tree.updateEditor();
|
||||
|
||||
XDebuggerTreeNode node;
|
||||
XDebugSession session = getSession(getPanel());
|
||||
|
||||
+10
-10
@@ -82,20 +82,24 @@ public abstract class GradleImportingTestCase extends ExternalSystemImportingTes
|
||||
@org.junit.runners.Parameterized.Parameter(0)
|
||||
public String gradleVersion;
|
||||
private GradleProjectSettings myProjectSettings;
|
||||
private String myJdkHome;
|
||||
|
||||
@Override
|
||||
public void setUp() throws Exception {
|
||||
myJdkHome = IdeaTestUtil.requireRealJdkHome();
|
||||
super.setUp();
|
||||
assumeThat(gradleVersion, versionMatcherRule.getMatcher());
|
||||
final String jdkHome = IdeaTestUtil.requireRealJdkHome();
|
||||
assertNull("JDK " + GRADLE_JDK_NAME + " already exists", ProjectJdkTable.getInstance().findJdk(GRADLE_JDK_NAME));
|
||||
new WriteAction() {
|
||||
@Override
|
||||
protected void run(@NotNull Result result) throws Throwable {
|
||||
VirtualFile jdkHomeDir = LocalFileSystem.getInstance().refreshAndFindFileByIoFile(new File(jdkHome));
|
||||
Sdk oldJdk = ProjectJdkTable.getInstance().findJdk(GRADLE_JDK_NAME);
|
||||
if (oldJdk != null) {
|
||||
ProjectJdkTable.getInstance().removeJdk(oldJdk);
|
||||
}
|
||||
VirtualFile jdkHomeDir = LocalFileSystem.getInstance().refreshAndFindFileByIoFile(new File(myJdkHome));
|
||||
Sdk jdk = SdkConfigurationUtil.setupSdk(new Sdk[0], jdkHomeDir, JavaSdk.getInstance(), true, null, GRADLE_JDK_NAME);
|
||||
assertNotNull("Cannot create JDK for " + jdkHome, jdk);
|
||||
SdkConfigurationUtil.addSdk(jdk);
|
||||
assertNotNull("Cannot create JDK for " + myJdkHome, jdk);
|
||||
ProjectJdkTable.getInstance().addJdk(jdk);
|
||||
}
|
||||
}.execute();
|
||||
myProjectSettings = new GradleProjectSettings();
|
||||
@@ -126,11 +130,7 @@ public abstract class GradleImportingTestCase extends ExternalSystemImportingTes
|
||||
|
||||
@Override
|
||||
protected void collectAllowedRoots(List<String> roots) throws IOException {
|
||||
final String javaHome = System.getenv("JAVA_HOME");
|
||||
if (javaHome != null) {
|
||||
roots.add(javaHome);
|
||||
}
|
||||
|
||||
roots.add(myJdkHome);
|
||||
roots.add(PathManager.getOptionsPath());
|
||||
}
|
||||
|
||||
|
||||
@@ -21,6 +21,7 @@ import com.intellij.openapi.editor.Document;
|
||||
import com.intellij.openapi.util.Key;
|
||||
import com.intellij.openapi.util.TextRange;
|
||||
import com.intellij.psi.*;
|
||||
import com.intellij.psi.codeStyle.CodeStyleSettingsManager;
|
||||
import com.intellij.psi.impl.source.tree.TreeUtil;
|
||||
import com.intellij.psi.tree.IElementType;
|
||||
import com.intellij.psi.tree.TokenSet;
|
||||
@@ -38,6 +39,9 @@ import java.util.Collection;
|
||||
import java.util.Collections;
|
||||
import java.util.List;
|
||||
|
||||
import static com.jetbrains.python.formatter.PyCodeStyleSettings.DICT_ALIGNMENT_ON_COLON;
|
||||
import static com.jetbrains.python.formatter.PyCodeStyleSettings.DICT_ALIGNMENT_ON_VALUE;
|
||||
|
||||
/**
|
||||
* @author yole
|
||||
*/
|
||||
@@ -83,6 +87,7 @@ public class PyBlock implements ASTBlock {
|
||||
private final PyBlockContext myContext;
|
||||
private List<PyBlock> mySubBlocks = null;
|
||||
private Alignment myChildAlignment;
|
||||
private final Alignment myDictAlignment;
|
||||
private final boolean myEmptySequence;
|
||||
|
||||
public PyBlock(final PyBlock parent,
|
||||
@@ -98,6 +103,8 @@ public class PyBlock implements ASTBlock {
|
||||
myWrap = wrap;
|
||||
myContext = context;
|
||||
myEmptySequence = isEmptySequence(node);
|
||||
|
||||
myDictAlignment = node.getElementType() == PyElementTypes.DICT_LITERAL_EXPRESSION ? Alignment.createAlignment(true) : null;
|
||||
}
|
||||
|
||||
@NotNull
|
||||
@@ -147,7 +154,10 @@ public class PyBlock implements ASTBlock {
|
||||
|
||||
private PyBlock buildSubBlock(ASTNode child) {
|
||||
final IElementType parentType = myNode.getElementType();
|
||||
final IElementType grandparentType = myNode.getTreeParent() == null ? null : myNode.getTreeParent().getElementType();
|
||||
|
||||
final ASTNode grandParentNode = myNode.getTreeParent();
|
||||
final IElementType grandparentType = grandParentNode == null ? null : grandParentNode.getElementType();
|
||||
|
||||
final IElementType childType = child.getElementType();
|
||||
Wrap wrap = null;
|
||||
Indent childIndent = Indent.getNoneIndent();
|
||||
@@ -216,6 +226,7 @@ public class PyBlock implements ASTBlock {
|
||||
}
|
||||
}
|
||||
|
||||
PyCodeStyleSettings settings = CodeStyleSettingsManager.getSettings(child.getPsi().getProject()).getCustomSettings(PyCodeStyleSettings.class);
|
||||
if (parentType == PyElementTypes.LIST_LITERAL_EXPRESSION || parentType == PyElementTypes.LIST_COMP_EXPRESSION) {
|
||||
if (childType == PyTokenTypes.RBRACKET || childType == PyTokenTypes.LBRACKET) {
|
||||
childIndent = Indent.getNoneIndent();
|
||||
@@ -241,7 +252,7 @@ public class PyBlock implements ASTBlock {
|
||||
else if (parentType == PyElementTypes.FROM_IMPORT_STATEMENT) {
|
||||
if (myNode.findChildByType(PyTokenTypes.LPAR) != null) {
|
||||
if (childType == PyElementTypes.IMPORT_ELEMENT) {
|
||||
if (myContext.getPySettings().ALIGN_MULTILINE_IMPORTS) {
|
||||
if (settings.ALIGN_MULTILINE_IMPORTS) {
|
||||
childAlignment = getAlignmentForChildren();
|
||||
}
|
||||
else {
|
||||
@@ -330,12 +341,27 @@ public class PyBlock implements ASTBlock {
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
if (isAfterStatementList(child) && !hasLineBreaksBefore(child, 2) && child.getElementType() != PyTokenTypes.END_OF_LINE_COMMENT) {
|
||||
// maybe enter was pressed and cut us from a previous (nested) statement list
|
||||
childIndent = Indent.getNormalIndent();
|
||||
}
|
||||
|
||||
if (settings.DICT_ALIGNMENT == DICT_ALIGNMENT_ON_VALUE) {
|
||||
if (isDictLiteralPropertyValue(child) && !ourListElementTypes.contains(childType)) {
|
||||
childAlignment = myParent.myDictAlignment;
|
||||
}
|
||||
else if (isDictLiteralPropertyValue(myNode) &&
|
||||
ourListElementTypes.contains(parentType) &&
|
||||
PyTokenTypes.OPEN_BRACES.contains(childType)) {
|
||||
childAlignment = myParent.myParent.myDictAlignment;
|
||||
}
|
||||
}
|
||||
else if (myContext.getPySettings().DICT_ALIGNMENT == DICT_ALIGNMENT_ON_COLON) {
|
||||
if (isInsideDictLiteralKeyValue(child) && childType == PyTokenTypes.COLON) {
|
||||
childAlignment = myParent.myDictAlignment;
|
||||
}
|
||||
}
|
||||
|
||||
ASTNode prev = child.getTreePrev();
|
||||
while (prev != null && prev.getElementType() == TokenType.WHITE_SPACE) {
|
||||
if (prev.textContains('\\') &&
|
||||
@@ -350,6 +376,23 @@ public class PyBlock implements ASTBlock {
|
||||
return new PyBlock(this, child, childAlignment, childIndent, wrap, myContext);
|
||||
}
|
||||
|
||||
private static boolean isDictLiteralPropertyValue(@NotNull ASTNode node) {
|
||||
return isInsideDictLiteralKeyValue(node) && node.getTreeParent().getPsi(PyKeyValueExpression.class).getValue() == node.getPsi();
|
||||
}
|
||||
|
||||
private static boolean isInsideDictLiteralKeyValue(@NotNull ASTNode node) {
|
||||
final ASTNode nodeParent = node.getTreeParent();
|
||||
if (nodeParent == null) {
|
||||
return false;
|
||||
}
|
||||
final ASTNode nodeGrandParent = nodeParent.getTreeParent();
|
||||
if (nodeGrandParent == null) {
|
||||
return false;
|
||||
}
|
||||
return nodeParent.getElementType() == PyElementTypes.KEY_VALUE_EXPRESSION &&
|
||||
nodeGrandParent.getElementType() == PyElementTypes.DICT_LITERAL_EXPRESSION;
|
||||
}
|
||||
|
||||
private static boolean isEmptySequence(@NotNull ASTNode node) {
|
||||
return node.getPsi() instanceof PySequenceExpression && ((PySequenceExpression)node.getPsi()).isEmpty();
|
||||
}
|
||||
|
||||
@@ -27,4 +27,9 @@ public class PyCodeStyleMainPanel extends TabbedLanguageCodeStylePanel {
|
||||
super(PythonLanguage.getInstance(), currentSettings, settings);
|
||||
}
|
||||
|
||||
@Override
|
||||
protected void initTabs(CodeStyleSettings settings) {
|
||||
super.initTabs(settings);
|
||||
addTab(new PyCodeStylePanel(settings));
|
||||
}
|
||||
}
|
||||
|
||||
@@ -1,12 +1,70 @@
|
||||
<?xml version="1.0" encoding="UTF-8"?>
|
||||
<form xmlns="http://www.intellij.com/uidesigner/form/" version="1" bind-to-class="com.jetbrains.python.formatter.PyCodeStylePanel">
|
||||
<grid id="27dc6" binding="myPanel" layout-manager="GridLayoutManager" row-count="1" column-count="1" same-size-horizontally="false" same-size-vertically="false" hgap="-1" vgap="-1">
|
||||
<grid id="27dc6" binding="myPanel" layout-manager="GridLayoutManager" row-count="5" column-count="2" same-size-horizontally="false" same-size-vertically="false" hgap="-1" vgap="-1">
|
||||
<margin top="0" left="0" bottom="0" right="0"/>
|
||||
<constraints>
|
||||
<xy x="20" y="20" width="500" height="400"/>
|
||||
</constraints>
|
||||
<properties/>
|
||||
<border type="none"/>
|
||||
<children/>
|
||||
<children>
|
||||
<grid id="e59db" binding="myPreviewPanel" layout-manager="GridLayoutManager" row-count="1" column-count="1" same-size-horizontally="false" same-size-vertically="false" hgap="-1" vgap="-1">
|
||||
<margin top="0" left="0" bottom="0" right="0"/>
|
||||
<constraints>
|
||||
<grid row="0" column="1" row-span="4" col-span="1" vsize-policy="3" hsize-policy="3" anchor="0" fill="3" indent="0" use-parent-layout="false"/>
|
||||
</constraints>
|
||||
<properties/>
|
||||
<border type="none"/>
|
||||
<children>
|
||||
<vspacer id="8bd9e">
|
||||
<constraints>
|
||||
<grid row="0" column="0" row-span="1" col-span="1" vsize-policy="6" hsize-policy="1" anchor="0" fill="2" indent="0" use-parent-layout="false"/>
|
||||
</constraints>
|
||||
</vspacer>
|
||||
</children>
|
||||
</grid>
|
||||
<grid id="d3271" layout-manager="GridLayoutManager" row-count="2" column-count="2" same-size-horizontally="false" same-size-vertically="false" hgap="-1" vgap="-1">
|
||||
<margin top="10" left="10" bottom="10" right="10"/>
|
||||
<constraints>
|
||||
<grid row="0" column="0" row-span="1" col-span="1" vsize-policy="3" hsize-policy="3" anchor="0" fill="3" indent="0" use-parent-layout="false"/>
|
||||
</constraints>
|
||||
<properties/>
|
||||
<border type="none"/>
|
||||
<children>
|
||||
<component id="ca8eb" class="com.intellij.openapi.ui.ComboBox" binding="myDictAlignmentCombo">
|
||||
<constraints>
|
||||
<grid row="0" column="1" row-span="1" col-span="1" vsize-policy="0" hsize-policy="2" anchor="0" fill="0" indent="0" use-parent-layout="false"/>
|
||||
</constraints>
|
||||
<properties/>
|
||||
</component>
|
||||
<component id="767d3" class="com.intellij.ui.components.JBLabel">
|
||||
<constraints>
|
||||
<grid row="0" column="0" row-span="1" col-span="1" vsize-policy="0" hsize-policy="0" anchor="0" fill="0" indent="0" use-parent-layout="false"/>
|
||||
</constraints>
|
||||
<properties>
|
||||
<text value="Dict alignment:"/>
|
||||
</properties>
|
||||
</component>
|
||||
<component id="b4945" class="com.intellij.ui.components.JBCheckBox" binding="myAddTrailingBlankLineCheckbox" default-binding="true">
|
||||
<constraints>
|
||||
<grid row="1" column="0" row-span="1" col-span="2" vsize-policy="0" hsize-policy="0" anchor="0" fill="0" indent="0" use-parent-layout="false"/>
|
||||
</constraints>
|
||||
<properties>
|
||||
<text value="Add line feed at the end of file"/>
|
||||
</properties>
|
||||
</component>
|
||||
</children>
|
||||
</grid>
|
||||
<vspacer id="4e0f0">
|
||||
<constraints>
|
||||
<grid row="1" column="0" row-span="3" col-span="1" vsize-policy="6" hsize-policy="1" anchor="0" fill="2" indent="0" use-parent-layout="false"/>
|
||||
</constraints>
|
||||
</vspacer>
|
||||
<hspacer id="f52d">
|
||||
<constraints>
|
||||
<grid row="4" column="1" row-span="1" col-span="1" vsize-policy="1" hsize-policy="6" anchor="0" fill="1" indent="0" use-parent-layout="false"/>
|
||||
</constraints>
|
||||
</hspacer>
|
||||
</children>
|
||||
</grid>
|
||||
</form>
|
||||
|
||||
@@ -20,23 +20,57 @@ import com.intellij.ide.highlighter.HighlighterFactory;
|
||||
import com.intellij.openapi.editor.colors.EditorColorsScheme;
|
||||
import com.intellij.openapi.editor.highlighter.EditorHighlighter;
|
||||
import com.intellij.openapi.fileTypes.FileType;
|
||||
import com.intellij.psi.PsiFile;
|
||||
import com.intellij.openapi.ui.ComboBox;
|
||||
import com.intellij.psi.codeStyle.CodeStyleSettings;
|
||||
import com.jetbrains.python.highlighting.PyHighlighter;
|
||||
import com.intellij.ui.components.JBCheckBox;
|
||||
import com.jetbrains.python.PythonFileType;
|
||||
import com.jetbrains.python.PythonLanguage;
|
||||
import com.jetbrains.python.formatter.PyCodeStyleSettings.DictAlignment;
|
||||
import com.jetbrains.python.highlighting.PyHighlighter;
|
||||
import com.jetbrains.python.psi.LanguageLevel;
|
||||
import org.jetbrains.annotations.NotNull;
|
||||
|
||||
import javax.swing.*;
|
||||
import java.awt.event.ActionEvent;
|
||||
import java.awt.event.ActionListener;
|
||||
import java.awt.event.ItemEvent;
|
||||
import java.awt.event.ItemListener;
|
||||
|
||||
/**
|
||||
* @author yole
|
||||
*/
|
||||
public class PyCodeStylePanel extends CodeStyleAbstractPanel {
|
||||
|
||||
private JPanel myPanel;
|
||||
private JBCheckBox myAddTrailingBlankLineCheckbox;
|
||||
private ComboBox myDictAlignmentCombo;
|
||||
private JPanel myPreviewPanel;
|
||||
|
||||
protected PyCodeStylePanel(CodeStyleSettings settings) {
|
||||
super(settings);
|
||||
super(PythonLanguage.getInstance(), null, settings);
|
||||
addPanelToWatch(myPanel);
|
||||
installPreviewPanel(myPreviewPanel);
|
||||
|
||||
for (DictAlignment alignment : DictAlignment.values()) {
|
||||
//noinspection unchecked
|
||||
myDictAlignmentCombo.addItem(alignment);
|
||||
}
|
||||
|
||||
myDictAlignmentCombo.addItemListener(new ItemListener() {
|
||||
@Override
|
||||
public void itemStateChanged(ItemEvent e) {
|
||||
if (e.getStateChange() == ItemEvent.SELECTED) {
|
||||
somethingChanged();
|
||||
}
|
||||
}
|
||||
});
|
||||
|
||||
myAddTrailingBlankLineCheckbox.addActionListener(new ActionListener() {
|
||||
@Override
|
||||
public void actionPerformed(ActionEvent e) {
|
||||
somethingChanged();
|
||||
}
|
||||
});
|
||||
}
|
||||
|
||||
@Override
|
||||
@@ -49,10 +83,6 @@ public class PyCodeStylePanel extends CodeStyleAbstractPanel {
|
||||
return 80;
|
||||
}
|
||||
|
||||
@Override
|
||||
protected void prepareForReformat(PsiFile psiFile) {
|
||||
}
|
||||
|
||||
@NotNull
|
||||
@Override
|
||||
protected FileType getFileType() {
|
||||
@@ -61,24 +91,54 @@ public class PyCodeStylePanel extends CodeStyleAbstractPanel {
|
||||
|
||||
@Override
|
||||
protected String getPreviewText() {
|
||||
return "";
|
||||
return PREVIEW;
|
||||
}
|
||||
|
||||
@Override
|
||||
protected void resetImpl(CodeStyleSettings settings) {
|
||||
for (DictAlignment alignment : DictAlignment.values()) {
|
||||
if (getCustomSettings(settings).DICT_ALIGNMENT == alignment.asInt()) {
|
||||
myDictAlignmentCombo.setSelectedItem(alignment);
|
||||
break;
|
||||
}
|
||||
}
|
||||
myAddTrailingBlankLineCheckbox.setSelected(getCustomSettings(settings).BLANK_LINE_AT_FILE_END);
|
||||
}
|
||||
|
||||
@Override
|
||||
public void apply(CodeStyleSettings settings) {
|
||||
final PyCodeStyleSettings customSettings = getCustomSettings(settings);
|
||||
customSettings.DICT_ALIGNMENT = getDictAlignmentAsInt();
|
||||
customSettings.BLANK_LINE_AT_FILE_END = ensureTrailingBlankLine();
|
||||
}
|
||||
|
||||
@Override
|
||||
public boolean isModified(CodeStyleSettings settings) {
|
||||
return false;
|
||||
final PyCodeStyleSettings customSettings = getCustomSettings(settings);
|
||||
return customSettings.DICT_ALIGNMENT != getDictAlignmentAsInt() ||
|
||||
customSettings.BLANK_LINE_AT_FILE_END != ensureTrailingBlankLine();
|
||||
}
|
||||
|
||||
@Override
|
||||
public JComponent getPanel() {
|
||||
return myPanel;
|
||||
}
|
||||
|
||||
@NotNull
|
||||
private static PyCodeStyleSettings getCustomSettings(@NotNull CodeStyleSettings settings) {
|
||||
return settings.getCustomSettings(PyCodeStyleSettings.class);
|
||||
}
|
||||
|
||||
private int getDictAlignmentAsInt() {
|
||||
return ((DictAlignment)myDictAlignmentCombo.getSelectedItem()).asInt();
|
||||
}
|
||||
|
||||
private boolean ensureTrailingBlankLine() {
|
||||
return myAddTrailingBlankLineCheckbox.isSelected();
|
||||
}
|
||||
|
||||
public static final String PREVIEW = "{\n" +
|
||||
" \"green\": 42,\n" +
|
||||
" \"eggs and ham\": -0.0e0\n" +
|
||||
"}";
|
||||
}
|
||||
|
||||
@@ -22,6 +22,33 @@ import com.intellij.psi.codeStyle.CustomCodeStyleSettings;
|
||||
* @author yole
|
||||
*/
|
||||
public class PyCodeStyleSettings extends CustomCodeStyleSettings {
|
||||
|
||||
public enum DictAlignment {
|
||||
NONE("Do not align"),
|
||||
ON_VALUE("Align on value"),
|
||||
ON_COLON("Align on colon");
|
||||
|
||||
String description;
|
||||
|
||||
DictAlignment(String description) {
|
||||
this.description = description;
|
||||
}
|
||||
|
||||
public int asInt() {
|
||||
return ordinal();
|
||||
}
|
||||
|
||||
@Override
|
||||
public String toString() {
|
||||
return description;
|
||||
}
|
||||
}
|
||||
|
||||
// Unfortunately, the old serializer for code style settings can't handle enums
|
||||
public static final int DICT_ALIGNMENT_NONE = DictAlignment.NONE.asInt();
|
||||
public static final int DICT_ALIGNMENT_ON_VALUE = DictAlignment.ON_VALUE.asInt();
|
||||
public static final int DICT_ALIGNMENT_ON_COLON = DictAlignment.ON_COLON.asInt();
|
||||
|
||||
public boolean SPACE_WITHIN_BRACES = false;
|
||||
public boolean SPACE_BEFORE_PY_COLON = false;
|
||||
public boolean SPACE_AFTER_PY_COLON = true;
|
||||
@@ -32,7 +59,7 @@ public class PyCodeStyleSettings extends CustomCodeStyleSettings {
|
||||
|
||||
public int BLANK_LINES_AROUND_TOP_LEVEL_CLASSES_FUNCTIONS = 2;
|
||||
// TODO make boolean (it needs special editor in BlankLinesPanel)
|
||||
public int BLANKS_LINES_AT_FILE_END = 1;
|
||||
public boolean BLANK_LINE_AT_FILE_END = true;
|
||||
|
||||
public boolean ALIGN_COLLECTIONS_AND_COMPREHENSIONS = true;
|
||||
public boolean ALIGN_MULTILINE_IMPORTS = true;
|
||||
@@ -43,6 +70,8 @@ public class PyCodeStyleSettings extends CustomCodeStyleSettings {
|
||||
public boolean SPACE_AFTER_NUMBER_SIGN = true;
|
||||
public boolean SPACE_BEFORE_NUMBER_SIGN = true;
|
||||
|
||||
public int DICT_ALIGNMENT = DICT_ALIGNMENT_NONE;
|
||||
|
||||
public PyCodeStyleSettings(CodeStyleSettings container) {
|
||||
super("Python", container);
|
||||
}
|
||||
|
||||
@@ -88,7 +88,6 @@ public class PyLanguageCodeStyleSettingsProvider extends LanguageCodeStyleSettin
|
||||
consumer.showCustomOption(PyCodeStyleSettings.class, "BLANK_LINES_AROUND_TOP_LEVEL_CLASSES_FUNCTIONS",
|
||||
"Around top-level classes and functions:",
|
||||
BLANK_LINES);
|
||||
consumer.showCustomOption(PyCodeStyleSettings.class, "BLANKS_LINES_AT_FILE_END", "Blank lines at the end of file", BLANK_LINES);
|
||||
}
|
||||
else if (settingsType == SettingsType.WRAPPING_AND_BRACES_SETTINGS) {
|
||||
consumer.showStandardOptions("RIGHT_MARGIN",
|
||||
|
||||
+17
-10
@@ -20,7 +20,6 @@ import com.intellij.openapi.editor.Document;
|
||||
import com.intellij.openapi.editor.ex.EditorSettingsExternalizable;
|
||||
import com.intellij.openapi.project.Project;
|
||||
import com.intellij.openapi.util.TextRange;
|
||||
import com.intellij.openapi.util.text.StringUtil;
|
||||
import com.intellij.psi.PsiDocumentManager;
|
||||
import com.intellij.psi.PsiElement;
|
||||
import com.intellij.psi.PsiFile;
|
||||
@@ -34,11 +33,11 @@ import org.jetbrains.annotations.NotNull;
|
||||
* Handles extra blank lines at the end of the file if corresponding whitespace elements belong to formatted range/element.
|
||||
* These trailing whitespaces are replaced by line feeds if either:
|
||||
* <ul>
|
||||
* <li>Option {@link PyCodeStyleSettings#BLANKS_LINES_AT_FILE_END} has positive value. In this case that number of line feeds will be
|
||||
* inserted at the end of file.</li>
|
||||
* <li>Option {@link PyCodeStyleSettings#BLANK_LINE_AT_FILE_END} is enabled.</li>
|
||||
* <li>Setting {@link EditorSettingsExternalizable#isEnsureNewLineAtEOF()} is enabled. Otherwise extra new line added on the next
|
||||
* "Save" action will be removed after reformatting.</li>
|
||||
* </ul>
|
||||
* <em>and</em> file is not empty.
|
||||
* If none of these conditions holds, blank lines are removed completely.
|
||||
*
|
||||
* @author Mikhail Golubev
|
||||
@@ -56,6 +55,7 @@ public class PyTrailingBlankLinesPostFormatProcessor implements PostFormatProces
|
||||
public PsiElement processElement(@NotNull PsiElement source, @NotNull CodeStyleSettings settings) {
|
||||
final PsiFile psiFile = source.getContainingFile();
|
||||
if (isApplicableTo(psiFile)) {
|
||||
applyPendingChangesToPsi(source);
|
||||
final TextRange whitespaceRange = findTrailingWhitespacesRange(psiFile);
|
||||
if (source.getTextRange().intersects(whitespaceRange)) {
|
||||
replaceOrDeleteTrailingWhitespaces(psiFile, whitespaceRange);
|
||||
@@ -69,6 +69,7 @@ public class PyTrailingBlankLinesPostFormatProcessor implements PostFormatProces
|
||||
if (!isApplicableTo(source)) {
|
||||
return rangeToReformat;
|
||||
}
|
||||
applyPendingChangesToPsi(source);
|
||||
final TextRange oldWhitespaceRange = findTrailingWhitespacesRange(source);
|
||||
if (rangeToReformat.intersects(oldWhitespaceRange)) {
|
||||
final TextRange newWhitespaceRange = replaceOrDeleteTrailingWhitespaces(source, oldWhitespaceRange);
|
||||
@@ -92,6 +93,14 @@ public class PyTrailingBlankLinesPostFormatProcessor implements PostFormatProces
|
||||
return rangeToReformat;
|
||||
}
|
||||
|
||||
private static void applyPendingChangesToPsi(@NotNull PsiElement source) {
|
||||
final PsiDocumentManager documentManager = PsiDocumentManager.getInstance(source.getContainingFile().getProject());
|
||||
final Document document = documentManager.getDocument(source.getContainingFile());
|
||||
if (document != null) {
|
||||
documentManager.doPostponedOperationsAndUnblockDocument(document);
|
||||
}
|
||||
}
|
||||
|
||||
@NotNull
|
||||
private static TextRange findTrailingWhitespacesRange(@NotNull PsiFile file) {
|
||||
final CharSequence contents = file.getViewProvider().getContents();
|
||||
@@ -113,14 +122,12 @@ public class PyTrailingBlankLinesPostFormatProcessor implements PostFormatProces
|
||||
final PsiDocumentManager documentManager = PsiDocumentManager.getInstance(project);
|
||||
final Document document = documentManager.getDocument(pyFile);
|
||||
if (document != null) {
|
||||
int numLineFeeds = CodeStyleSettingsManager.getSettings(project).getCustomSettings(PyCodeStyleSettings.class).BLANKS_LINES_AT_FILE_END;
|
||||
if (numLineFeeds <= 0 && EditorSettingsExternalizable.getInstance().isEnsureNewLineAtEOF()) {
|
||||
numLineFeeds = 1;
|
||||
}
|
||||
documentManager.doPostponedOperationsAndUnblockDocument(document);
|
||||
final PyCodeStyleSettings customSettings = CodeStyleSettingsManager.getSettings(project).getCustomSettings(PyCodeStyleSettings.class);
|
||||
final boolean addLineFeed = customSettings.BLANK_LINE_AT_FILE_END || EditorSettingsExternalizable.getInstance().isEnsureNewLineAtEOF();
|
||||
try {
|
||||
final String text = StringUtil.repeat("\n", numLineFeeds);
|
||||
if (numLineFeeds > 0 && whitespaceRange.getStartOffset() != 0) {
|
||||
final String text = addLineFeed ? "\n" : "";
|
||||
// Do not add extra blank line in empty file
|
||||
if (!text.isEmpty() && whitespaceRange.getStartOffset() != 0) {
|
||||
if (!whitespaceRange.isEmpty()) {
|
||||
document.replaceString(whitespaceRange.getStartOffset(), whitespaceRange.getEndOffset(), text);
|
||||
}
|
||||
|
||||
@@ -0,0 +1,7 @@
|
||||
{
|
||||
"a": 1,
|
||||
"bbb": [
|
||||
2
|
||||
],
|
||||
"bbbbb": 3
|
||||
}
|
||||
@@ -0,0 +1,7 @@
|
||||
{
|
||||
"a" : 1,
|
||||
"bbb" : [
|
||||
2
|
||||
],
|
||||
"bbbbb": 3
|
||||
}
|
||||
@@ -0,0 +1,7 @@
|
||||
{
|
||||
"a": 1,
|
||||
"bbb": [
|
||||
2
|
||||
],
|
||||
"bbbbb": 3
|
||||
}
|
||||
@@ -0,0 +1,7 @@
|
||||
{
|
||||
"a": 1,
|
||||
"bbb": [
|
||||
2
|
||||
],
|
||||
"bbbbb": 3
|
||||
}
|
||||
@@ -0,0 +1,4 @@
|
||||
{
|
||||
"aaaaa": 1,
|
||||
"bbb aaaaaaa": 2
|
||||
}
|
||||
@@ -0,0 +1,4 @@
|
||||
{
|
||||
"aaaaa" : 1,
|
||||
"bbb aaaaaaa": 2
|
||||
}
|
||||
@@ -567,6 +567,18 @@ public class PyFormatterTest extends PyTestCase {
|
||||
doTest();
|
||||
}
|
||||
|
||||
// PY-14962
|
||||
public void testAlignDictLiteralOnValue() {
|
||||
getCustomSettings().DICT_ALIGNMENT = PyCodeStyleSettings.DICT_ALIGNMENT_ON_VALUE;
|
||||
doTest();
|
||||
}
|
||||
|
||||
// PY-14962
|
||||
public void testAlignDictLiteralOnColon() {
|
||||
getCustomSettings().DICT_ALIGNMENT = PyCodeStyleSettings.DICT_ALIGNMENT_ON_COLON;
|
||||
doTest();
|
||||
}
|
||||
|
||||
// PY-15530
|
||||
public void testAlignmentInArgumentListWhereFirstArgumentIsEmptyCall() {
|
||||
doTest();
|
||||
@@ -589,6 +601,11 @@ public class PyFormatterTest extends PyTestCase {
|
||||
doTest();
|
||||
}
|
||||
|
||||
public void testDoNotDestroyAlignment_OnPostponedFormatting() throws Exception {
|
||||
getCustomSettings().DICT_ALIGNMENT = PyCodeStyleSettings.DICT_ALIGNMENT_ON_COLON;
|
||||
doTest();
|
||||
}
|
||||
|
||||
public void testAlignmentOfEmptyCollectionLiterals() {
|
||||
doTest();
|
||||
}
|
||||
|
||||
@@ -49,10 +49,7 @@ import com.intellij.testFramework.LightProjectDescriptor;
|
||||
import com.intellij.testFramework.PlatformTestCase;
|
||||
import com.intellij.testFramework.TestDataPath;
|
||||
import com.intellij.testFramework.UsefulTestCase;
|
||||
import com.intellij.testFramework.fixtures.CodeInsightTestFixture;
|
||||
import com.intellij.testFramework.fixtures.IdeaProjectTestFixture;
|
||||
import com.intellij.testFramework.fixtures.IdeaTestFixtureFactory;
|
||||
import com.intellij.testFramework.fixtures.TestFixtureBuilder;
|
||||
import com.intellij.testFramework.fixtures.*;
|
||||
import com.intellij.testFramework.fixtures.impl.LightTempDirTestFixtureImpl;
|
||||
import com.intellij.usageView.UsageInfo;
|
||||
import com.intellij.usages.Usage;
|
||||
@@ -124,12 +121,20 @@ public abstract class PyTestCase extends UsefulTestCase {
|
||||
TestFixtureBuilder<IdeaProjectTestFixture> fixtureBuilder = factory.createLightFixtureBuilder(getProjectDescriptor());
|
||||
final IdeaProjectTestFixture fixture = fixtureBuilder.getFixture();
|
||||
myFixture = IdeaTestFixtureFactory.getFixtureFactory().createCodeInsightFixture(fixture,
|
||||
new LightTempDirTestFixtureImpl(true));
|
||||
createTempDirFixture());
|
||||
myFixture.setUp();
|
||||
|
||||
myFixture.setTestDataPath(getTestDataPath());
|
||||
}
|
||||
|
||||
/**
|
||||
* @return fixture to be used as temporary dir.
|
||||
*/
|
||||
@NotNull
|
||||
protected TempDirTestFixture createTempDirFixture() {
|
||||
return new LightTempDirTestFixtureImpl(true); // "tmp://" dir by default
|
||||
}
|
||||
|
||||
protected String getTestDataPath() {
|
||||
return PythonTestUtil.getTestDataPath();
|
||||
}
|
||||
|
||||
@@ -444,6 +444,8 @@ action.watch.method.return.value.description=Enables watching last executed meth
|
||||
action.watches.method.return.value.enable=Watch method return values
|
||||
action.watches.method.return.value.disable=Stop watching method return values
|
||||
action.watches.method.return.value.unavailable.reason=Feature is not supported by the target VM
|
||||
action.auto.variables.mode=Auto-Variables Mode
|
||||
action.auto.variables.mode.description=Show only variables used near the execution point
|
||||
action.maximizeContent.text
|
||||
breakpoint.properties.panel.option.depends.disable.again=Disable again
|
||||
breakpoint.properties.panel.option.depends.leave.enabled=Leave enabled
|
||||
|
||||
@@ -1521,12 +1521,13 @@
|
||||
<debugger.syntheticProvider implementation="com.intellij.debugger.engine.DefaultSyntheticProvider"/>
|
||||
<debugger.sourcePositionProvider implementation="com.intellij.debugger.engine.DefaultSourcePositionProvider" order="last"/>
|
||||
|
||||
<debugger.nodeRenderer implementation="com.intellij.debugger.settings.ColorObjectRenderer"/>
|
||||
<debugger.nodeRenderer implementation="com.intellij.debugger.settings.ImageObjectRenderer"/>
|
||||
<debugger.nodeRenderer implementation="com.intellij.debugger.settings.IconObjectRenderer"/>
|
||||
<debugger.nodeRenderer implementation="com.intellij.debugger.settings.GraphicsObjectRenderer"/>
|
||||
<debugger.nodeRenderer implementation="com.intellij.debugger.ui.tree.render.ColorObjectRenderer"/>
|
||||
<debugger.nodeRenderer implementation="com.intellij.debugger.ui.tree.render.ImageObjectRenderer"/>
|
||||
<debugger.nodeRenderer implementation="com.intellij.debugger.ui.tree.render.IconObjectRenderer"/>
|
||||
<debugger.nodeRenderer implementation="com.intellij.debugger.ui.tree.render.GraphicsObjectRenderer"/>
|
||||
<debugger.nodeRenderer implementation="com.intellij.debugger.ui.tree.render.BinaryRenderer"/>
|
||||
<debugger.nodeRenderer implementation="com.intellij.debugger.ui.tree.render.TimestampRenderer"/>
|
||||
<debugger.nodeRenderer implementation="com.intellij.debugger.ui.tree.render.FileObjectRenderer"/>
|
||||
|
||||
<applicationService serviceInterface="com.intellij.remoteServer.runtime.deployment.debug.JavaDebuggerLauncher"
|
||||
serviceImplementation="com.intellij.remoteServer.impl.runtime.deployment.debug.JavaDebuggerLauncherImpl"/>
|
||||
|
||||
Reference in New Issue
Block a user