diff --git a/jps/jps-launcher/src/org/jetbrains/jps/cmdline/Launcher.java b/jps/jps-launcher/src/org/jetbrains/jps/cmdline/Launcher.java index c97c70705317..4bbbe937d2c2 100644 --- a/jps/jps-launcher/src/org/jetbrains/jps/cmdline/Launcher.java +++ b/jps/jps-launcher/src/org/jetbrains/jps/cmdline/Launcher.java @@ -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); diff --git a/platform/platform-impl/src/org/jetbrains/io/NettyUtil.java b/platform/platform-impl/src/org/jetbrains/io/NettyUtil.java index 208c285b6b86..8a898de77a9b 100644 --- a/platform/platform-impl/src/org/jetbrains/io/NettyUtil.java +++ b/platform/platform-impl/src/org/jetbrains/io/NettyUtil.java @@ -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))); diff --git a/platform/script-debugger/backend/src/org/jetbrains/debugger/ObjectProperty.java b/platform/script-debugger/backend/src/org/jetbrains/debugger/ObjectProperty.java index 4cf529638edd..a3f9a9683fc8 100644 --- a/platform/script-debugger/backend/src/org/jetbrains/debugger/ObjectProperty.java +++ b/platform/script-debugger/backend/src/org/jetbrains/debugger/ObjectProperty.java @@ -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 evaluateGet(@NotNull EvaluateContext evaluateContext); + AsyncResult evaluateGet(@NotNull ObjectValue host, @NotNull EvaluateContext evaluateContext); } diff --git a/platform/script-debugger/backend/src/org/jetbrains/debugger/ValueModifierUtil.java b/platform/script-debugger/backend/src/org/jetbrains/debugger/ValueModifierUtil.java index 654008063f1a..ae3269ef0140 100644 --- a/platform/script-debugger/backend/src/org/jetbrains/debugger/ValueModifierUtil.java +++ b/platform/script-debugger/backend/src/org/jetbrains/debugger/ValueModifierUtil.java @@ -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() { @@ -16,4 +39,88 @@ public final class ValueModifierUtil { }).notifyWhenRejected(callback); return callback; } + + @NotNull + public static AsyncResult 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() { + @Override + public void consume(Value value) { + property.setValue(value); + } + }); + } + + public static String propertyNamesToString(List 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('"'); + } } \ No newline at end of file diff --git a/platform/script-debugger/backend/src/org/jetbrains/debugger/values/ObjectPropertyBase.java b/platform/script-debugger/backend/src/org/jetbrains/debugger/values/ObjectPropertyBase.java index dd38cc1ba260..a7b7824f38f4 100644 --- a/platform/script-debugger/backend/src/org/jetbrains/debugger/values/ObjectPropertyBase.java +++ b/platform/script-debugger/backend/src/org/jetbrains/debugger/values/ObjectPropertyBase.java @@ -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 evaluateGet(@NotNull EvaluateContext evaluateContext) { - throw new UnsupportedOperationException(); - } } \ No newline at end of file diff --git a/platform/script-debugger/debugger-ui/src/org/jetbrains/debugger/DebuggerViewSupport.java b/platform/script-debugger/debugger-ui/src/org/jetbrains/debugger/DebuggerViewSupport.java index 3331155243b4..95e4a208594b 100644 --- a/platform/script-debugger/debugger-ui/src/org/jetbrains/debugger/DebuggerViewSupport.java +++ b/platform/script-debugger/debugger-ui/src/org/jetbrains/debugger/DebuggerViewSupport.java @@ -72,24 +72,7 @@ public interface DebuggerViewSupport extends MemberFilter { @NotNull @Override public String propertyNamesToString(@NotNull List 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 diff --git a/platform/script-debugger/debugger-ui/src/org/jetbrains/debugger/ScopeVariablesGroup.java b/platform/script-debugger/debugger-ui/src/org/jetbrains/debugger/ScopeVariablesGroup.java index 933e5ccf7c73..dfe0b5f9c0f5 100644 --- a/platform/script-debugger/debugger-ui/src/org/jetbrains/debugger/ScopeVariablesGroup.java +++ b/platform/script-debugger/debugger-ui/src/org/jetbrains/debugger/ScopeVariablesGroup.java @@ -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() { @@ -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) { diff --git a/platform/script-debugger/debugger-ui/src/org/jetbrains/debugger/VariableContextWrapper.java b/platform/script-debugger/debugger-ui/src/org/jetbrains/debugger/VariableContextWrapper.java new file mode 100644 index 000000000000..0a46f84b9622 --- /dev/null +++ b/platform/script-debugger/debugger-ui/src/org/jetbrains/debugger/VariableContextWrapper.java @@ -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; + } +} \ No newline at end of file diff --git a/platform/script-debugger/debugger-ui/src/org/jetbrains/debugger/VariableView.java b/platform/script-debugger/debugger-ui/src/org/jetbrains/debugger/VariableView.java index d198296d0cea..5bad94430810 100644 --- a/platform/script-debugger/debugger-ui/src/org/jetbrains/debugger/VariableView.java +++ b/platform/script-debugger/debugger-ui/src/org/jetbrains/debugger/VariableView.java @@ -49,7 +49,7 @@ public final class VariableView extends XNamedValue implements VariableContext { private volatile List 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() { + ObjectValue host = (ObjectValue)((VariableView)context).getValue(); + assert host != null; + ObsolescentAsyncResults.consume(((ObjectProperty)variable).evaluateGet(host, getEvaluateContext()), node, new PairConsumer() { @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); diff --git a/platform/script-debugger/debugger-ui/src/org/jetbrains/debugger/Variables.java b/platform/script-debugger/debugger-ui/src/org/jetbrains/debugger/Variables.java index f68b45d39127..25fd52851f69 100644 --- a/platform/script-debugger/debugger-ui/src/org/jetbrains/debugger/Variables.java +++ b/platform/script-debugger/debugger-ui/src/org/jetbrains/debugger/Variables.java @@ -217,9 +217,39 @@ public final class Variables { public static XValueChildrenList createVariablesList(@NotNull List 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; + } + } } \ No newline at end of file diff --git a/platform/xdebugger-impl/src/com/intellij/xdebugger/impl/ui/tree/nodes/XValueNodeImpl.java b/platform/xdebugger-impl/src/com/intellij/xdebugger/impl/ui/tree/nodes/XValueNodeImpl.java index a0cb0cdb8b0a..1dbb83bbf4a1 100644 --- a/platform/xdebugger-impl/src/com/intellij/xdebugger/impl/ui/tree/nodes/XValueNodeImpl.java +++ b/platform/xdebugger-impl/src/com/intellij/xdebugger/impl/ui/tree/nodes/XValueNodeImpl.java @@ -43,7 +43,6 @@ public class XValueNodeImpl extends XValueContainerNode implements XValu public static final Comparator COMPARATOR = new Comparator() { @Override public int compare(XValueNodeImpl o1, XValueNodeImpl o2) { - //noinspection ConstantConditions return StringUtil.naturalCompare(o1.getName(), o2.getName()); } };