8145486: jjs should support documentation key shortcut in interactive mode
Reviewed-by: mhaupt, hannesw
--- a/nashorn/buildtools/nasgen/src/jdk/nashorn/internal/tools/nasgen/ClassGenerator.java Mon Dec 14 17:38:56 2015 +0100
+++ b/nashorn/buildtools/nasgen/src/jdk/nashorn/internal/tools/nasgen/ClassGenerator.java Wed Dec 16 16:42:03 2015 +0530
@@ -59,6 +59,8 @@
import static jdk.nashorn.internal.tools.nasgen.StringConstants.SCRIPTFUNCTION_CREATEBUILTIN_SPECS_DESC;
import static jdk.nashorn.internal.tools.nasgen.StringConstants.SCRIPTFUNCTION_SETARITY;
import static jdk.nashorn.internal.tools.nasgen.StringConstants.SCRIPTFUNCTION_SETARITY_DESC;
+import static jdk.nashorn.internal.tools.nasgen.StringConstants.SCRIPTFUNCTION_SETDOCUMENTATION;
+import static jdk.nashorn.internal.tools.nasgen.StringConstants.SCRIPTFUNCTION_SETDOCUMENTATION_DESC;
import static jdk.nashorn.internal.tools.nasgen.StringConstants.SCRIPTFUNCTION_TYPE;
import static jdk.nashorn.internal.tools.nasgen.StringConstants.SETTER_PREFIX;
import static jdk.nashorn.internal.tools.nasgen.StringConstants.TYPE_OBJECT;
@@ -291,6 +293,13 @@
mi.push(memInfo.getArity());
mi.invokeVirtual(SCRIPTFUNCTION_TYPE, SCRIPTFUNCTION_SETARITY, SCRIPTFUNCTION_SETARITY_DESC);
}
+
+ String doc = memInfo.getDocumentation();
+ if (doc != null) {
+ mi.dup();
+ mi.loadLiteral(memInfo.getDocumentation());
+ mi.invokeVirtual(SCRIPTFUNCTION_TYPE, SCRIPTFUNCTION_SETDOCUMENTATION, SCRIPTFUNCTION_SETDOCUMENTATION_DESC);
+ }
}
static void linkerAddGetterSetter(final MethodGenerator mi, final String className, final MemberInfo memInfo) {
--- a/nashorn/buildtools/nasgen/src/jdk/nashorn/internal/tools/nasgen/ConstructorGenerator.java Mon Dec 14 17:38:56 2015 +0100
+++ b/nashorn/buildtools/nasgen/src/jdk/nashorn/internal/tools/nasgen/ConstructorGenerator.java Wed Dec 16 16:42:03 2015 +0530
@@ -42,6 +42,8 @@
import static jdk.nashorn.internal.tools.nasgen.StringConstants.SCRIPTFUNCTION_INIT_DESC4;
import static jdk.nashorn.internal.tools.nasgen.StringConstants.SCRIPTFUNCTION_SETARITY;
import static jdk.nashorn.internal.tools.nasgen.StringConstants.SCRIPTFUNCTION_SETARITY_DESC;
+import static jdk.nashorn.internal.tools.nasgen.StringConstants.SCRIPTFUNCTION_SETDOCUMENTATION;
+import static jdk.nashorn.internal.tools.nasgen.StringConstants.SCRIPTFUNCTION_SETDOCUMENTATION_DESC;
import static jdk.nashorn.internal.tools.nasgen.StringConstants.SCRIPTFUNCTION_SETPROTOTYPE;
import static jdk.nashorn.internal.tools.nasgen.StringConstants.SCRIPTFUNCTION_SETPROTOTYPE_DESC;
import static jdk.nashorn.internal.tools.nasgen.StringConstants.SCRIPTFUNCTION_TYPE;
@@ -159,6 +161,13 @@
mi.invokeVirtual(SCRIPTFUNCTION_TYPE, SCRIPTFUNCTION_SETARITY,
SCRIPTFUNCTION_SETARITY_DESC);
}
+ final String doc = constructor.getDocumentation();
+ if (doc != null) {
+ mi.loadThis();
+ mi.loadLiteral(doc);
+ mi.invokeVirtual(SCRIPTFUNCTION_TYPE, SCRIPTFUNCTION_SETDOCUMENTATION,
+ SCRIPTFUNCTION_SETDOCUMENTATION_DESC);
+ }
}
mi.returnVoid();
mi.computeMaxs();
--- a/nashorn/buildtools/nasgen/src/jdk/nashorn/internal/tools/nasgen/MemberInfo.java Mon Dec 14 17:38:56 2015 +0100
+++ b/nashorn/buildtools/nasgen/src/jdk/nashorn/internal/tools/nasgen/MemberInfo.java Wed Dec 16 16:42:03 2015 +0530
@@ -85,6 +85,8 @@
private MemberInfo.Kind kind;
// script property name
private String name;
+ // documentation for this member
+ private String documentation;
// script property attributes
private int attributes;
// name of the java member
@@ -137,6 +139,20 @@
}
/**
+ * @return the documentation
+ */
+ public String getDocumentation() {
+ return documentation;
+ }
+
+ /**
+ * @param doc the documentation to set
+ */
+ public void setDocumentation(final String doc) {
+ this.documentation = doc;
+ }
+
+ /**
* Tag something as specialized constructor or not
* @param isSpecializedConstructor boolean, true if specialized constructor
*/
--- a/nashorn/buildtools/nasgen/src/jdk/nashorn/internal/tools/nasgen/ScriptClassInfoCollector.java Mon Dec 14 17:38:56 2015 +0100
+++ b/nashorn/buildtools/nasgen/src/jdk/nashorn/internal/tools/nasgen/ScriptClassInfoCollector.java Wed Dec 16 16:42:03 2015 +0530
@@ -206,6 +206,7 @@
// These could be "null" if values are not supplied,
// in which case we have to use the default values.
private String name;
+ private String documentation;
private Integer attributes;
private Integer arity;
private Where where;
@@ -222,6 +223,13 @@
name = null;
}
break;
+ case "documentation":
+ this.documentation = (String)annotationValue;
+ if (documentation.isEmpty()) {
+ documentation = null;
+ }
+
+ break;
case "attributes":
this.attributes = (Integer)annotationValue;
break;
@@ -270,6 +278,8 @@
} else {
memInfo.setName(name == null ? methodName : name);
}
+
+ memInfo.setDocumentation(documentation);
memInfo.setAttributes(attributes == null ? MemberInfo.DEFAULT_ATTRIBUTES : attributes);
memInfo.setArity((arity == null)? MemberInfo.DEFAULT_ARITY : arity);
--- a/nashorn/buildtools/nasgen/src/jdk/nashorn/internal/tools/nasgen/StringConstants.java Mon Dec 14 17:38:56 2015 +0100
+++ b/nashorn/buildtools/nasgen/src/jdk/nashorn/internal/tools/nasgen/StringConstants.java Wed Dec 16 16:42:03 2015 +0530
@@ -118,6 +118,8 @@
static final String SCRIPTFUNCTION_TYPE = TYPE_SCRIPTFUNCTION.getInternalName();
static final String SCRIPTFUNCTION_SETARITY = "setArity";
static final String SCRIPTFUNCTION_SETARITY_DESC = Type.getMethodDescriptor(Type.VOID_TYPE, Type.INT_TYPE);
+ static final String SCRIPTFUNCTION_SETDOCUMENTATION = "setDocumentation";
+ static final String SCRIPTFUNCTION_SETDOCUMENTATION_DESC = Type.getMethodDescriptor(Type.VOID_TYPE, TYPE_STRING);
static final String SCRIPTFUNCTION_SETPROTOTYPE = "setPrototype";
static final String SCRIPTFUNCTION_SETPROTOTYPE_DESC = Type.getMethodDescriptor(Type.VOID_TYPE, TYPE_OBJECT);
static final String SCRIPTFUNCTION_CREATEBUILTIN = "createBuiltin";
--- a/nashorn/src/jdk.scripting.nashorn.shell/share/classes/jdk/nashorn/tools/jjs/Console.java Mon Dec 14 17:38:56 2015 +0100
+++ b/nashorn/src/jdk.scripting.nashorn.shell/share/classes/jdk/nashorn/tools/jjs/Console.java Wed Dec 16 16:42:03 2015 +0530
@@ -25,6 +25,7 @@
package jdk.nashorn.tools.jjs;
+import java.awt.event.ActionListener;
import java.io.File;
import java.io.IOException;
import java.io.InputStream;
@@ -34,21 +35,24 @@
import java.util.Collections;
import java.util.Iterator;
import java.util.List;
+import java.util.function.Function;
import jdk.internal.jline.NoInterruptUnixTerminal;
import jdk.internal.jline.Terminal;
import jdk.internal.jline.TerminalFactory;
import jdk.internal.jline.TerminalFactory.Flavor;
import jdk.internal.jline.WindowsTerminal;
import jdk.internal.jline.console.ConsoleReader;
+import jdk.internal.jline.console.KeyMap;
import jdk.internal.jline.console.completer.Completer;
import jdk.internal.jline.console.history.FileHistory;
class Console implements AutoCloseable {
+ private static final String DOCUMENTATION_SHORTCUT = "\033\133\132"; //Shift-TAB
private final ConsoleReader in;
private final FileHistory history;
Console(final InputStream cmdin, final PrintStream cmdout, final File historyFile,
- final Completer completer) throws IOException {
+ final Completer completer, final Function<String, String> docHelper) throws IOException {
TerminalFactory.registerFlavor(Flavor.WINDOWS, isCygwin()? JJSUnixTerminal::new : JJSWindowsTerminal::new);
TerminalFactory.registerFlavor(Flavor.UNIX, JJSUnixTerminal::new);
in = new ConsoleReader(cmdin, cmdout);
@@ -58,6 +62,7 @@
in.setHistory(history = new FileHistory(historyFile));
in.addCompleter(completer);
Runtime.getRuntime().addShutdownHook(new Thread((Runnable)this::saveHistory));
+ bind(DOCUMENTATION_SHORTCUT, (ActionListener)evt -> showDocumentation(docHelper));
}
String readLine(final String prompt) throws IOException {
@@ -138,4 +143,34 @@
private static boolean isCygwin() {
return System.getenv("SHELL") != null;
}
+
+ private void bind(String shortcut, Object action) {
+ KeyMap km = in.getKeys();
+ for (int i = 0; i < shortcut.length(); i++) {
+ final Object value = km.getBound(Character.toString(shortcut.charAt(i)));
+ if (value instanceof KeyMap) {
+ km = (KeyMap) value;
+ } else {
+ km.bind(shortcut.substring(i), action);
+ }
+ }
+ }
+
+ private void showDocumentation(final Function<String, String> docHelper) {
+ final String buffer = in.getCursorBuffer().buffer.toString();
+ final int cursor = in.getCursorBuffer().cursor;
+ final String doc = docHelper.apply(buffer.substring(0, cursor));
+ try {
+ if (doc != null) {
+ in.println();
+ in.println(doc);
+ in.redrawLine();
+ in.flush();
+ } else {
+ in.beep();
+ }
+ } catch (IOException ex) {
+ throw new IllegalStateException(ex);
+ }
+ }
}
--- a/nashorn/src/jdk.scripting.nashorn.shell/share/classes/jdk/nashorn/tools/jjs/Main.java Mon Dec 14 17:38:56 2015 +0100
+++ b/nashorn/src/jdk.scripting.nashorn.shell/share/classes/jdk/nashorn/tools/jjs/Main.java Wed Dec 16 16:42:03 2015 +0530
@@ -25,6 +25,9 @@
package jdk.nashorn.tools.jjs;
+import static jdk.nashorn.internal.runtime.ScriptRuntime.UNDEFINED;
+
+import java.awt.Desktop;
import java.awt.GraphicsEnvironment;
import java.io.BufferedReader;
import java.io.File;
@@ -33,15 +36,21 @@
import java.io.IOException;
import java.io.OutputStream;
import java.io.PrintWriter;
+import java.net.URI;
+import java.util.concurrent.Callable;
import java.util.function.Consumer;
+import java.util.function.Function;
import jdk.internal.jline.console.completer.Completer;
import jdk.internal.jline.console.UserInterruptException;
import jdk.nashorn.api.scripting.NashornException;
import jdk.nashorn.internal.objects.Global;
+import jdk.nashorn.internal.objects.NativeJava;
import jdk.nashorn.internal.runtime.Context;
+import jdk.nashorn.internal.runtime.NativeJavaPackage;
import jdk.nashorn.internal.runtime.JSType;
import jdk.nashorn.internal.runtime.Property;
import jdk.nashorn.internal.runtime.ScriptEnvironment;
+import jdk.nashorn.internal.runtime.ScriptFunction;
import jdk.nashorn.internal.runtime.ScriptRuntime;
import jdk.nashorn.tools.Shell;
@@ -109,7 +118,32 @@
final PropertiesHelper propsHelper = new PropertiesHelper(env._classpath);
final NashornCompleter completer = new NashornCompleter(context, global, this, propsHelper);
- try (final Console in = new Console(System.in, System.out, HIST_FILE, completer)) {
+ try (final Console in = new Console(System.in, System.out, HIST_FILE, completer,
+ str -> {
+ try {
+ final Object res = context.eval(global, str, global, "<shell>");
+ if (res != null && res != UNDEFINED) {
+ // Special case Java types: show the javadoc for the class.
+ if (NativeJava.isType(UNDEFINED, res)) {
+ final String typeName = NativeJava.typeName(UNDEFINED, res).toString();
+ final String url = typeName.replace('.', '/').replace('$', '.') + ".html";
+ openBrowserForJavadoc(url);
+ } else if (res instanceof NativeJavaPackage) {
+ final String pkgName = ((NativeJavaPackage)res).getName();
+ final String url = pkgName.replace('.', '/') + "/package-summary.html";
+ openBrowserForJavadoc(url);
+ } else if (res instanceof ScriptFunction) {
+ return ((ScriptFunction)res).getDocumentation();
+ }
+
+ // FIXME: better than toString for other cases?
+ return JSType.toString(res);
+ }
+ } catch (Exception ignored) {
+ }
+ return null;
+ })) {
+
if (globalChanged) {
Context.setGlobal(global);
}
@@ -164,7 +198,7 @@
try {
final Object res = context.eval(global, source, global, "<shell>");
- if (res != ScriptRuntime.UNDEFINED) {
+ if (res != UNDEFINED) {
err.println(toString(res, global));
}
} catch (final Exception exp) {
@@ -218,7 +252,7 @@
final PrintWriter err, final boolean doe) {
try {
final Object res = context.eval(global, source, global, "<shell>");
- if (res != ScriptRuntime.UNDEFINED) {
+ if (res != UNDEFINED) {
err.println(JSType.toString(res));
}
} catch (final Exception e) {
@@ -228,4 +262,15 @@
}
}
}
+
+ // FIXME: needs to be changed to use javase 9 docs later
+ private static String JAVADOC_BASE = "http://download.java.net/jdk9/docs/api/";
+
+ private static void openBrowserForJavadoc(String relativeUrl) {
+ try {
+ final URI uri = new URI(JAVADOC_BASE + relativeUrl);
+ Desktop.getDesktop().browse(uri);
+ } catch (Exception ignored) {
+ }
+ }
}
--- a/nashorn/src/jdk.scripting.nashorn/share/classes/jdk/nashorn/internal/objects/NativeObject.java Mon Dec 14 17:38:56 2015 +0100
+++ b/nashorn/src/jdk.scripting.nashorn/share/classes/jdk/nashorn/internal/objects/NativeObject.java Wed Dec 16 16:42:03 2015 +0530
@@ -148,7 +148,8 @@
* @param buf external buffer - should be a nio ByteBuffer
* @return the 'obj' object
*/
- @Function(attributes = Attribute.NOT_ENUMERABLE, where = Where.CONSTRUCTOR)
+ @Function(attributes = Attribute.NOT_ENUMERABLE, where = Where.CONSTRUCTOR,
+ documentation = "sets ByteBuffer to hold indexed data (nashorn extension)")
public static ScriptObject setIndexedPropertiesToExternalArrayData(final Object self, final Object obj, final Object buf) {
Global.checkObject(obj);
final ScriptObject sobj = (ScriptObject)obj;
@@ -168,7 +169,8 @@
* @param obj object to get prototype from
* @return the prototype of an object
*/
- @Function(attributes = Attribute.NOT_ENUMERABLE, where = Where.CONSTRUCTOR)
+ @Function(attributes = Attribute.NOT_ENUMERABLE, where = Where.CONSTRUCTOR,
+ documentation = "returns the prototype of the specified object")
public static Object getPrototypeOf(final Object self, final Object obj) {
if (obj instanceof ScriptObject) {
return ((ScriptObject)obj).getProto();
@@ -195,7 +197,8 @@
* @param proto prototype object to be used
* @return object whose prototype is set
*/
- @Function(attributes = Attribute.NOT_ENUMERABLE, where = Where.CONSTRUCTOR)
+ @Function(attributes = Attribute.NOT_ENUMERABLE, where = Where.CONSTRUCTOR,
+ documentation = "sets the prototype of the given object (ES6)")
public static Object setPrototypeOf(final Object self, final Object obj, final Object proto) {
if (obj instanceof ScriptObject) {
((ScriptObject)obj).setPrototypeOf(proto);
@@ -216,7 +219,8 @@
* @param prop property descriptor
* @return property descriptor
*/
- @Function(attributes = Attribute.NOT_ENUMERABLE, where = Where.CONSTRUCTOR)
+ @Function(attributes = Attribute.NOT_ENUMERABLE, where = Where.CONSTRUCTOR,
+ documentation = "returns a property descriptor for an own property (not inherited property)")
public static Object getOwnPropertyDescriptor(final Object self, final Object obj, final Object prop) {
if (obj instanceof ScriptObject) {
final String key = JSType.toString(prop);
@@ -240,7 +244,8 @@
* @param obj object to query for property names
* @return array of property names
*/
- @Function(attributes = Attribute.NOT_ENUMERABLE, where = Where.CONSTRUCTOR)
+ @Function(attributes = Attribute.NOT_ENUMERABLE, where = Where.CONSTRUCTOR,
+ documentation = "returns an array of all properties (enumerable or not) found directly on the given object")
public static ScriptObject getOwnPropertyNames(final Object self, final Object obj) {
if (obj instanceof ScriptObject) {
return new NativeArray(((ScriptObject)obj).getOwnKeys(true));
@@ -258,7 +263,8 @@
* @param obj object to query for property names
* @return array of property names
*/
- @Function(attributes = Attribute.NOT_ENUMERABLE, where = Where.CONSTRUCTOR)
+ @Function(attributes = Attribute.NOT_ENUMERABLE, where = Where.CONSTRUCTOR,
+ documentation = "returns an array of all symbol properties found directly on the given object (ES6)")
public static ScriptObject getOwnPropertySymbols(final Object self, final Object obj) {
if (obj instanceof ScriptObject) {
return new NativeArray(((ScriptObject)obj).getOwnSymbols(true));
@@ -276,7 +282,8 @@
* @param props properties to define
* @return object created
*/
- @Function(attributes = Attribute.NOT_ENUMERABLE, where = Where.CONSTRUCTOR)
+ @Function(attributes = Attribute.NOT_ENUMERABLE, where = Where.CONSTRUCTOR,
+ documentation = "creates a new object with the specified prototype object and properties")
public static ScriptObject create(final Object self, final Object proto, final Object props) {
if (proto != null) {
Global.checkObject(proto);
@@ -302,7 +309,8 @@
* @param attr attributes for property descriptor
* @return object
*/
- @Function(attributes = Attribute.NOT_ENUMERABLE, where = Where.CONSTRUCTOR)
+ @Function(attributes = Attribute.NOT_ENUMERABLE, where = Where.CONSTRUCTOR,
+ documentation = "adds an own property and/or update the attributes of an existing own property of an object")
public static ScriptObject defineProperty(final Object self, final Object obj, final Object prop, final Object attr) {
final ScriptObject sobj = Global.checkObject(obj);
sobj.defineOwnProperty(JSType.toPropertyKey(prop), attr, true);
@@ -317,7 +325,8 @@
* @param props properties
* @return object
*/
- @Function(attributes = Attribute.NOT_ENUMERABLE, where = Where.CONSTRUCTOR)
+ @Function(attributes = Attribute.NOT_ENUMERABLE, where = Where.CONSTRUCTOR,
+ documentation = "defines new or modifies existing properties directly on the given object")
public static ScriptObject defineProperties(final Object self, final Object obj, final Object props) {
final ScriptObject sobj = Global.checkObject(obj);
final Object propsObj = Global.toObject(props);
@@ -339,7 +348,8 @@
* @param obj object to seal
* @return sealed object
*/
- @Function(attributes = Attribute.NOT_ENUMERABLE, where = Where.CONSTRUCTOR)
+ @Function(attributes = Attribute.NOT_ENUMERABLE, where = Where.CONSTRUCTOR,
+ documentation = "prevents new properties from being added to the given object and marks existing properties as non-configurable")
public static Object seal(final Object self, final Object obj) {
if (obj instanceof ScriptObject) {
return ((ScriptObject)obj).seal();
@@ -358,7 +368,8 @@
* @param obj object to freeze
* @return frozen object
*/
- @Function(attributes = Attribute.NOT_ENUMERABLE, where = Where.CONSTRUCTOR)
+ @Function(attributes = Attribute.NOT_ENUMERABLE, where = Where.CONSTRUCTOR,
+ documentation = "prevents new properties from being added to the given object and prevents existing properties from being removed or re-configured")
public static Object freeze(final Object self, final Object obj) {
if (obj instanceof ScriptObject) {
return ((ScriptObject)obj).freeze();
@@ -376,7 +387,8 @@
* @param obj object, for which to set the internal extensible property to false
* @return object
*/
- @Function(attributes = Attribute.NOT_ENUMERABLE, where = Where.CONSTRUCTOR)
+ @Function(attributes = Attribute.NOT_ENUMERABLE, where = Where.CONSTRUCTOR,
+ documentation = "prevents new properties from ever being added to the given object")
public static Object preventExtensions(final Object self, final Object obj) {
if (obj instanceof ScriptObject) {
return ((ScriptObject)obj).preventExtensions();
@@ -394,7 +406,8 @@
* @param obj check whether an object is sealed
* @return true if sealed, false otherwise
*/
- @Function(attributes = Attribute.NOT_ENUMERABLE, where = Where.CONSTRUCTOR)
+ @Function(attributes = Attribute.NOT_ENUMERABLE, where = Where.CONSTRUCTOR,
+ documentation = "tells if an object is sealed or not")
public static boolean isSealed(final Object self, final Object obj) {
if (obj instanceof ScriptObject) {
return ((ScriptObject)obj).isSealed();
@@ -412,7 +425,8 @@
* @param obj check whether an object
* @return true if object is frozen, false otherwise
*/
- @Function(attributes = Attribute.NOT_ENUMERABLE, where = Where.CONSTRUCTOR)
+ @Function(attributes = Attribute.NOT_ENUMERABLE, where = Where.CONSTRUCTOR,
+ documentation = "tells if an object is fronzen or not")
public static boolean isFrozen(final Object self, final Object obj) {
if (obj instanceof ScriptObject) {
return ((ScriptObject)obj).isFrozen();
@@ -430,7 +444,8 @@
* @param obj check whether an object is extensible
* @return true if object is extensible, false otherwise
*/
- @Function(attributes = Attribute.NOT_ENUMERABLE, where = Where.CONSTRUCTOR)
+ @Function(attributes = Attribute.NOT_ENUMERABLE, where = Where.CONSTRUCTOR,
+ documentation = "tells if an object is extensible or not")
public static boolean isExtensible(final Object self, final Object obj) {
if (obj instanceof ScriptObject) {
return ((ScriptObject)obj).isExtensible();
@@ -448,7 +463,8 @@
* @param obj object from which to extract keys
* @return array of keys in object
*/
- @Function(attributes = Attribute.NOT_ENUMERABLE, where = Where.CONSTRUCTOR)
+ @Function(attributes = Attribute.NOT_ENUMERABLE, where = Where.CONSTRUCTOR,
+ documentation = "returns an array of the given object's own enumerable properties")
public static ScriptObject keys(final Object self, final Object obj) {
if (obj instanceof ScriptObject) {
final ScriptObject sobj = (ScriptObject)obj;
@@ -471,7 +487,7 @@
* @param value value of object to be instantiated
* @return the new NativeObject
*/
- @Constructor
+ @Constructor(documentation = "creates a new script object or converts given value as a script object")
public static Object construct(final boolean newObj, final Object self, final Object value) {
final JSType type = JSType.ofNoFunction(value);
@@ -505,7 +521,8 @@
* @param self self reference
* @return ToString of object
*/
- @Function(attributes = Attribute.NOT_ENUMERABLE)
+ @Function(attributes = Attribute.NOT_ENUMERABLE,
+ documentation = "returns a string representing of this object")
public static String toString(final Object self) {
return ScriptRuntime.builtinObjectToString(self);
}
@@ -558,7 +575,8 @@
* @param v property to check for
* @return true if property exists in object
*/
- @Function(attributes = Attribute.NOT_ENUMERABLE)
+ @Function(attributes = Attribute.NOT_ENUMERABLE,
+ documentation = "tells whether this object has the specified property or not")
public static boolean hasOwnProperty(final Object self, final Object v) {
// Convert ScriptObjects to primitive with String.class hint
// but no need to convert other primitives to string.
@@ -575,7 +593,8 @@
* @param v v prototype object to check against
* @return true if object is prototype of v
*/
- @Function(attributes = Attribute.NOT_ENUMERABLE)
+ @Function(attributes = Attribute.NOT_ENUMERABLE,
+ documentation = "tests for this object in another object's prototype chain")
public static boolean isPrototypeOf(final Object self, final Object v) {
if (!(v instanceof ScriptObject)) {
return false;
@@ -601,7 +620,8 @@
* @param v property to check if enumerable
* @return true if property is enumerable
*/
- @Function(attributes = Attribute.NOT_ENUMERABLE)
+ @Function(attributes = Attribute.NOT_ENUMERABLE,
+ documentation = "tells whether the given property is enumerable or not")
public static boolean propertyIsEnumerable(final Object self, final Object v) {
final String str = JSType.toString(v);
final Object obj = Global.toObject(self);
@@ -676,7 +696,8 @@
* @param source the source object whose properties are bound to the target
* @return the target object after property binding
*/
- @Function(attributes = Attribute.NOT_ENUMERABLE, where = Where.CONSTRUCTOR)
+ @Function(attributes = Attribute.NOT_ENUMERABLE, where = Where.CONSTRUCTOR,
+ documentation = "binds the source object's properties to the target object (nashorn extension)")
public static Object bindProperties(final Object self, final Object target, final Object source) {
// target object has to be a ScriptObject
final ScriptObject targetObj = Global.checkObject(target);
--- a/nashorn/src/jdk.scripting.nashorn/share/classes/jdk/nashorn/internal/objects/annotations/Constructor.java Mon Dec 14 17:38:56 2015 +0100
+++ b/nashorn/src/jdk.scripting.nashorn/share/classes/jdk/nashorn/internal/objects/annotations/Constructor.java Wed Dec 16 16:42:03 2015 +0530
@@ -48,4 +48,9 @@
* arity.
*/
public int arity() default -2;
+
+ /**
+ * @return the documentation string for this constructor.
+ */
+ public String documentation() default "";
}
--- a/nashorn/src/jdk.scripting.nashorn/share/classes/jdk/nashorn/internal/objects/annotations/Function.java Mon Dec 14 17:38:56 2015 +0100
+++ b/nashorn/src/jdk.scripting.nashorn/share/classes/jdk/nashorn/internal/objects/annotations/Function.java Wed Dec 16 16:42:03 2015 +0530
@@ -60,4 +60,9 @@
* @return where this function lives.
*/
public Where where() default Where.PROTOTYPE;
+
+ /**
+ * @return return the documentation string for this function.
+ */
+ public String documentation() default "";
}
--- a/nashorn/src/jdk.scripting.nashorn/share/classes/jdk/nashorn/internal/runtime/ScriptFunction.java Mon Dec 14 17:38:56 2015 +0100
+++ b/nashorn/src/jdk.scripting.nashorn/share/classes/jdk/nashorn/internal/runtime/ScriptFunction.java Wed Dec 16 16:42:03 2015 +0530
@@ -646,6 +646,24 @@
}
/**
+ * Get the documentation for this function
+ *
+ * @return the documentation
+ */
+ public final String getDocumentation() {
+ return data.getDocumentation();
+ }
+
+ /**
+ * Set the documentation for this function
+ *
+ * @param doc documentation String for this function
+ */
+ public final void setDocumentation(final String doc) {
+ data.setDocumentation(doc);
+ }
+
+ /**
* Get the name for this function
*
* @return the name
--- a/nashorn/src/jdk.scripting.nashorn/share/classes/jdk/nashorn/internal/runtime/ScriptFunctionData.java Mon Dec 14 17:38:56 2015 +0100
+++ b/nashorn/src/jdk.scripting.nashorn/share/classes/jdk/nashorn/internal/runtime/ScriptFunctionData.java Wed Dec 16 16:42:03 2015 +0530
@@ -70,6 +70,9 @@
// value, the function might still be capable of receiving variable number of arguments, see isVariableArity.
private int arity;
+ // this may be null, if not available
+ private String documentation;
+
/**
* A pair of method handles used for generic invoker and constructor. Field is volatile as it can be initialized by
* multiple threads concurrently, but we still tolerate a race condition in it as all values stored into it are
@@ -118,6 +121,10 @@
return arity;
}
+ final String getDocumentation() {
+ return documentation != null? documentation : toSource();
+ }
+
final boolean isVariableArity() {
return (flags & IS_VARIABLE_ARITY) != 0;
}
@@ -137,6 +144,15 @@
this.arity = arity;
}
+ /**
+ * Used from nasgen generated code.
+ *
+ * @param doc documentation for this function
+ */
+ void setDocumentation(final String doc) {
+ this.documentation = doc;
+ }
+
CompiledFunction bind(final CompiledFunction originalInv, final ScriptFunction fn, final Object self, final Object[] args) {
final MethodHandle boundInvoker = bindInvokeHandle(originalInv.createComposableInvoker(), fn, self, args);