Merge remote-tracking branch 'origin/master'

This commit is contained in:
Anna Kozlova
2014-04-24 18:10:17 +02:00
11 changed files with 211 additions and 91 deletions
@@ -44,11 +44,11 @@ public class Launcher {
final URLClassLoader jpsLoader = new URLClassLoader(urls.toArray(new URL[urls.size()]), Launcher.class.getClassLoader());
// IDEA-120811; speeding up DefaultChannelIDd calculation for netty
if (Boolean.parseBoolean(System.getProperty("io.netty.random.id"))) {
//if (Boolean.parseBoolean(System.getProperty("io.netty.random.id"))) {
final String id = UUID.randomUUID().toString();
System.setProperty("io.netty.machineId", id.substring(id.length() - 8));
System.setProperty("io.netty.processId", Integer.toString(new Random().nextInt(65535)));
}
//}
final Class<?> mainClass = jpsLoader.loadClass(mainClassName);
final Method mainMethod = mainClass.getMethod("main", String[].class);
@@ -45,7 +45,7 @@ public final class NettyUtil {
static {
// IDEA-120811
if (SystemProperties.getBooleanProperty("io.netty.random.id", false)) {
if (SystemProperties.getBooleanProperty("io.netty.random.id", true)) {
String id = UUID.randomUUID().toString();
System.setProperty("io.netty.machineId", id.substring(id.length() - 8));
System.setProperty("io.netty.processId", Integer.toString(new Random().nextInt(65535)));
@@ -4,6 +4,7 @@ import com.intellij.openapi.util.AsyncResult;
import org.jetbrains.annotations.NotNull;
import org.jetbrains.annotations.Nullable;
import org.jetbrains.debugger.values.FunctionValue;
import org.jetbrains.debugger.values.ObjectValue;
import org.jetbrains.debugger.values.Value;
/**
@@ -42,5 +43,5 @@ public interface ObjectProperty extends Variable {
* Asynchronously evaluates property getter and returns property value
*/
@NotNull
AsyncResult<Value> evaluateGet(@NotNull EvaluateContext evaluateContext);
AsyncResult<Value> evaluateGet(@NotNull ObjectValue host, @NotNull EvaluateContext evaluateContext);
}
@@ -1,11 +1,34 @@
package org.jetbrains.debugger;
import com.intellij.openapi.util.ActionCallback;
import com.intellij.openapi.util.AsyncResult;
import com.intellij.util.Consumer;
import org.jetbrains.annotations.NotNull;
import org.jetbrains.debugger.values.ObjectValue;
import org.jetbrains.debugger.values.Value;
import java.util.Collections;
import java.util.List;
import java.util.regex.Pattern;
public final class ValueModifierUtil {
private static final Pattern KEY_NOTATION_PROPERTY_NAME_PATTERN = Pattern.compile("[\\p{L}_$]+[\\d\\p{L}_$]*");
private static final String[] REPLACEMENT_CHARS;
static {
REPLACEMENT_CHARS = new String[128];
for (int i = 0; i <= 31; i++) {
REPLACEMENT_CHARS[i] = String.format("\\u%04x", (int)i);
}
REPLACEMENT_CHARS['"'] = "\\\"";
REPLACEMENT_CHARS['\\'] = "\\\\";
REPLACEMENT_CHARS['\t'] = "\\t";
REPLACEMENT_CHARS['\b'] = "\\b";
REPLACEMENT_CHARS['\n'] = "\\n";
REPLACEMENT_CHARS['\r'] = "\\r";
REPLACEMENT_CHARS['\f'] = "\\f";
}
public static ActionCallback setValue(@NotNull final Variable variable, String newValue, @NotNull final EvaluateContext evaluateContext, @NotNull final ValueModifier modifier) {
final ActionCallback callback = new ActionCallback();
evaluateContext.evaluate(newValue).doWhenDone(new Consumer<Value>() {
@@ -16,4 +39,88 @@ public final class ValueModifierUtil {
}).notifyWhenRejected(callback);
return callback;
}
@NotNull
public static AsyncResult<Value> evaluateGet(@NotNull final ObjectProperty property,
@NotNull EvaluateContextAdditionalParameter host,
@NotNull EvaluateContext evaluateContext,
@NotNull String selfName) {
ObjectValue getterFunction = property.getGetter();
if (getterFunction == null) {
throw new RuntimeException("Getter is not a function");
}
StringBuilder builder = new StringBuilder(selfName);
appendName(builder, property.getName(), false);
return evaluateContext.evaluate(builder.toString(), Collections.singletonMap(selfName, host)).doWhenDone(new Consumer<Value>() {
@Override
public void consume(Value value) {
property.setValue(value);
}
});
}
public static String propertyNamesToString(List<String> list, boolean quotedAware) {
StringBuilder builder = new StringBuilder();
for (int i = list.size() - 1; i >= 0; i--) {
String name = list.get(i);
boolean quoted = quotedAware && (name.charAt(0) == '"' || name.charAt(0) == '\'');
appendName(builder, name, quoted);
}
return builder.toString();
}
public static void appendName(@NotNull StringBuilder builder, @NotNull String name, boolean quoted) {
boolean useKeyNotation = !quoted && KEY_NOTATION_PROPERTY_NAME_PATTERN.matcher(name).matches();
if (builder.length() != 0) {
builder.append(useKeyNotation ? '.' : '[');
}
if (useKeyNotation) {
builder.append(name);
}
else {
if (quoted) {
builder.append(name);
}
else {
escape(name, builder);
}
builder.append(']');
}
}
public static void escape(CharSequence value, StringBuilder sb) {
int length = value.length();
sb.ensureCapacity(sb.capacity() + length + 2);
sb.append('"');
int last = 0;
for (int i = 0; i < length; i++) {
char c = value.charAt(i);
String replacement;
if (c < 128) {
replacement = REPLACEMENT_CHARS[c];
if (replacement == null) {
continue;
}
}
else if (c == '\u2028') {
replacement = "\\u2028";
}
else if (c == '\u2029') {
replacement = "\\u2029";
}
else {
continue;
}
if (last < i) {
sb.append(value, last, i);
}
sb.append(replacement);
last = i + 1;
}
if (last < length) {
sb.append(value, last, length);
}
sb.append('"');
}
}
@@ -1,20 +1,20 @@
package org.jetbrains.debugger.values;
import com.intellij.openapi.util.AsyncResult;
import org.jetbrains.annotations.NotNull;
import org.jetbrains.annotations.Nullable;
import org.jetbrains.debugger.EvaluateContext;
import org.jetbrains.debugger.ObjectProperty;
import org.jetbrains.debugger.ValueModifier;
import org.jetbrains.debugger.VariableImpl;
public abstract class ObjectPropertyBase extends VariableImpl implements ObjectProperty {
private final FunctionValue getter;
private final FunctionValue setter;
protected ObjectPropertyBase(@NotNull String name, @Nullable Value value, @Nullable FunctionValue getter, @Nullable ValueModifier valueModifier) {
protected ObjectPropertyBase(@NotNull String name, @Nullable Value value, @Nullable FunctionValue getter, @Nullable FunctionValue setter, @Nullable ValueModifier valueModifier) {
super(name, value, valueModifier);
this.getter = getter;
this.setter = setter;
}
@Override
@@ -31,7 +31,7 @@ public abstract class ObjectPropertyBase extends VariableImpl implements ObjectP
@Nullable
@Override
public FunctionValue getSetter() {
return null;
return setter;
}
@Override
@@ -43,10 +43,4 @@ public abstract class ObjectPropertyBase extends VariableImpl implements ObjectP
public boolean isEnumerable() {
return true;
}
@NotNull
@Override
public AsyncResult<Value> evaluateGet(@NotNull EvaluateContext evaluateContext) {
throw new UnsupportedOperationException();
}
}
@@ -72,24 +72,7 @@ public interface DebuggerViewSupport extends MemberFilter {
@NotNull
@Override
public String propertyNamesToString(@NotNull List<String> list, boolean quotedAware) {
// todo
StringBuilder builder = new StringBuilder();
for (int i = list.size() - 1; i >= 0; i--) {
String name = list.get(i);
boolean quoted = quotedAware && (name.charAt(0) == '"' || name.charAt(0) == '\'');
boolean useKeyNotation = !quoted;
if (builder.length() != 0) {
builder.append(useKeyNotation ? '.' : '[');
}
if (useKeyNotation) {
builder.append(name);
}
else {
builder.append(name);
builder.append(']');
}
}
return builder.toString();
return ValueModifierUtil.propertyNamesToString(list, quotedAware);
}
@Override
@@ -27,7 +27,7 @@ public class ScopeVariablesGroup extends XValueGroup {
this.context = new ParentlessVariableContext(context, scope, scope.getType() == Scope.Type.GLOBAL);
}
else {
this.context = new ScopedVariableContext(context, scope);
this.context = new VariableContextWrapper(context, scope);
}
this.callFrame = scope.getType() == Scope.Type.LOCAL ? callFrame : null;
@@ -91,7 +91,7 @@ public class ScopeVariablesGroup extends XValueGroup {
@Override
public void consume(Variable variable) {
if (!node.isObsolete()) {
node.addChildren(variable == null ? XValueChildrenList.EMPTY : XValueChildrenList.singleton(CallFrameBase.RECEIVER_NAME, new VariableView(context, variable)), true);
node.addChildren(variable == null ? XValueChildrenList.EMPTY : XValueChildrenList.singleton(CallFrameBase.RECEIVER_NAME, new VariableView(variable, context)), true);
}
}
}).doWhenRejected(new Consumer<String>() {
@@ -107,58 +107,7 @@ public class ScopeVariablesGroup extends XValueGroup {
Variables.processScopeVariables(scope, node, context, callback);
}
private static class ScopedVariableContext implements VariableContext {
private final VariableContext parentContext;
private final Scope scope;
public ScopedVariableContext(@NotNull VariableContext parentContext, @NotNull Scope scope) {
this.parentContext = parentContext;
this.scope = scope;
}
@Nullable
@Override
public String getName() {
return parentContext.getName();
}
@NotNull
@Override
public MemberFilter getMemberFilter() {
return parentContext.getMemberFilter();
}
@NotNull
@Override
public EvaluateContext getEvaluateContext() {
return parentContext.getEvaluateContext();
}
@NotNull
@Override
public DebuggerViewSupport getDebugProcess() {
return parentContext.getDebugProcess();
}
@Override
public boolean watchableAsEvaluationExpression() {
return parentContext.watchableAsEvaluationExpression();
}
@Nullable
@Override
public Scope getScope() {
return scope;
}
@Nullable
@Override
public VariableContext getParent() {
return parentContext;
}
}
private static final class ParentlessVariableContext extends ScopedVariableContext {
private static final class ParentlessVariableContext extends VariableContextWrapper {
private final boolean watchableAsEvaluationExpression;
public ParentlessVariableContext(@NotNull VariableContext parentContext, @NotNull Scope scope, boolean watchableAsEvaluationExpression) {
@@ -0,0 +1,55 @@
package org.jetbrains.debugger;
import org.jetbrains.annotations.NotNull;
import org.jetbrains.annotations.Nullable;
class VariableContextWrapper implements VariableContext {
private final VariableContext parentContext;
private final Scope scope;
public VariableContextWrapper(@NotNull VariableContext parentContext, @Nullable Scope scope) {
this.parentContext = parentContext;
this.scope = scope;
}
@Nullable
@Override
public String getName() {
return parentContext.getName();
}
@NotNull
@Override
public MemberFilter getMemberFilter() {
return parentContext.getMemberFilter();
}
@NotNull
@Override
public EvaluateContext getEvaluateContext() {
return parentContext.getEvaluateContext();
}
@NotNull
@Override
public DebuggerViewSupport getDebugProcess() {
return parentContext.getDebugProcess();
}
@Override
public boolean watchableAsEvaluationExpression() {
return parentContext.watchableAsEvaluationExpression();
}
@Nullable
@Override
public Scope getScope() {
return scope;
}
@Nullable
@Override
public VariableContext getParent() {
return parentContext;
}
}
@@ -49,7 +49,7 @@ public final class VariableView extends XNamedValue implements VariableContext {
private volatile List<Variable> remainingChildren;
private volatile int remainingChildrenOffset;
public VariableView(@NotNull VariableContext context, @NotNull Variable variable) {
public VariableView(@NotNull Variable variable, @NotNull VariableContext context) {
super(context.getMemberFilter().normalizeMemberName(variable));
this.context = context;
@@ -137,7 +137,9 @@ public final class VariableView extends XNamedValue implements VariableContext {
public void computePresentation(@NotNull XValueNode node, @NotNull XValuePlace place) {
value = variable.getValue();
if (value == null) {
ObsolescentAsyncResults.consume(((ObjectProperty)variable).evaluateGet(context.getEvaluateContext()), node, new PairConsumer<Value, XValueNode>() {
ObjectValue host = (ObjectValue)((VariableView)context).getValue();
assert host != null;
ObsolescentAsyncResults.consume(((ObjectProperty)variable).evaluateGet(host, getEvaluateContext()), node, new PairConsumer<Value, XValueNode>() {
@Override
public void consume(Value value, XValueNode node) {
VariableView.this.value = value;
@@ -349,7 +351,7 @@ public final class VariableView extends XNamedValue implements VariableContext {
}
for (int i = notGroupedVariablesOffset; i < variables.size(); i++) {
groupList.add(new VariableView(this, variables.get(i)));
groupList.add(new VariableView(variables.get(i), this));
}
node.addChildren(groupList, true);
@@ -217,9 +217,39 @@ public final class Variables {
public static XValueChildrenList createVariablesList(@NotNull List<Variable> variables, int from, int to, @NotNull VariableContext variableContext) {
XValueChildrenList list = new XValueChildrenList(to - from);
VariableContext getterOrSetterContext = null;
for (int i = from; i < to; i++) {
list.add(new VariableView(variableContext, variables.get(i)));
Variable variable = variables.get(i);
list.add(new VariableView(variable, variableContext));
if (variable instanceof ObjectProperty) {
ObjectProperty property = (ObjectProperty)variable;
if (property.getGetter() != null) {
if (getterOrSetterContext == null) {
getterOrSetterContext = new NonWatchableVariableContext(variableContext);
}
list.add(new VariableView(new VariableImpl("get " + property.getName(), property.getGetter()), getterOrSetterContext));
}
if (property.getSetter() != null) {
if (getterOrSetterContext == null) {
getterOrSetterContext = new NonWatchableVariableContext(variableContext);
}
list.add(new VariableView(new VariableImpl("set " + property.getName(), property.getSetter()), getterOrSetterContext));
}
}
}
return list;
}
private static class NonWatchableVariableContext extends VariableContextWrapper {
public NonWatchableVariableContext(VariableContext variableContext) {
super(variableContext, null);
}
@Override
public boolean watchableAsEvaluationExpression() {
return false;
}
}
}
@@ -43,7 +43,6 @@ public class XValueNodeImpl extends XValueContainerNode<XValue> implements XValu
public static final Comparator<XValueNodeImpl> COMPARATOR = new Comparator<XValueNodeImpl>() {
@Override
public int compare(XValueNodeImpl o1, XValueNodeImpl o2) {
//noinspection ConstantConditions
return StringUtil.naturalCompare(o1.getName(), o2.getName());
}
};