init WEB-9103 nodejs: Debugger not showing value of getter

This commit is contained in:
Vladimir Krivosheev
2014-04-24 18:07:11 +02:00
parent 03cba2c32b
commit 72276e4b7f
5 changed files with 117 additions and 30 deletions
@@ -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
@@ -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;