8134939: Improve toString method of Dynalink DynamicMethod objects

Reviewed-by: hannesw, sundar
This commit is contained in:
Attila Szegedi 2015-09-02 16:35:14 +02:00
parent e68e98e9e0
commit dcc5af1d2d
9 changed files with 121 additions and 17 deletions

View File

@ -107,7 +107,7 @@ class CallerSensitiveDynamicMethod extends SingleDynamicMethod {
private final AccessibleObject target;
private final MethodType type;
public CallerSensitiveDynamicMethod(final AccessibleObject target) {
CallerSensitiveDynamicMethod(final AccessibleObject target) {
super(getName(target));
this.target = target;
this.type = getMethodType(target);
@ -115,8 +115,9 @@ class CallerSensitiveDynamicMethod extends SingleDynamicMethod {
private static String getName(final AccessibleObject target) {
final Member m = (Member)target;
return getMethodNameWithSignature(getMethodType(target), getClassAndMethodName(m.getDeclaringClass(),
m.getName()));
final boolean constructor = m instanceof Constructor;
return getMethodNameWithSignature(getMethodType(target), constructor ? m.getName() :
getClassAndMethodName(m.getDeclaringClass(), m.getName()), !constructor);
}
@Override

View File

@ -86,7 +86,9 @@ package jdk.internal.dynalink.beans;
import java.lang.invoke.MethodHandle;
import java.lang.invoke.MethodHandles;
import java.lang.invoke.MethodType;
import java.text.Collator;
import java.util.ArrayList;
import java.util.Collections;
import java.util.Iterator;
import java.util.LinkedList;
import java.util.List;
@ -242,6 +244,35 @@ class OverloadedDynamicMethod extends DynamicMethod {
return methods.getFirst().isConstructor();
}
@Override
public String toString() {
// First gather the names and sort them. This makes it consistent and easier to read.
final List<String> names = new ArrayList<>(methods.size());
int len = 0;
for (final SingleDynamicMethod m: methods) {
final String name = m.getName();
len += name.length();
names.add(name);
}
// Case insensitive sorting, so e.g. "Object" doesn't come before "boolean".
final Collator collator = Collator.getInstance();
collator.setStrength(Collator.SECONDARY);
Collections.sort(names, collator);
final String className = getClass().getName();
// Class name length + length of signatures + 2 chars/per signature for indentation and newline +
// 3 for brackets and initial newline
final int totalLength = className.length() + len + 2 * names.size() + 3;
final StringBuilder b = new StringBuilder(totalLength);
b.append('[').append(className).append('\n');
for(final String name: names) {
b.append(' ').append(name).append('\n');
}
b.append(']');
assert b.length() == totalLength;
return b.toString();
};
ClassLoader getClassLoader() {
return classLoader;
}

View File

@ -122,13 +122,13 @@ class SimpleDynamicMethod extends SingleDynamicMethod {
* @param constructor does this represent a constructor?
*/
SimpleDynamicMethod(final MethodHandle target, final Class<?> clazz, final String name, final boolean constructor) {
super(getName(target, clazz, name));
super(getName(target, clazz, name, constructor));
this.target = target;
this.constructor = constructor;
}
private static String getName(final MethodHandle target, final Class<?> clazz, final String name) {
return getMethodNameWithSignature(target.type(), getClassAndMethodName(clazz, name));
private static String getName(final MethodHandle target, final Class<?> clazz, final String name, final boolean constructor) {
return getMethodNameWithSignature(target.type(), constructor ? name : getClassAndMethodName(clazz, name), !constructor);
}
@Override

View File

@ -143,14 +143,18 @@ abstract class SingleDynamicMethod extends DynamicMethod {
return getMethodType().parameterList().equals(method.getMethodType().parameterList());
}
static String getMethodNameWithSignature(final MethodType type, final String methodName) {
static String getMethodNameWithSignature(final MethodType type, final String methodName, final boolean withReturnType) {
final String typeStr = type.toString();
final int retTypeIndex = typeStr.lastIndexOf(')') + 1;
int secondParamIndex = typeStr.indexOf(',') + 1;
if(secondParamIndex == 0) {
secondParamIndex = retTypeIndex - 1;
}
return typeStr.substring(retTypeIndex) + " " + methodName + "(" + typeStr.substring(secondParamIndex, retTypeIndex);
final StringBuilder b = new StringBuilder();
if (withReturnType) {
b.append(typeStr, retTypeIndex, typeStr.length()).append(' ');
}
return b.append(methodName).append('(').append(typeStr, secondParamIndex, retTypeIndex).toString();
}
/**

View File

@ -1,14 +1,28 @@
bcd
[jdk.internal.dynalink.beans.SimpleDynamicMethod String java.lang.String.java.lang.String(char[],int,int)]
[jdk.internal.dynalink.beans.SimpleDynamicMethod java.lang.String(char[],int,int)]
red
TypeError: No such Java class: java.lang.NonExistent
TypeError: No such Java constructor: Object(String)
TypeError: Java constructor signature invalid: Object()xxxxx
TypeError: Java constructor signature invalid: Object(
TypeError: Java constructor signature invalid: Object)
TypeError: Java method [jdk.internal.dynalink.beans.OverloadedDynamicMethod java.lang.System.getProperty] cannot be used as a constructor.
TypeError: Java method [jdk.internal.dynalink.beans.OverloadedDynamicMethod java.io.PrintStream.println] cannot be used as a constructor.
TypeError: Constructor [jdk.internal.dynalink.beans.SimpleDynamicMethod String java.lang.String.java.lang.String(char[],int,int)] requires "new".
TypeError: Java method [jdk.internal.dynalink.beans.OverloadedDynamicMethod
String java.lang.System.getProperty(String,String)
String java.lang.System.getProperty(String)
] cannot be used as a constructor.
TypeError: Java method [jdk.internal.dynalink.beans.OverloadedDynamicMethod
void java.io.PrintStream.println()
void java.io.PrintStream.println(boolean)
void java.io.PrintStream.println(char)
void java.io.PrintStream.println(char[])
void java.io.PrintStream.println(double)
void java.io.PrintStream.println(float)
void java.io.PrintStream.println(int)
void java.io.PrintStream.println(long)
void java.io.PrintStream.println(Object)
void java.io.PrintStream.println(String)
] cannot be used as a constructor.
TypeError: Constructor [jdk.internal.dynalink.beans.SimpleDynamicMethod java.lang.String(char[],int,int)] requires "new".
TypeError: No such Java constructor: Runnable()
TypeError: No such Java constructor: Runnable(int)
java.lang.InstantiationException: java.io.InputStream

View File

@ -1,10 +1,10 @@
abc
[jdk.internal.dynalink.beans.SimpleDynamicMethod String java.lang.String.java.lang.String(char[],int,int)]
[jdk.internal.dynalink.beans.SimpleDynamicMethod java.lang.String(char[],int,int)]
ava
TypeError: null is not a function
TypeError: null is not a function
TypeError: null is not a function
TypeError: Constructor [jdk.internal.dynalink.beans.SimpleDynamicMethod String java.lang.String.java.lang.String(char[],int,int)] requires "new".
TypeError: Constructor [jdk.internal.dynalink.beans.SimpleDynamicMethod java.lang.String(char[],int,int)] requires "new".
TypeError: null is not a function
TypeError: null is not a function
java.lang.InstantiationException: java.io.InputStream

View File

@ -1,2 +1,2 @@
TypeError: Can not create new object with constructor [jdk.internal.dynalink.beans.SimpleDynamicMethod File java.io.File.java.io.File(String,String)] with the passed arguments; they do not match any of its method signatures.
TypeError: Can not create new object with constructor [jdk.internal.dynalink.beans.SimpleDynamicMethod Color java.awt.Color.java.awt.Color(int,int,int)] with the passed arguments; they do not match any of its method signatures.
TypeError: Can not create new object with constructor [jdk.internal.dynalink.beans.SimpleDynamicMethod java.io.File(String,String)] with the passed arguments; they do not match any of its method signatures.
TypeError: Can not create new object with constructor [jdk.internal.dynalink.beans.SimpleDynamicMethod java.awt.Color(int,int,int)] with the passed arguments; they do not match any of its method signatures.

View File

@ -0,0 +1,43 @@
/*
* Copyright (c) 2015 Oracle and/or its affiliates. All rights reserved.
* DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
*
* This code is free software; you can redistribute it and/or modify it
* under the terms of the GNU General Public License version 2 only, as
* published by the Free Software Foundation.
*
* This code is distributed in the hope that it will be useful, but WITHOUT
* ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
* FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
* version 2 for more details (a copy is included in the LICENSE file that
* accompanied this code).
*
* You should have received a copy of the GNU General Public License version
* 2 along with this work; if not, write to the Free Software Foundation,
* Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
*
* Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
* or visit www.oracle.com if you need additional information or have any
* questions.
*/
/**
* JDK-8134939: Improve toString method of Dynalink OverloadedDynamicMethod
*
* @test
* @run
*/
var overloadedSetter = new (Java.type("jdk.nashorn.test.models.OverloadedSetter"));
Assert.assertEquals(String(overloadedSetter.foo),
"[jdk.internal.dynalink.beans.OverloadedDynamicMethod\n" +
" String jdk.nashorn.test.models.OverloadedSetter.foo(String)\n" +
" void jdk.nashorn.test.models.OverloadedSetter.foo(int)\n" +
"]");
Assert.assertEquals(String(overloadedSetter.setColor),
"[jdk.internal.dynalink.beans.OverloadedDynamicMethod\n" +
" void jdk.nashorn.test.models.OverloadedSetter.setColor(int)\n" +
" void jdk.nashorn.test.models.OverloadedSetter.setColor(String)\n" +
"]");

View File

@ -4,7 +4,18 @@ typeof java.util.Vector evalutes to function
typeof java.util.Map evalutes to function
typeof java.util.HashMap evalutes to function
var m = new java.util.HashMap(); m.put('foo', 42); m evalutes to {foo=42}
java.lang.System.out.println evalutes to [jdk.internal.dynalink.beans.OverloadedDynamicMethod java.io.PrintStream.println]
java.lang.System.out.println evalutes to [jdk.internal.dynalink.beans.OverloadedDynamicMethod
void java.io.PrintStream.println()
void java.io.PrintStream.println(boolean)
void java.io.PrintStream.println(char)
void java.io.PrintStream.println(char[])
void java.io.PrintStream.println(double)
void java.io.PrintStream.println(float)
void java.io.PrintStream.println(int)
void java.io.PrintStream.println(long)
void java.io.PrintStream.println(Object)
void java.io.PrintStream.println(String)
]
java.lang.System.exit evalutes to [jdk.internal.dynalink.beans.SimpleDynamicMethod void java.lang.System.exit(int)]
new javax.script.SimpleBindings throws java.lang.RuntimeException: java.lang.ClassNotFoundException: javax.script.SimpleBindings
Java.type('javax.script.ScriptContext') throws java.lang.RuntimeException: java.lang.ClassNotFoundException: javax.script.ScriptContext