aboutsummaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorManu Sridharan2013-08-16 12:55:14 (EDT)
committerMark Macdonald2013-09-30 11:38:23 (EDT)
commit931be5b50cff124f819acfdd80f1cf24ee358862 (patch)
treeb74b8a716160174b3037c83008923fcc3b338955
parent76f9278efbe5d6d0c6d8f020461c96ab9ca1c266 (diff)
downloadorg.eclipse.orion.client-931be5b50cff124f819acfdd80f1cf24ee358862.zip
org.eclipse.orion.client-931be5b50cff124f819acfdd80f1cf24ee358862.tar.gz
org.eclipse.orion.client-931be5b50cff124f819acfdd80f1cf24ee358862.tar.bz2
Better content assist support for node.js.
We detect node.js files as those with the following jslint directive: /*jslint node:true */ For such files, content assist will now suggest appropriate globals. Furthermore, if a built-in node.js module is included via a require() call, content assist can make appropriate suggestions for the variable holding the return value of the call. The index file nodeIndex.js is still incomplete and a work in progress. Also includes related cleanup and improvement to various parts of the content assist code. Finally, add indexFileParsingTests.(html/js), with separate regression tests for our code for parsing index files. Signed-off-by: Manu Sridharan <msridhar@us.ibm.com>
-rw-r--r--bundles/org.eclipse.orion.client.ui/web/js-tests/esprima/esprimaJsContentAssistTests.js55
-rw-r--r--bundles/org.eclipse.orion.client.ui/web/js-tests/esprima/indexFileParsingTests.html29
-rw-r--r--bundles/org.eclipse.orion.client.ui/web/js-tests/esprima/indexFileParsingTests.js159
-rw-r--r--bundles/org.eclipse.orion.client.ui/web/plugins/esprima/esprimaJsContentAssist.js4
-rw-r--r--bundles/org.eclipse.orion.client.ui/web/plugins/esprima/indexFiles/browserIndex.js42
-rw-r--r--bundles/org.eclipse.orion.client.ui/web/plugins/esprima/indexFiles/nodeIndex.js1717
-rw-r--r--bundles/org.eclipse.orion.client.ui/web/plugins/esprima/typeEnvironment.js189
-rw-r--r--bundles/org.eclipse.orion.client.ui/web/plugins/esprima/typeInference.js43
-rw-r--r--bundles/org.eclipse.orion.client.ui/web/plugins/esprima/typeUtils.js6
-rw-r--r--bundles/org.eclipse.orion.client.ui/web/plugins/esprima/typesFromIndexFile.js382
10 files changed, 2300 insertions, 326 deletions
diff --git a/bundles/org.eclipse.orion.client.ui/web/js-tests/esprima/esprimaJsContentAssistTests.js b/bundles/org.eclipse.orion.client.ui/web/js-tests/esprima/esprimaJsContentAssistTests.js
index 7b21d81..ff4df8b 100644
--- a/bundles/org.eclipse.orion.client.ui/web/js-tests/esprima/esprimaJsContentAssistTests.js
+++ b/bundles/org.eclipse.orion.client.ui/web/js-tests/esprima/esprimaJsContentAssistTests.js
@@ -2320,10 +2320,10 @@ define([
tests["test node1"] = function() {
var results = computeContentAssist(
"/*jslint node:true*/\n" +
- "mod", "mod"
+ "glo", "glo"
);
return testProposals(results, [
- ["module", "module : Global"]
+ ["global", "global : Global"]
]);
};
@@ -2340,17 +2340,17 @@ define([
tests["test node3"] = function() {
var results = computeContentAssist(
"/*jslint browser:false node:true*/\n" +
- "mod", "mod"
+ "glo", "glo"
);
return testProposals(results, [
- ["module", "module : Global"]
+ ["global", "global : Global"]
]);
};
tests["test node4"] = function() {
var results = computeContentAssist(
"/*jslint node:false*/\n" +
- "mod", "mod"
+ "glo", "glo"
);
return testProposals(results, []);
};
@@ -2372,7 +2372,7 @@ define([
tests["test node6"] = function() {
var results = computeContentAssist(
"/*jslint node: xxx true*/\n" +
- "mod", "mod"
+ "glo", "glo"
);
return testProposals(results, []);
};
@@ -2381,7 +2381,7 @@ define([
tests["test node7"] = function() {
var results = computeContentAssist(
"/*jslint node xxxx : true*/\n" +
- "mod", "mod"
+ "glo", "glo"
);
return testProposals(results, []);
};
@@ -2389,10 +2389,10 @@ define([
// configuration from .scripted
tests["test node8"] = function() {
var results = computeContentAssist(
- "mod", "mod", null, {options:{node:true}}
+ "glo", "glo", null, {options:{node:true}}
);
return testProposals(results, [
- ["module", "module : Global"]
+ ["global", "global : Global"]
]);
};
@@ -2400,7 +2400,7 @@ define([
tests["test node9"] = function() {
var results = computeContentAssist(
"/*jslint node:false*/\n" +
- "mod", "mod", null, {options:{node:true}}
+ "glo", "glo", null, {options:{node:true}}
);
return testProposals(results, []);
};
@@ -2409,10 +2409,10 @@ define([
tests["test node10"] = function() {
var results = computeContentAssist(
"/*jslint node:true*/\n" +
- "mod", "mod", null, {options:{browser:true}}
+ "glo", "glo", null, {options:{browser:true}}
);
return testProposals(results, [
- ["module", "module : Global"]
+ ["global", "global : Global"]
]);
};
@@ -2427,6 +2427,37 @@ define([
]);
};
+ tests["test node12"] = function() {
+ var results = computeContentAssist(
+ "/*jslint node:true*/\n" +
+ "process.", ""
+ );
+ // just testing that we don't crash
+ return results.then(function () {});
+ };
+
+ tests["test node13"] = function() {
+ var results = computeContentAssist(
+ "/*jslint node:true*/\n" +
+ "var x = require(\"fs\");\n" +
+ "x.o", "o"
+ );
+ return testProposals(results, [
+ ["open(path, flags, mode, callback)", "open(path, flags, mode, callback) : undefined"],
+ ["openSync(path, flags, [mode])", "openSync(path, flags, [mode]) : Number"]
+ ]);
+ };
+
+ tests["test node14"] = function() {
+ var results = computeContentAssist(
+ "/*jslint node:true*/\n" +
+ "process.stdout.wr", "wr"
+ );
+ return testProposals(results, [
+ ["write(chunk, [encoding], [callback])", "write(chunk, [encoding], [callback]) : Boolean"]
+ ]);
+ };
+
////////////////////////////////////////
// jsdoc tests
diff --git a/bundles/org.eclipse.orion.client.ui/web/js-tests/esprima/indexFileParsingTests.html b/bundles/org.eclipse.orion.client.ui/web/js-tests/esprima/indexFileParsingTests.html
new file mode 100644
index 0000000..29c92d7
--- /dev/null
+++ b/bundles/org.eclipse.orion.client.ui/web/js-tests/esprima/indexFileParsingTests.html
@@ -0,0 +1,29 @@
+<!DOCTYPE HTML PUBLIC "-//W3C//DTD HTML 4.01 Transitional//EN"
+ "http://www.w3.org/TR/html4/loose.dtd">
+<html>
+<head>
+ <script src="../../orion/plugin.js"></script>
+ <script src="../../requirejs/require.js"></script>
+ <script>
+ /*global window require */
+ require({
+ baseUrl: '../..',
+ paths: {
+ "scriptedLogger": "plugins/esprima/scriptedLogger",
+ text: 'requirejs/text',
+ i18n: 'requirejs/i18n',
+ domReady: 'requirejs/domReady'
+ }
+ });
+ window.onload = function() {
+ require(["orion/test","js-tests/esprima/indexFileParsingTests"],
+ function(test, jsTests) {
+ test.run(jsTests);
+ });
+ };
+ </script>
+</head>
+<body>
+ <h1>Unit tests for index file parsing</h1>
+</body>
+</html> \ No newline at end of file
diff --git a/bundles/org.eclipse.orion.client.ui/web/js-tests/esprima/indexFileParsingTests.js b/bundles/org.eclipse.orion.client.ui/web/js-tests/esprima/indexFileParsingTests.js
new file mode 100644
index 0000000..4198666
--- /dev/null
+++ b/bundles/org.eclipse.orion.client.ui/web/js-tests/esprima/indexFileParsingTests.js
@@ -0,0 +1,159 @@
+/*******************************************************************************
+ * @license
+ * Copyright (c) 2012 VMware, Inc. All Rights Reserved.
+ * Copyright (c) 2013 IBM Corporation.
+ *
+ * THIS FILE IS PROVIDED UNDER THE TERMS OF THE ECLIPSE PUBLIC LICENSE
+ * ("AGREEMENT"). ANY USE, REPRODUCTION OR DISTRIBUTION OF THIS FILE
+ * CONSTITUTES RECIPIENTS ACCEPTANCE OF THE AGREEMENT.
+ * You can obtain a current copy of the Eclipse Public License from
+ * http://www.opensource.org/licenses/eclipse-1.0.php
+ *
+ * Contributors:
+ * Andrew Eisenberg (VMware) - initial API and implementation
+ * Manu Sridharan (IBM) - Various improvements
+ ******************************************************************************/
+
+/*global define esprima console setTimeout doctrine*/
+define(["plugins/esprima/typesFromIndexFile", "plugins/esprima/typeEnvironment", "orion/assert"], function(mTypes, typeEnv, assert) {
+
+ //////////////////////////////////////////////////////////
+ // helpers
+ //////////////////////////////////////////////////////////
+
+ function testSig(ternSig, closureSig, constructorName) {
+ assert.equal(mTypes.ternSig2ClosureSig(ternSig, constructorName), closureSig, "Bad conversion");
+ }
+
+ function testType(type, name, expectedTypeInfo) {
+ var result = mTypes.parseType(type, name);
+ assert.equal(JSON.stringify(result.typeInfo), JSON.stringify(expectedTypeInfo), "Bad parse");
+ }
+
+ function makeEnvironmentOptionsFromIndex(indexDataArr) {
+ var options = {};
+ options.buffer = "";
+ options.uid = "0";
+ options.indexData = indexDataArr;
+ return options;
+ }
+
+ function checkEnvironment(indexData, cb) {
+ var options = makeEnvironmentOptionsFromIndex([indexData]);
+ var envPromise = typeEnv.createEnvironment(options);
+ var result = envPromise.then(cb);
+ return result;
+ }
+
+ //////////////////////////////////////////////////////////
+ // tests
+ //////////////////////////////////////////////////////////
+
+ var tests = {};
+
+ tests["test basic 1"] = function() {
+ testSig("fn() -> String", "function():String");
+ };
+
+ tests["test basic 2"] = function() {
+ testSig("fn(m: Number, n?: Number) -> Boolean", "function(m:Number,n:Number=):Boolean");
+ };
+
+ tests["test constructor 1"] = function() {
+ // TODO is this really right? comma after Fizz?
+ testSig("fn()", "function(new:Fizz):Fizz", "Fizz");
+ };
+
+ tests["test array of functions"] = function() {
+ testSig("fn() -> [fn()]", "function():Array");
+ };
+ tests["test callback"] = function() {
+ testSig("fn(cb: fn(x: Object) -> Object) -> Number", "function(cb:function(x:Object):Object):Number");
+ };
+
+ tests["test callback 2"] = function() {
+ testSig("fn(cb: fn(x: Object) -> Object) -> fn(y: Object) -> Object",
+ "function(cb:function(x:Object):Object):function(y:Object):Object");
+ };
+
+ tests["test callback 3"] = function() {
+ testSig("fn(cb: fn(x: Object) -> fn(z: Object) -> Object, cb2: fn(p: Object) -> String) -> fn(y: Object) -> Object",
+ "function(cb:function(x:Object):function(z:Object):Object,cb2:function(p:Object):String):function(y:Object):Object");
+ };
+
+ tests["test type 1"] = function() {
+ var type = {
+ fizz: "String",
+ bazz: "Number"
+ };
+ var expected = {
+ "Foo": {
+ "fizz": {
+ "_typeObj": {
+ "type": "NameExpression",
+ "name": "String"
+ }
+ },
+ "bazz": {
+ "_typeObj": {
+ "type": "NameExpression",
+ "name": "Number"
+ }
+ },
+ "$$isBuiltin": true
+ }
+ };
+ testType(type, "Foo", expected);
+ };
+
+ tests["test type reference with dot"] = function() {
+ var type = {
+ foo: "+x.OtherType"
+ };
+ var expected = {
+ "Foo": {
+ "foo": {
+ "_typeObj": {
+ "type": "NameExpression",
+ "name": "x..OtherType..prototype"
+ }
+ },
+ "$$isBuiltin": true
+ }
+ };
+ testType(type, "Foo", expected);
+ };
+
+ tests["test environment basic"] = function() {
+ var index = {
+ bizz: "String"
+ };
+ return checkEnvironment(index, function (env) {
+ assert.equal("String", env.lookupTypeObj("bizz").name, "bad environment");
+ });
+ };
+
+ tests["test environment prototype"] = function() {
+ var index = {
+ Fizz: {
+ "!type": "fn(p:String)",
+ prototype: {
+ x: "String"
+ }
+ },
+ Buzz: {
+ "!type": "fn(p:String)",
+ prototype: {
+ "!proto": "Fizz.prototype",
+ y: "String"
+ }
+ }
+ };
+ return checkEnvironment(index, function (env) {
+ var t = env.lookupTypeObj("x", "Fizz..prototype");
+ // TODO figureout out what to check here!!!
+ });
+ };
+
+ return tests;
+});
diff --git a/bundles/org.eclipse.orion.client.ui/web/plugins/esprima/esprimaJsContentAssist.js b/bundles/org.eclipse.orion.client.ui/web/plugins/esprima/esprimaJsContentAssist.js
index cd7257f..53a8e75 100644
--- a/bundles/org.eclipse.orion.client.ui/web/plugins/esprima/esprimaJsContentAssist.js
+++ b/bundles/org.eclipse.orion.client.ui/web/plugins/esprima/esprimaJsContentAssist.js
@@ -219,7 +219,7 @@ define(["plugins/esprima/esprimaVisitor", "plugins/esprima/typeEnvironment", "pl
}
function createInferredProposals(targetTypeName, env, completionKind, prefix, replaceStart, proposals, relevance) {
- var prop, propTypeObj, propName, res, type = env.getAllTypes()[targetTypeName], proto = type.$$proto;
+ var prop, propTypeObj, propName, res, type = env.lookupQualifiedType(targetTypeName), proto = type.$$proto;
if (!relevance) {
relevance = 100;
}
@@ -265,6 +265,8 @@ define(["plugins/esprima/esprimaVisitor", "plugins/esprima/typeEnvironment", "pl
}
if (proposalUtils.looselyMatches(prefix, propName)) {
propTypeObj = type[prop].typeObj;
+ // if propTypeObj is a reference to a function type,
+ // extract the actual function type
if ((env._allTypes[propTypeObj.name]) && (env._allTypes[propTypeObj.name].$$fntype)) {
propTypeObj = env._allTypes[propTypeObj.name].$$fntype;
}
diff --git a/bundles/org.eclipse.orion.client.ui/web/plugins/esprima/indexFiles/browserIndex.js b/bundles/org.eclipse.orion.client.ui/web/plugins/esprima/indexFiles/browserIndex.js
index 92aa1fc..25214c2 100644
--- a/bundles/org.eclipse.orion.client.ui/web/plugins/esprima/indexFiles/browserIndex.js
+++ b/bundles/org.eclipse.orion.client.ui/web/plugins/esprima/indexFiles/browserIndex.js
@@ -34,6 +34,10 @@ define("plugins/esprima/indexFiles/browserIndex", [], function () {
"!type": "fn(data: String)"
}
},
+ "WebSocket_obj": {
+ "!type": "fn(url: String, protocols: String)",
+ "prototype": "WebSocket"
+ },
"EventHandler": {
"!proto": "Object"
},
@@ -70,7 +74,11 @@ define("plugins/esprima/indexFiles/browserIndex", [], function () {
"status": "Number",
"statusText": "String"
},
- "Worker": {
+ "XHR_obj": {
+ "!type": "fn()",
+ "prototype": "XMLHttpRequest"
+ },
+ "Worker_proto": {
"!proto": "Object",
"terminate": {
"!type": "fn()"
@@ -82,6 +90,10 @@ define("plugins/esprima/indexFiles/browserIndex", [], function () {
"!type": "fn()"
}
},
+ "Worker_obj": {
+ "!type": "fn(url: String)",
+ "prototype": "Worker_proto"
+ },
"HTMLOptionElement": {
"!proto": "HTMLElement"
},
@@ -121,6 +133,10 @@ define("plugins/esprima/indexFiles/browserIndex", [], function () {
"!type": "fn()"
}
},
+ "Event_obj": {
+ "!type": "fn(type: String)",
+ "prototype": "Event"
+ },
"MediaQueryList": {
"!proto": "Object"
},
@@ -299,6 +315,10 @@ define("plugins/esprima/indexFiles/browserIndex", [], function () {
"!type": "fn(namespace: String) -> Boolean"
}
},
+ "Node_obj": {
+ "!type": "fn()",
+ "prototype": "Node"
+ },
"NodeList": {
"!proto": "Object",
"item": "Node",
@@ -957,20 +977,10 @@ define("plugins/esprima/indexFiles/browserIndex", [], function () {
"Option": {
"!type": "fn(text?: String, value?: Object, defaultSelected?: Boolean, selected?: Boolean)"
},
- "Worker": {
- "!type": "fn(url: String)"
- },
- "XMLHttpRequest": {
- "!type": "fn()"
- },
- "WebSocket": {
- "!type": "fn(url: String, protocols: String)"
- },
- "Event": {
- "!type": "fn(type: String)"
- },
- "Node": {
- "!type": "fn()"
- }
+ "Worker": "Worker_obj",
+ "XMLHttpRequest": "XHR_obj",
+ "WebSocket": "WebSocket_obj",
+ "Event": "Event_obj",
+ "Node": "Node_obj"
};
}); \ No newline at end of file
diff --git a/bundles/org.eclipse.orion.client.ui/web/plugins/esprima/indexFiles/nodeIndex.js b/bundles/org.eclipse.orion.client.ui/web/plugins/esprima/indexFiles/nodeIndex.js
index 06a4f9a..8f128ed 100644
--- a/bundles/org.eclipse.orion.client.ui/web/plugins/esprima/indexFiles/nodeIndex.js
+++ b/bundles/org.eclipse.orion.client.ui/web/plugins/esprima/indexFiles/nodeIndex.js
@@ -11,137 +11,1704 @@
* Contributors:
* Manu Sridharan (IBM) - Initial API and implementation
******************************************************************************/
-
-// this file was generated by a script from the model in types.js
-/*global define */
+ /*global define */
define("plugins/esprima/indexFiles/nodeIndex", [], function () {
return {
- "!name": "nodejs",
+ "console": "Console",
+ "process": "Process",
"!define": {
- "Process": {
- "!proto": "Object",
- "on": {
- "!type": "fn(kind: String, callback: fn())"
+ "assert": {
+ "fail": {
+ "!type": "fn(actual: Object, expected: Object, message: Object, operator: Object)"
+ },
+ "assert": {
+ "!type": "fn(value: Object, message: Object)"
+ },
+ "ok": {
+ "!type": "fn(value: Object, message?: Object)"
+ },
+ "equal": {
+ "!type": "fn(actual: Object, expected: Object, message?: Object)"
+ },
+ "notEqual": {
+ "!type": "fn(actual: Object, expected: Object, message?: Object)"
+ },
+ "deepEqual": {
+ "!type": "fn(actual: Object, expected: Object, message?: Object)"
+ },
+ "notDeepEqual": {
+ "!type": "fn(actual: Object, expected: Object, message?: Object)"
+ },
+ "strictEqual": {
+ "!type": "fn(actual: Object, expected: Object, message?: Object)"
+ },
+ "notStrictEqual": {
+ "!type": "fn(actual: Object, expected: Object, message?: Object)"
+ },
+ "throws": {
+ "!type": "fn(block: Object, error?: Object, message?: Object)"
+ },
+ "doesNotThrow": {
+ "!type": "fn(block: Object, message?: Object)"
+ },
+ "ifError": {
+ "!type": "fn(value: Object)"
+ }
+ },
+ "buffer": {
+ "INSPECT_MAX_BYTES": {
+ "!type": "Object"
+ },
+ "Buffer": {
+ "!type": "fn()",
+ "prototype": {
+ "write": {
+ "!type": "fn(string: Object, offset?: Object, length?: Object, encoding?: Object)"
+ },
+ "toString": {
+ "!type": "fn(encoding?: Object, start?: Object, end?: Object)"
+ },
+ "toJSON": {
+ "!type": "fn()"
+ },
+ "copy": {
+ "!type": "fn(targetBuffer: Object, targetStart?: Object, sourceStart?: Object, sourceEnd?: Object)"
+ },
+ "slice": {
+ "!type": "fn(start?: Object, end?: Object)"
+ },
+ "readUInt8": {
+ "!type": "fn(offset: Object, noAssert?: Object)"
+ },
+ "readUInt16LE": {
+ "!type": "fn(offset: Object, noAssert?: Object)"
+ },
+ "readUInt16BE": {
+ "!type": "fn(offset: Object, noAssert?: Object)"
+ },
+ "readUInt32LE": {
+ "!type": "fn(offset: Object, noAssert?: Object)"
+ },
+ "readUInt32BE": {
+ "!type": "fn(offset: Object, noAssert?: Object)"
+ },
+ "readInt8": {
+ "!type": "fn(offset: Object, noAssert?: Object)"
+ },
+ "readInt16LE": {
+ "!type": "fn(offset: Object, noAssert?: Object)"
+ },
+ "readInt16BE": {
+ "!type": "fn(offset: Object, noAssert?: Object)"
+ },
+ "readInt32LE": {
+ "!type": "fn(offset: Object, noAssert?: Object)"
+ },
+ "readInt32BE": {
+ "!type": "fn(offset: Object, noAssert?: Object)"
+ },
+ "readFloatLE": {
+ "!type": "fn(offset: Object, noAssert?: Object)"
+ },
+ "readFloatBE": {
+ "!type": "fn(offset: Object, noAssert?: Object)"
+ },
+ "readDoubleLE": {
+ "!type": "fn(offset: Object, noAssert?: Object)"
+ },
+ "readDoubleBE": {
+ "!type": "fn(offset: Object, noAssert?: Object)"
+ },
+ "writeUInt8": {
+ "!type": "fn(value: Object, offset: Object, noAssert?: Object)"
+ },
+ "writeUInt16LE": {
+ "!type": "fn(value: Object, offset: Object, noAssert?: Object)"
+ },
+ "writeUInt16BE": {
+ "!type": "fn(value: Object, offset: Object, noAssert?: Object)"
+ },
+ "writeUInt32LE": {
+ "!type": "fn(value: Object, offset: Object, noAssert?: Object)"
+ },
+ "writeUInt32BE": {
+ "!type": "fn(value: Object, offset: Object, noAssert?: Object)"
+ },
+ "writeInt8": {
+ "!type": "fn(value: Object, offset: Object, noAssert?: Object)"
+ },
+ "writeInt16LE": {
+ "!type": "fn(value: Object, offset: Object, noAssert?: Object)"
+ },
+ "writeInt16BE": {
+ "!type": "fn(value: Object, offset: Object, noAssert?: Object)"
+ },
+ "writeInt32LE": {
+ "!type": "fn(value: Object, offset: Object, noAssert?: Object)"
+ },
+ "writeInt32BE": {
+ "!type": "fn(value: Object, offset: Object, noAssert?: Object)"
+ },
+ "writeFloatLE": {
+ "!type": "fn(value: Object, offset: Object, noAssert?: Object)"
+ },
+ "writeFloatBE": {
+ "!type": "fn(value: Object, offset: Object, noAssert?: Object)"
+ },
+ "writeDoubleLE": {
+ "!type": "fn(value: Object, offset: Object, noAssert?: Object)"
+ },
+ "writeDoubleBE": {
+ "!type": "fn(value: Object, offset: Object, noAssert?: Object)"
+ },
+ "fill": {
+ "!type": "fn(value: Object, offset?: Object, end?: Object)"
+ },
+ "[index]": {
+ "!type": "Object"
+ },
+ "length": {
+ "!type": "Object"
+ }
+ }
+ },
+ "SlowBuffer": {
+ "!type": "fn()",
+ "prototype": {}
+ }
+ },
+ "child_process": {
+ "spawn": {
+ "!type": "fn(command: Object, args?: Object, options?: Object) -> ChildProcessobject"
+ },
+ "exec": {
+ "!type": "fn(command: Object, options: Object, callback: Object)"
+ },
+ "execFile": {
+ "!type": "fn(file: Object, args: Object, options: Object, callback: Object)"
+ },
+ "fork": {
+ "!type": "fn(modulePath: Object, args?: Object, options?: Object)"
+ },
+ "ChildProcess": {
+ "!type": "fn()",
+ "prototype": {
+ "kill": {
+ "!type": "fn(signal?: Object)"
+ },
+ "send": {
+ "!type": "fn(message: Object, sendHandle?: Object)"
+ },
+ "disconnect": {
+ "!type": "fn()"
+ },
+ "stdin": {
+ "!type": "Object"
+ },
+ "stdout": {
+ "!type": "Object"
+ },
+ "stderr": {
+ "!type": "Object"
+ },
+ "pid": {
+ "!type": "Object"
+ }
+ }
+ }
+ },
+ "cluster": {
+ "setupMaster": {
+ "!type": "fn(settings?: Object)"
+ },
+ "fork": {
+ "!type": "fn(env?: Object) -> Workerobject"
+ },
+ "disconnect": {
+ "!type": "fn(callback?: Object)"
+ },
+ "settings": {
+ "!type": "Object"
+ },
+ "isMaster": {
+ "!type": "Object"
+ },
+ "isWorker": {
+ "!type": "Object"
+ },
+ "worker": {
+ "!type": "Object"
+ },
+ "workers": {
+ "!type": "Object"
+ },
+ "Worker": {
+ "!type": "fn()",
+ "prototype": {
+ "send": {
+ "!type": "fn(message: Object, sendHandle?: Object)"
+ },
+ "kill": {
+ "!type": "fn(signal?: Object)"
+ },
+ "disconnect": {
+ "!type": "fn()"
+ },
+ "id": {
+ "!type": "Object"
+ },
+ "process": {
+ "!type": "Object"
+ },
+ "suicide": {
+ "!type": "Object"
+ }
+ }
+ }
+ },
+ "Console": {
+ "log": {
+ "!type": "fn(data?: Object, other?: Object)"
+ },
+ "info": {
+ "!type": "fn(data?: Object, other?: Object)"
+ },
+ "error": {
+ "!type": "fn(data?: Object, other?: Object)"
+ },
+ "warn": {
+ "!type": "fn(data?: Object, other?: Object)"
+ },
+ "dir": {
+ "!type": "fn(obj: Object)"
+ },
+ "time": {
+ "!type": "fn(label: Object)"
+ },
+ "timeEnd": {
+ "!type": "fn(label: Object)"
+ },
+ "trace": {
+ "!type": "fn(label: Object)"
+ },
+ "assert": {
+ "!type": "fn(expression: Object, message?: Object)"
+ }
+ },
+ "crypto": {
+ "getCiphers": {
+ "!type": "fn()"
+ },
+ "getHashes": {
+ "!type": "fn()"
+ },
+ "createCredentials": {
+ "!type": "fn(details: Object)"
+ },
+ "createHash": {
+ "!type": "fn(algorithm: Object)"
+ },
+ "createHmac": {
+ "!type": "fn(algorithm: Object, key: Object)"
+ },
+ "createCipher": {
+ "!type": "fn(algorithm: Object, password: Object)"
+ },
+ "createCipheriv": {
+ "!type": "fn(algorithm: Object, key: Object, iv: Object)"
+ },
+ "createDecipher": {
+ "!type": "fn(algorithm: Object, password: Object)"
+ },
+ "createDecipheriv": {
+ "!type": "fn(algorithm: Object, key: Object, iv: Object)"
+ },
+ "createSign": {
+ "!type": "fn(algorithm: Object)"
+ },
+ "createVerify": {
+ "!type": "fn(algorithm: Object)"
+ },
+ "createDiffieHellman": {
+ "!type": "fn(prime: Object, encoding?: Object)"
+ },
+ "getDiffieHellman": {
+ "!type": "fn(group_name: Object)"
+ },
+ "pbkdf2": {
+ "!type": "fn(password: Object, salt: Object, iterations: Object, keylen: Object, callback: Object)"
+ },
+ "pbkdf2Sync": {
+ "!type": "fn(password: Object, salt: Object, iterations: Object, keylen: Object)"
+ },
+ "randomBytes": {
+ "!type": "fn(size: Object, callback?: Object)"
+ },
+ "pseudoRandomBytes": {
+ "!type": "fn(size: Object, callback?: Object)"
+ },
+ "DEFAULT_ENCODING": {
+ "!type": "Object"
+ },
+ "Hash": {
+ "!type": "fn()",
+ "prototype": {
+ "update": {
+ "!type": "fn(data: Object, input_encoding?: Object)"
+ },
+ "digest": {
+ "!type": "fn(encoding?: Object)"
+ }
+ }
+ },
+ "Hmac": {
+ "!type": "fn()",
+ "prototype": {
+ "update": {
+ "!type": "fn(data: Object)"
+ },
+ "digest": {
+ "!type": "fn(encoding?: Object)"
+ }
+ }
+ },
+ "Cipher": {
+ "!type": "fn()",
+ "prototype": {
+ "update": {
+ "!type": "fn(data: Object, input_encoding?: Object, output_encoding?: Object)"
+ },
+ "final": {
+ "!type": "fn(output_encoding?: Object)"
+ },
+ "setAutoPadding": {
+ "!type": "fn(auto_padding: Object)"
+ }
+ }
+ },
+ "Decipher": {
+ "!type": "fn()",
+ "prototype": {
+ "update": {
+ "!type": "fn(data: Object, input_encoding?: Object, output_encoding?: Object)"
+ },
+ "final": {
+ "!type": "fn(output_encoding?: Object)"
+ },
+ "setAutoPadding": {
+ "!type": "fn(auto_padding: Object)"
+ }
+ }
+ },
+ "Sign": {
+ "!type": "fn()",
+ "prototype": {
+ "update": {
+ "!type": "fn(data: Object)"
+ },
+ "sign": {
+ "!type": "fn(private_key: Object, output_format?: Object)"
+ }
+ }
+ },
+ "Verify": {
+ "!type": "fn()",
+ "prototype": {
+ "update": {
+ "!type": "fn(data: Object)"
+ },
+ "verify": {
+ "!type": "fn(object: Object, signature: Object, signature_format?: Object)"
+ }
+ }
+ },
+ "DiffieHellman": {
+ "!type": "fn()",
+ "prototype": {
+ "generateKeys": {
+ "!type": "fn(encoding?: Object)"
+ },
+ "computeSecret": {
+ "!type": "fn(other_public_key: Object, input_encoding?: Object, output_encoding?: Object)"
+ },
+ "getPrime": {
+ "!type": "fn(encoding?: Object)"
+ },
+ "getGenerator": {
+ "!type": "fn(encoding?: Object)"
+ },
+ "getPublicKey": {
+ "!type": "fn(encoding?: Object)"
+ },
+ "getPrivateKey": {
+ "!type": "fn(encoding?: Object)"
+ },
+ "setPublicKey": {
+ "!type": "fn(public_key: Object, encoding?: Object)"
+ },
+ "setPrivateKey": {
+ "!type": "fn(private_key: Object, encoding?: Object)"
+ }
+ }
+ }
+ },
+ "dgram": {
+ "createSocket": {
+ "!type": "fn(type: Object, callback?: Object)"
+ },
+ "Socket": {
+ "!type": "fn()",
+ "prototype": {
+ "send": {
+ "!type": "fn(buf: Object, offset: Object, length: Object, port: Object, address: Object, callback?: Object)"
+ },
+ "bind": {
+ "!type": "fn(port: Object, address?: Object, callback?: Object)"
+ },
+ "close": {
+ "!type": "fn()"
+ },
+ "address": {
+ "!type": "fn()"
+ },
+ "setBroadcast": {
+ "!type": "fn(flag: Object)"
+ },
+ "setTTL": {
+ "!type": "fn(ttl: Object)"
+ },
+ "setMulticastTTL": {
+ "!type": "fn(ttl: Object)"
+ },
+ "setMulticastLoopback": {
+ "!type": "fn(flag: Object)"
+ },
+ "addMembership": {
+ "!type": "fn(multicastAddress: Object, multicastInterface?: Object)"
+ },
+ "dropMembership": {
+ "!type": "fn(multicastAddress: Object, multicastInterface?: Object)"
+ },
+ "unref": {
+ "!type": "fn()"
+ },
+ "ref": {
+ "!type": "fn()"
+ }
+ }
+ }
+ },
+ "dns": {
+ "lookup": {
+ "!type": "fn(domain: Object, family: Object, callback: Object)"
+ },
+ "resolve": {
+ "!type": "fn(domain: Object, rrtype: Object, callback: Object)"
+ },
+ "resolve4": {
+ "!type": "fn(domain: Object, callback: Object)"
+ },
+ "resolve6": {
+ "!type": "fn(domain: Object, callback: Object)"
+ },
+ "resolveMx": {
+ "!type": "fn(domain: Object, callback: Object)"
+ },
+ "resolveTxt": {
+ "!type": "fn(domain: Object, callback: Object)"
+ },
+ "resolveSrv": {
+ "!type": "fn(domain: Object, callback: Object)"
+ },
+ "resolveNs": {
+ "!type": "fn(domain: Object, callback: Object)"
+ },
+ "resolveCname": {
+ "!type": "fn(domain: Object, callback: Object)"
+ },
+ "reverse": {
+ "!type": "fn(ip: Object, callback: Object)"
+ }
+ },
+ "domain": {
+ "create": {
+ "!type": "fn() -> Domain"
+ },
+ "Domain": {
+ "!type": "fn()",
+ "prototype": {
+ "run": {
+ "!type": "fn(fn: Object)"
+ },
+ "add": {
+ "!type": "fn(emitter: Object)"
+ },
+ "remove": {
+ "!type": "fn(emitter: Object)"
+ },
+ "bind": {
+ "!type": "fn(callback: Object) -> Function"
+ },
+ "intercept": {
+ "!type": "fn(callback: Object) -> Function"
+ },
+ "enter": {
+ "!type": "fn()"
+ },
+ "exit": {
+ "!type": "fn()"
+ },
+ "dispose": {
+ "!type": "fn()"
+ },
+ "members": {
+ "!type": "Object"
+ }
+ }
+ }
+ },
+ "events": {
+ "EventEmitter": {
+ "!type": "fn()",
+ "prototype": {
+ "addListener": {
+ "!type": "fn(event: Object, listener: Object)"
+ },
+ "on": {
+ "!type": "fn(event: Object, listener: Object)"
+ },
+ "once": {
+ "!type": "fn(event: Object, listener: Object)"
+ },
+ "removeListener": {
+ "!type": "fn(event: Object, listener: Object)"
+ },
+ "removeAllListeners": {
+ "!type": "fn(event?: Object)"
+ },
+ "setMaxListeners": {
+ "!type": "fn(n: Object)"
+ },
+ "listeners": {
+ "!type": "fn(event: Object)"
+ },
+ "emit": {
+ "!type": "fn(event: Object, arg1?: Object, arg2?: Object, other?: Object)"
+ }
+ }
+ }
+ },
+ "fs": {
+ "rename": {
+ "!type": "fn(oldPath: Object, newPath: Object, callback: Object)"
+ },
+ "renameSync": {
+ "!type": "fn(oldPath: Object, newPath: Object)"
+ },
+ "ftruncate": {
+ "!type": "fn(fd: Object, len: Object, callback: Object)"
+ },
+ "ftruncateSync": {
+ "!type": "fn(fd: Object, len: Object)"
+ },
+ "truncate": {
+ "!type": "fn(path: Object, len: Object, callback: Object)"
+ },
+ "truncateSync": {
+ "!type": "fn(path: Object, len: Object)"
+ },
+ "chown": {
+ "!type": "fn(path: Object, uid: Object, gid: Object, callback: Object)"
+ },
+ "chownSync": {
+ "!type": "fn(path: Object, uid: Object, gid: Object)"
+ },
+ "fchown": {
+ "!type": "fn(fd: Object, uid: Object, gid: Object, callback: Object)"
+ },
+ "fchownSync": {
+ "!type": "fn(fd: Object, uid: Object, gid: Object)"
+ },
+ "lchown": {
+ "!type": "fn(path: Object, uid: Object, gid: Object, callback: Object)"
+ },
+ "lchownSync": {
+ "!type": "fn(path: Object, uid: Object, gid: Object)"
+ },
+ "chmod": {
+ "!type": "fn(path: Object, mode: Object, callback: Object)"
+ },
+ "chmodSync": {
+ "!type": "fn(path: Object, mode: Object)"
+ },
+ "fchmod": {
+ "!type": "fn(fd: Object, mode: Object, callback: Object)"
+ },
+ "fchmodSync": {
+ "!type": "fn(fd: Object, mode: Object)"
+ },
+ "lchmod": {
+ "!type": "fn(path: Object, mode: Object, callback: Object)"
+ },
+ "lchmodSync": {
+ "!type": "fn(path: Object, mode: Object)"
+ },
+ "stat": {
+ "!type": "fn(path: Object, callback: Object)"
+ },
+ "lstat": {
+ "!type": "fn(path: Object, callback: Object)"
+ },
+ "fstat": {
+ "!type": "fn(fd: Object, callback: Object)"
+ },
+ "statSync": {
+ "!type": "fn(path: Object)"
+ },
+ "lstatSync": {
+ "!type": "fn(path: Object)"
+ },
+ "fstatSync": {
+ "!type": "fn(fd: Object)"
+ },
+ "link": {
+ "!type": "fn(srcpath: Object, dstpath: Object, callback: Object)"
+ },
+ "linkSync": {
+ "!type": "fn(srcpath: Object, dstpath: Object)"
+ },
+ "symlink": {
+ "!type": "fn(srcpath: Object, dstpath: Object, type: Object, callback: Object)"
+ },
+ "symlinkSync": {
+ "!type": "fn(srcpath: Object, dstpath: Object, type?: Object)"
+ },
+ "readlink": {
+ "!type": "fn(path: Object, callback: Object)"
+ },
+ "readlinkSync": {
+ "!type": "fn(path: Object)"
+ },
+ "realpath": {
+ "!type": "fn(path: Object, cache: Object, callback: Object)"
+ },
+ "realpathSync": {
+ "!type": "fn(path: Object, cache?: Object)"
+ },
+ "unlink": {
+ "!type": "fn(path: Object, callback: Object)"
+ },
+ "unlinkSync": {
+ "!type": "fn(path: Object)"
+ },
+ "rmdir": {
+ "!type": "fn(path: Object, callback: Object)"
+ },
+ "rmdirSync": {
+ "!type": "fn(path: Object)"
+ },
+ "mkdir": {
+ "!type": "fn(path: Object, mode: Object, callback: Object)"
+ },
+ "mkdirSync": {
+ "!type": "fn(path: Object, mode?: Object)"
+ },
+ "readdir": {
+ "!type": "fn(path: Object, callback: Object)"
+ },
+ "readdirSync": {
+ "!type": "fn(path: Object)"
+ },
+ "close": {
+ "!type": "fn(fd: Object, callback: Object)"
+ },
+ "closeSync": {
+ "!type": "fn(fd: Object)"
+ },
+ "open": {
+ "!type": "fn(path: Object, flags: Object, mode: Object, callback: Object)"
+ },
+ "openSync": {
+ "!type": "fn(path: Object, flags: Object, mode?: Object) -> Number"
+ },
+ "utimes": {
+ "!type": "fn(path: Object, atime: Object, mtime: Object)"
+ },
+ "utimesSync": {
+ "!type": "fn(path: Object, atime: Object, mtime: Object)"
+ },
+ "futimes": {
+ "!type": "fn(fd: Object, atime: Object, mtime: Object)"
+ },
+ "futimesSync": {
+ "!type": "fn(fd: Object, atime: Object, mtime: Object)"
+ },
+ "fsync": {
+ "!type": "fn(fd: Object, callback: Object)"
+ },
+ "fsyncSync": {
+ "!type": "fn(fd: Object)"
+ },
+ "write": {
+ "!type": "fn(fd: Object, buffer: Object, offset: Object, length: Object, position: Object, callback: Object)"
+ },
+ "writeSync": {
+ "!type": "fn(fd: Object, buffer: Object, offset: Object, length: Object, position: Object)"
+ },
+ "read": {
+ "!type": "fn(fd: Object, buffer: Object, offset: Object, length: Object, position: Object, callback: Object)"
+ },
+ "readSync": {
+ "!type": "fn(fd: Object, buffer: Object, offset: Object, length: Object, position: Object)"
+ },
+ "readFile": {
+ "!type": "fn(filename: Object, options: Object, callback: Object)"
+ },
+ "readFileSync": {
+ "!type": "fn(filename: Object, options?: Object)"
+ },
+ "writeFile": {
+ "!type": "fn(filename: Object, data: Object, options: Object, callback: Object)"
+ },
+ "writeFileSync": {
+ "!type": "fn(filename: Object, data: Object, options?: Object)"
+ },
+ "appendFile": {
+ "!type": "fn(filename: Object, data: Object, options: Object, callback: Object)"
+ },
+ "appendFileSync": {
+ "!type": "fn(filename: Object, data: Object, options?: Object)"
+ },
+ "watchFile": {
+ "!type": "fn(filename: Object, options: Object, listener: Object)"
+ },
+ "unwatchFile": {
+ "!type": "fn(filename: Object, listener?: Object)"
+ },
+ "watch": {
+ "!type": "fn(filename: Object, options?: Object, listener?: Object)"
+ },
+ "exists": {
+ "!type": "fn(path: Object, callback: Object)"
+ },
+ "existsSync": {
+ "!type": "fn(path: Object)"
+ },
+ "createReadStream": {
+ "!type": "fn(path: Object, options?: Object)"
+ },
+ "createWriteStream": {
+ "!type": "fn(path: Object, options?: Object)"
+ },
+ "Stats": {
+ "!type": "fn()",
+ "prototype": {}
+ },
+ "ReadStream": {
+ "!type": "fn()",
+ "prototype": {}
+ },
+ "WriteStream": {
+ "!type": "fn()",
+ "prototype": {
+ "bytesWritten": {
+ "!type": "Object"
+ }
+ }
+ },
+ "FSWatcher": {
+ "!type": "fn()",
+ "prototype": {
+ "close": {
+ "!type": "fn()"
+ }
+ }
+ }
+ },
+ "http": {
+ "createServer": {
+ "!type": "fn(requestListener?: Object)"
+ },
+ "createClient": {
+ "!type": "fn(port?: Object, host?: Object)"
+ },
+ "request": {
+ "!type": "fn(options: Object, callback: Object)"
+ },
+ "get": {
+ "!type": "fn(options: Object, callback: Object)"
+ },
+ "STATUS_CODES": {
+ "!type": "Object"
+ },
+ "globalAgent": {
+ "!type": "Object"
+ },
+ "IncomingMessage": {
+ "!type": "Object"
+ },
+ "Server": {
+ "!type": "fn()",
+ "prototype": {
+ "listen": {
+ "!type": "fn(handle: Object, callback?: Object)"
+ },
+ "close": {
+ "!type": "fn(callback?: Object)"
+ },
+ "setTimeout": {
+ "!type": "fn(msecs: Object, callback: Object)"
+ },
+ "maxHeadersCount": {
+ "!type": "Object"
+ },
+ "timeout": {
+ "!type": "Object"
+ }
+ }
+ },
+ "ServerResponse": {
+ "!type": "fn()",
+ "prototype": {
+ "writeContinue": {
+ "!type": "fn()"
+ },
+ "writeHead": {
+ "!type": "fn(statusCode: Object, reasonPhrase?: Object, headers?: Object)"
+ },
+ "setTimeout": {
+ "!type": "fn(msecs: Object, callback: Object)"
+ },
+ "setHeader": {
+ "!type": "fn(name: Object, value: Object)"
+ },
+ "getHeader": {
+ "!type": "fn(name: Object)"
+ },
+ "removeHeader": {
+ "!type": "fn(name: Object)"
+ },
+ "write": {
+ "!type": "fn(chunk: Object, encoding?: Object)"
+ },
+ "addTrailers": {
+ "!type": "fn(headers: Object)"
+ },
+ "end": {
+ "!type": "fn(data?: Object, encoding?: Object)"
+ },
+ "statusCode": {
+ "!type": "Object"
+ },
+ "headersSent": {
+ "!type": "Object"
+ },
+ "sendDate": {
+ "!type": "Object"
+ }
+ }
+ },
+ "Agent": {
+ "!type": "fn()",
+ "prototype": {
+ "maxSockets": {
+ "!type": "Object"
+ },
+ "sockets": {
+ "!type": "Object"
+ },
+ "requests": {
+ "!type": "Object"
+ }
+ }
+ },
+ "ClientRequest": {
+ "!type": "fn()",
+ "prototype": {
+ "write": {
+ "!type": "fn(chunk: Object, encoding?: Object)"
+ },
+ "end": {
+ "!type": "fn(data?: Object, encoding?: Object)"
+ },
+ "abort": {
+ "!type": "fn()"
+ },
+ "setTimeout": {
+ "!type": "fn(timeout: Object, callback?: Object)"
+ },
+ "setNoDelay": {
+ "!type": "fn(noDelay?: Object)"
+ },
+ "setSocketKeepAlive": {
+ "!type": "fn(enable?: Object, initialDelay?: Object)"
+ }
+ }
+ }
+ },
+ "https": {
+ "createServer": {
+ "!type": "fn(options: Object, requestListener?: Object)"
+ },
+ "request": {
+ "!type": "fn(options: Object, callback: Object)"
},
+ "get": {
+ "!type": "fn(options: Object, callback: Object)"
+ },
+ "globalAgent": {
+ "!type": "Object"
+ },
+ "Server": {
+ "!type": "fn()",
+ "prototype": {}
+ },
+ "Agent": {
+ "!type": "fn()",
+ "prototype": {}
+ }
+ },
+ "net": {
+ "createServer": {
+ "!type": "fn(options?: Object, connectionListener?: Object)"
+ },
+ "connect": {
+ "!type": "fn(path: Object, connectListener?: Object)"
+ },
+ "createConnection": {
+ "!type": "fn(path: Object, connectListener?: Object)"
+ },
+ "isIP": {
+ "!type": "fn(input: Object)"
+ },
+ "isIPv4": {
+ "!type": "fn(input: Object)"
+ },
+ "isIPv6": {
+ "!type": "fn(input: Object)"
+ },
+ "Server": {
+ "!type": "fn()",
+ "prototype": {
+ "listen": {
+ "!type": "fn(handle: Object, callback?: Object)"
+ },
+ "close": {
+ "!type": "fn(callback?: Object)"
+ },
+ "address": {
+ "!type": "fn()"
+ },
+ "unref": {
+ "!type": "fn()"
+ },
+ "ref": {
+ "!type": "fn()"
+ },
+ "getConnections": {
+ "!type": "fn(callback: Object)"
+ },
+ "maxConnections": {
+ "!type": "Object"
+ },
+ "connections": {
+ "!type": "Object"
+ }
+ }
+ },
+ "Socket": {
+ "!type": "fn()",
+ "prototype": {
+ "Socket": {
+ "!type": "fn(options?: Object)"
+ },
+ "connect": {
+ "!type": "fn(path: Object, connectListener?: Object)"
+ },
+ "setEncoding": {
+ "!type": "fn(encoding?: Object)"
+ },
+ "write": {
+ "!type": "fn(data: Object, encoding?: Object, callback?: Object)"
+ },
+ "end": {
+ "!type": "fn(data?: Object, encoding?: Object)"
+ },
+ "destroy": {
+ "!type": "fn()"
+ },
+ "pause": {
+ "!type": "fn()"
+ },
+ "resume": {
+ "!type": "fn()"
+ },
+ "setTimeout": {
+ "!type": "fn(timeout: Object, callback?: Object)"
+ },
+ "setNoDelay": {
+ "!type": "fn(noDelay?: Object)"
+ },
+ "setKeepAlive": {
+ "!type": "fn(enable?: Object, initialDelay?: Object)"
+ },
+ "address": {
+ "!type": "fn()"
+ },
+ "unref": {
+ "!type": "fn()"
+ },
+ "ref": {
+ "!type": "fn()"
+ },
+ "bufferSize": {
+ "!type": "Object"
+ },
+ "remoteAddress": {
+ "!type": "Object"
+ },
+ "remotePort": {
+ "!type": "Object"
+ },
+ "localAddress": {
+ "!type": "Object"
+ },
+ "localPort": {
+ "!type": "Object"
+ },
+ "bytesRead": {
+ "!type": "Object"
+ },
+ "bytesWritten": {
+ "!type": "Object"
+ }
+ }
+ }
+ },
+ "os": {
+ "tmpdir": {
+ "!type": "fn()"
+ },
+ "endianness": {
+ "!type": "fn()"
+ },
+ "hostname": {
+ "!type": "fn()"
+ },
+ "type": {
+ "!type": "fn()"
+ },
+ "platform": {
+ "!type": "fn()"
+ },
+ "arch": {
+ "!type": "fn()"
+ },
+ "release": {
+ "!type": "fn()"
+ },
+ "uptime": {
+ "!type": "fn()"
+ },
+ "loadavg": {
+ "!type": "fn()"
+ },
+ "totalmem": {
+ "!type": "fn()"
+ },
+ "freemem": {
+ "!type": "fn()"
+ },
+ "cpus": {
+ "!type": "fn()"
+ },
+ "networkInterfaces": {
+ "!type": "fn()"
+ },
+ "EOL": {
+ "!type": "Object"
+ }
+ },
+ "path": {
+ "normalize": {
+ "!type": "fn(p: Object)"
+ },
+ "join": {
+ "!type": "fn(path1?: Object, path2?: Object, other?: Object)"
+ },
+ "resolve": {
+ "!type": "fn(from: Object, to: Object)"
+ },
+ "relative": {
+ "!type": "fn(from: Object, to: Object)"
+ },
+ "dirname": {
+ "!type": "fn(p: Object)"
+ },
+ "basename": {
+ "!type": "fn(p: Object, ext?: Object)"
+ },
+ "extname": {
+ "!type": "fn(p: Object)"
+ },
+ "sep": {
+ "!type": "Object"
+ },
+ "delimiter": {
+ "!type": "Object"
+ }
+ },
+ "Process": {
"abort": {
"!type": "fn()"
},
- "stdout": "Stream",
- "stderr": "Stream",
- "stdin": "Stream",
- "argv": "Array",
- "execPath": "String",
"chdir": {
- "!type": "fn(directory: String)"
+ "!type": "fn(directory: Object)"
},
"cwd": {
- "!type": "fn() -> String"
+ "!type": "fn()"
+ },
+ "exit": {
+ "!type": "fn(code?: Object)"
},
- "env": "Object",
"getgid": {
- "!type": "fn() -> Number"
+ "!type": "fn()"
},
"setgid": {
- "!type": "fn(id: Number)"
+ "!type": "fn(id: Object)"
},
"getuid": {
- "!type": "fn() -> Number"
+ "!type": "fn()"
},
"setuid": {
- "!type": "fn(id: Number)"
+ "!type": "fn(id: Object)"
+ },
+ "getgroups": {
+ "!type": "fn()"
+ },
+ "setgroups": {
+ "!type": "fn(groups: Object)"
+ },
+ "initgroups": {
+ "!type": "fn(user: Object, extra_group: Object)"
},
- "version": "String",
- "versions": "Object",
- "config": "Object",
"kill": {
- "!type": "fn(pid: Number, signal?: Number)"
+ "!type": "fn(pid: Object, signal?: Object)"
},
- "pid": "Number",
- "title": "String",
- "arch": "String",
- "platform": "String",
"memoryUsage": {
- "!type": "fn() -> Object"
+ "!type": "fn()"
},
"nextTick": {
- "!type": "fn(callback: fn())"
+ "!type": "fn(callback: Object)"
},
"umask": {
- "!type": "fn(mask?: Number)"
+ "!type": "fn(mask?: Object)"
},
"uptime": {
- "!type": "fn() -> Number"
+ "!type": "fn()"
},
"hrtime": {
- "!type": "fn() -> Array"
+ "!type": "fn()"
+ },
+ "stdout": {
+ "!type": "+stream.Writable"
+ },
+ "stderr": {
+ "!type": "Object"
+ },
+ "stdin": {
+ "!type": "Object"
+ },
+ "argv": {
+ "!type": "Object"
+ },
+ "execPath": {
+ "!type": "Object"
+ },
+ "execArgv": {
+ "!type": "Object"
+ },
+ "env": {
+ "!type": "Object"
+ },
+ "version": {
+ "!type": "Object"
+ },
+ "versions": {
+ "!type": "Object"
+ },
+ "config": {
+ "!type": "Object"
+ },
+ "pid": {
+ "!type": "Object"
+ },
+ "title": {
+ "!type": "Object"
+ },
+ "arch": {
+ "!type": "Object"
+ },
+ "platform": {
+ "!type": "Object"
+ },
+ "maxTickDepth": {
+ "!type": "Object"
}
},
- "Stream": {
- "!proto": "Object",
- "data": {
- "!type": "fn(data: Object)"
+ "punycode": {
+ "decode": {
+ "!type": "fn(string: Object)"
},
- "error": {
- "!type": "fn(exception: Object)"
+ "encode": {
+ "!type": "fn(string: Object)"
},
- "close": {
- "!type": "fn()"
+ "toUnicode": {
+ "!type": "fn(domain: Object)"
+ },
+ "toASCII": {
+ "!type": "fn(domain: Object)"
},
- "readable": "Boolean",
- "setEncoding": {
- "!type": "fn(encoding?: String)"
+ "ucs2": {
+ "!type": "Object"
},
- "pause": {
+ "version": {
+ "!type": "Object"
+ }
+ },
+ "querystring": {
+ "stringify": {
+ "!type": "fn(obj: Object, sep?: Object, eq?: Object)"
+ },
+ "parse": {
+ "!type": "fn(str: Object, sep?: Object, eq?: Object, options?: Object)"
+ },
+ "escape": {
+ "!type": "Object"
+ },
+ "unescape": {
+ "!type": "Object"
+ }
+ },
+ "readline": {
+ "createInterface": {
+ "!type": "fn(options: Object)"
+ },
+ "Interface": {
+ "!type": "fn()",
+ "prototype": {
+ "setPrompt": {
+ "!type": "fn(prompt: Object, length: Object)"
+ },
+ "prompt": {
+ "!type": "fn(preserveCursor?: Object)"
+ },
+ "question": {
+ "!type": "fn(query: Object, callback: Object)"
+ },
+ "pause": {
+ "!type": "fn()"
+ },
+ "resume": {
+ "!type": "fn()"
+ },
+ "close": {
+ "!type": "fn()"
+ },
+ "write": {
+ "!type": "fn(data: Object, key?: Object)"
+ }
+ }
+ }
+ },
+ "repl": {
+ "start": {
+ "!type": "fn(options: Object)"
+ }
+ },
+ "stream": {
+ "Readable": {
+ "!type": "fn()",
+ "prototype": {
+ "read": {
+ "!type": "fn(size?: Object) -> String"
+ },
+ "setEncoding": {
+ "!type": "fn(encoding: Object)"
+ },
+ "resume": {
+ "!type": "fn()"
+ },
+ "pause": {
+ "!type": "fn()"
+ },
+ "pipe": {
+ "!type": "fn(destination: Object, options?: Object)"
+ },
+ "unpipe": {
+ "!type": "fn(destination?: Object)"
+ },
+ "unshift": {
+ "!type": "fn(chunk: Object)"
+ },
+ "wrap": {
+ "!type": "fn(stream: Object)"
+ }
+ }
+ },
+ "Writable": {
+ "!type": "fn()",
+ "prototype": {
+ "write": {
+ "!type": "fn(chunk: Object, encoding?: Object, callback?: Object) -> Boolean"
+ },
+ "end": {
+ "!type": "fn(chunk?: Object, encoding?: Object, callback?: Object)"
+ }
+ }
+ },
+ "Duplex": {
+ "!type": "fn()",
+ "prototype": {}
+ },
+ "Transform": {
+ "!type": "fn()",
+ "prototype": {}
+ }
+ },
+ "string_decoder": {
+ "StringDecoder": {
+ "!type": "fn()",
+ "prototype": {
+ "write": {
+ "!type": "fn(buffer: Object)"
+ },
+ "end": {
+ "!type": "fn()"
+ }
+ }
+ }
+ },
+ "timers": {
+ "setTimeout": {
+ "!type": "fn(callback: Object, delay: Object, arg?: Object, other?: Object)"
+ },
+ "clearTimeout": {
+ "!type": "fn(timeoutId: Object)"
+ },
+ "setInterval": {
+ "!type": "fn(callback: Object, delay: Object, arg?: Object, other?: Object)"
+ },
+ "clearInterval": {
+ "!type": "fn(intervalId: Object)"
+ },
+ "unref": {
"!type": "fn()"
},
- "resume": {
+ "ref": {
"!type": "fn()"
},
- "pipe": {
- "!type": "fn(destination: Object, options?: Object)"
+ "setImmediate": {
+ "!type": "fn(callback: Object, arg?: Object, other?: Object)"
},
- "drain": {
+ "clearImmediate": {
+ "!type": "fn(immediateId: Object)"
+ }
+ },
+ "tls": {
+ "getCiphers": {
"!type": "fn()"
},
- "writable": "Boolean",
- "write": {
- "!type": "fn(buffer?: Object)"
+ "createServer": {
+ "!type": "fn(options: Object, secureConnectionListener?: Object)"
},
- "end": {
- "!type": "fn(string?: String, encoding?: String)"
+ "connect": {
+ "!type": "fn(port: Object, host?: Object, options?: Object, callback?: Object)"
},
- "destroy": {
- "!type": "fn()"
+ "createSecurePair": {
+ "!type": "fn(credentials?: Object, isServer?: Object, requestCert?: Object, rejectUnauthorized?: Object)"
},
- "destroySoon": {
- "!type": "fn()"
+ "SLAB_BUFFER_SIZE": {
+ "!type": "Object"
+ },
+ "SecurePair": {
+ "!type": "fn()",
+ "prototype": {}
+ },
+ "Server": {
+ "!type": "fn()",
+ "prototype": {
+ "listen": {
+ "!type": "fn(port: Object, host?: Object, callback?: Object)"
+ },
+ "close": {
+ "!type": "fn()"
+ },
+ "address": {
+ "!type": "fn()"
+ },
+ "addContext": {
+ "!type": "fn(hostname: Object, credentials: Object)"
+ },
+ "maxConnections": {
+ "!type": "Object"
+ },
+ "connections": {
+ "!type": "Object"
+ }
+ }
+ },
+ "CryptoStream": {
+ "!type": "fn()",
+ "prototype": {
+ "bytesWritten": {
+ "!type": "Object"
+ }
+ }
+ },
+ "CleartextStream": {
+ "!type": "fn()",
+ "prototype": {
+ "getPeerCertificate": {
+ "!type": "fn()"
+ },
+ "getCipher": {
+ "!type": "fn()"
+ },
+ "address": {
+ "!type": "fn()"
+ },
+ "authorized": {
+ "!type": "Object"
+ },
+ "authorizationError": {
+ "!type": "Object"
+ },
+ "remoteAddress": {
+ "!type": "Object"
+ },
+ "remotePort": {
+ "!type": "Object"
+ }
+ }
+ }
+ },
+ "tty": {
+ "isatty": {
+ "!type": "fn(fd: Object)"
+ },
+ "setRawMode": {
+ "!type": "fn(mode: Object)"
+ },
+ "ReadStream": {
+ "!type": "fn()",
+ "prototype": {
+ "setRawMode": {
+ "!type": "fn(mode: Object)"
+ },
+ "isRaw": {
+ "!type": "Object"
+ }
+ }
+ },
+ "WriteStream": {
+ "!type": "fn()",
+ "prototype": {
+ "columns": {
+ "!type": "Object"
+ },
+ "rows": {
+ "!type": "Object"
+ }
+ }
+ }
+ },
+ "url": {
+ "parse": {
+ "!type": "fn(urlStr: Object, parseQueryString?: Object, slashesDenoteHost?: Object)"
+ },
+ "format": {
+ "!type": "fn(urlObj: Object)"
+ },
+ "resolve": {
+ "!type": "fn(from: Object, to: Object)"
}
},
- "Module": {}
+ "util": {
+ "format": {
+ "!type": "fn(format: Object, other?: Object)"
+ },
+ "debug": {
+ "!type": "fn(string: Object)"
+ },
+ "error": {
+ "!type": "fn(other?: Object)"
+ },
+ "puts": {
+ "!type": "fn(other?: Object)"
+ },
+ "print": {
+ "!type": "fn(other?: Object)"
+ },
+ "log": {
+ "!type": "fn(string: Object)"
+ },
+ "inspect": {
+ "!type": "fn(object: Object, options?: Object)"
+ },
+ "isArray": {
+ "!type": "fn(object: Object)"
+ },
+ "isRegExp": {
+ "!type": "fn(object: Object)"
+ },
+ "isDate": {
+ "!type": "fn(object: Object)"
+ },
+ "isError": {
+ "!type": "fn(object: Object)"
+ },
+ "pump": {
+ "!type": "fn(readableStream: Object, writableStream: Object, callback?: Object)"
+ },
+ "inherits": {
+ "!type": "fn(constructor: Object, superConstructor: Object)"
+ }
+ },
+ "vm": {
+ "runInThisContext": {
+ "!type": "fn(code: Object, filename?: Object)"
+ },
+ "runInNewContext": {
+ "!type": "fn(code: Object, sandbox?: Object, filename?: Object)"
+ },
+ "runInContext": {
+ "!type": "fn(code: Object, context: Object, filename?: Object)"
+ },
+ "createContext": {
+ "!type": "fn(initSandbox?: Object)"
+ },
+ "createScript": {
+ "!type": "fn(code: Object, filename?: Object)"
+ },
+ "Script": {
+ "!type": "fn()",
+ "prototype": {
+ "runInThisContext": {
+ "!type": "fn()"
+ },
+ "runInNewContext": {
+ "!type": "fn(sandbox?: Object)"
+ }
+ }
+ }
+ },
+ "zlib": {
+ "createGzip": {
+ "!type": "fn(options?: Object)"
+ },
+ "createGunzip": {
+ "!type": "fn(options?: Object)"
+ },
+ "createDeflate": {
+ "!type": "fn(options?: Object)"
+ },
+ "createInflate": {
+ "!type": "fn(options?: Object)"
+ },
+ "createDeflateRaw": {
+ "!type": "fn(options?: Object)"
+ },
+ "createInflateRaw": {
+ "!type": "fn(options?: Object)"
+ },
+ "createUnzip": {
+ "!type": "fn(options?: Object)"
+ },
+ "deflate": {
+ "!type": "fn(buf: Object, callback: Object)"
+ },
+ "deflateRaw": {
+ "!type": "fn(buf: Object, callback: Object)"
+ },
+ "gzip": {
+ "!type": "fn(buf: Object, callback: Object)"
+ },
+ "gunzip": {
+ "!type": "fn(buf: Object, callback: Object)"
+ },
+ "inflate": {
+ "!type": "fn(buf: Object, callback: Object)"
+ },
+ "inflateRaw": {
+ "!type": "fn(buf: Object, callback: Object)"
+ },
+ "unzip": {
+ "!type": "fn(buf: Object, callback: Object)"
+ },
+ "Zlib": {
+ "!type": "fn()",
+ "prototype": {
+ "flush": {
+ "!type": "fn(callback: Object)"
+ },
+ "reset": {
+ "!type": "fn()"
+ }
+ }
+ },
+ "Gzip": {
+ "!type": "fn()",
+ "prototype": {}
+ },
+ "Gunzip": {
+ "!type": "fn()",
+ "prototype": {}
+ },
+ "Deflate": {
+ "!type": "fn()",
+ "prototype": {}
+ },
+ "Inflate": {
+ "!type": "fn()",
+ "prototype": {}
+ },
+ "DeflateRaw": {
+ "!type": "fn()",
+ "prototype": {}
+ },
+ "InflateRaw": {
+ "!type": "fn()",
+ "prototype": {}
+ },
+ "Unzip": {
+ "!type": "fn()",
+ "prototype": {}
+ }
+ }
},
+ "!name": "node",
"this": "<top>",
- "Buffer": "Object",
- "console": "Object",
- "module": "<top>",
- "process": "Process",
+ "global": "<top>",
+ "buffer": "+Buffer",
"require": {
- "!type": "fn(module: String) -> Object"
+ "!type": "fn(name: String) -> Object"
},
- "clearInterval": {
- "!type": "fn(t: Number)"
+ "__filename": "String",
+ "__dirname": "String",
+ "module": "Object",
+ "exports": "Object",
+ "setTimeout": {
+ "!type": "fn(cb: Object, ms: Number) -> Object"
},
"clearTimeout": {
- "!type": "fn(t: Number)"
+ "!type": "fn(t: Object)"
},
"setInterval": {
- "!type": "fn(callback: Function, ms: Number) -> Number"
+ "!type": "fn(cb: Object, ms: Number) -> Object"
},
- "setTimeout": {
- "!type": "fn(callback: Function, ms: Number) -> Number"
- },
- "global": "<top>",
- "querystring": "String",
- "__filename": "String",
- "__dirname": "String"
+ "clearInterval": {
+ "!type": "fn(t: Object)"
+ }
};
}); \ No newline at end of file
diff --git a/bundles/org.eclipse.orion.client.ui/web/plugins/esprima/typeEnvironment.js b/bundles/org.eclipse.orion.client.ui/web/plugins/esprima/typeEnvironment.js
index a073150..05341c3 100644
--- a/bundles/org.eclipse.orion.client.ui/web/plugins/esprima/typeEnvironment.js
+++ b/bundles/org.eclipse.orion.client.ui/web/plugins/esprima/typeEnvironment.js
@@ -49,22 +49,32 @@ function(typeUtils, mTypes, Deferred) {
* Returns a promise that is resolved with the populated
* mTypes.Types object.
*/
- function initKnownTypes(globalObjName) {
- var types = new mTypes.Types();
- var result;
- if (globalObjName === "Window") {
- // browser code; load the browser module
- result = mTypes.addLibrary(types,"browser");
-
- } else if (globalObjName === "Module") {
- // node.js code
- result = mTypes.addLibrary(types,"node");
- } else {
- var d = new Deferred();
- d.resolve(types);
- result = d.promise;
- }
- return result;
+ function initKnownTypes(globalObjName, indexData) {
+ var coreLibPromise = mTypes.init();
+ var finalResult = coreLibPromise.then(function () {
+ var types = new mTypes.Types();
+ if (indexData) {
+ indexData.forEach(function (d) {
+ // mutates types
+ mTypes.addIndexData(d, types);
+ });
+ }
+ var result = null;
+ if (globalObjName === "Window") {
+ // browser code; load the browser module
+ result = mTypes.addLibrary(types,"browser");
+
+ } else if (globalObjName === "Module") {
+ // node.js code
+ result = mTypes.addLibrary(types,"node");
+ } else {
+ var d = new Deferred();
+ d.resolve(types);
+ result = d.promise;
+ }
+ return result;
+ });
+ return finalResult;
}
@@ -76,7 +86,7 @@ function(typeUtils, mTypes, Deferred) {
* Returns a promise that is resolved with the environment object.
*/
function createEnvironment(options) {
- var buffer = options.buffer, uid = options.uid, offset = options.offset, indexer = options.indexer, globalObjName = options.globalObjName;
+ var buffer = options.buffer, uid = options.uid, offset = options.offset, indexer = options.indexer, globalObjName = options.globalObjName, indexData = options.indexData;
if (!offset) {
offset = buffer.length+1;
}
@@ -104,6 +114,47 @@ function(typeUtils, mTypes, Deferred) {
return hash;
};
+ // translate function names on object into safe names
+ var swapper = function(name) {
+ switch (name) {
+ case "prototype":
+ return "$$prototype";
+ case "__proto__":
+ return "$$proto";
+ case "toString":
+ case "hasOwnProperty":
+ case "toLocaleString":
+ case "valueOf":
+ case "isProtoTypeOf":
+ case "propertyIsEnumerable":
+ return "$_$" + name;
+ default:
+ return name;
+ }
+ };
+
+ // routine to lookup a member name of a type that follows the prototype chain
+ // to search for the member
+ function innerLookup(env, name, type, includeDefinition) {
+ var res = type[name];
+
+ var proto = type.$$proto;
+ if (res) {
+ // found it. if includeDefinition is set, we return
+ // the Definition object res. if we were looking for
+ // a function type, then res represents the function
+ // type directly, so we return it. Otherwise, res
+ // is a Definition object, and we return its enclosed
+ // type object
+ return includeDefinition || name === '$$fntype' ? res : res.typeObj;
+ } else if (proto) {
+ return innerLookup(env, name, env.lookupQualifiedType(proto.typeObj.name), includeDefinition);
+ } else {
+ return null;
+ }
+ }
+
+
// prefix for generating local types
// need to add a unique id for each file so that types defined in dependencies don't clash with types
// defined locally
@@ -111,7 +162,7 @@ function(typeUtils, mTypes, Deferred) {
// uncomment to show names
// var namePrefix = typeUtils.GEN_NAME + (uid) + "~";
- var promise = initKnownTypes(globalObjName);
+ var promise = initKnownTypes(globalObjName, indexData);
var result = promise.then(function (knownTypes) {
return {
/** Each element is the type of the current scope, which is a key into the types array */
@@ -130,6 +181,8 @@ function(typeUtils, mTypes, Deferred) {
amdModule : null,
/** if this is a wrapped commonjs module, then the value of this property is the 'define' call expression */
commonjsModule : null,
+ /** is this a node.js module? */
+ nodeJSModule: globalObjName === "Module",
/** the indexer for thie content assist invocation. Used to track down dependencies */
indexer: indexer,
/** the offset of content assist invocation */
@@ -269,6 +322,10 @@ function(typeUtils, mTypes, Deferred) {
return "Function";
} else if (inferredTypeObj.type === 'ArrayType') {
return "Array";
+ } else if (inferredTypeObj.type === 'TypeApplication') {
+ return inferredTypeObj.expression.name;
+ } else if (inferredTypeObj.type === 'UndefinedLiteral') {
+ return "Object";
}
} else {
// grab topmost scope
@@ -399,51 +456,38 @@ function(typeUtils, mTypes, Deferred) {
}
return defn;
},
-
+
+ /**
+ * lookup a qualified type name a..b..c. '..' is used to
+ * separate members, to avoid confusion with the use of '.'
+ * in names for constructors.
+ * returns the type itself (the object containing information
+ * on members), rather than a type object with the type's name
+ */
+ lookupQualifiedType : function(name, includeDefinition) {
+ var scopeNames = name.split("..");
+ var targetType = this._allTypes[scopeNames[0]];
+ for (var i = 1; i < scopeNames.length; i++) {
+ var typeObj = innerLookup(this, swapper(scopeNames[i]), targetType, includeDefinition);
+ targetType = this._allTypes[typeObj.name];
+ }
+ return targetType;
+ },
+
/**
* looks up the name in the hierarchy
* @return {{}} type objec for the current name or null if doesn't exist
*/
lookupTypeObj : function(name, target, includeDefinition) {
- // translate function names on object into safe names
- var swapper = function(name) {
- switch (name) {
- case "prototype":
- return "$$prototype";
- case "__proto__":
- return "$$proto";
- case "toString":
- case "hasOwnProperty":
- case "toLocaleString":
- case "valueOf":
- case "isProtoTypeOf":
- case "propertyIsEnumerable":
- return "$_$" + name;
- default:
- return name;
- }
- };
-
- var innerLookup = function(name, type, allTypes) {
- var res = type[name];
-
- var proto = type.$$proto;
- if (res) {
- return includeDefinition || name === '$$fntype' ? res : res.typeObj;
- } else if (proto) {
- return innerLookup(name, allTypes[proto.typeObj.name], allTypes);
- } else {
- return null;
- }
- };
- var targetType = this._allTypes[this.scope(target)];
+ var scope = this.scope(target);
+ var targetType = this.lookupQualifiedType(scope, includeDefinition);
// uncomment this if we want to hide errors where there is an unknown type being placed on the scope stack
// if (!targetType) {
// targetType = this.globalScope()
// }
- var res = innerLookup(swapper(name), targetType, this._allTypes);
+ var res = innerLookup(this, swapper(name), targetType, includeDefinition);
return res;
},
@@ -512,13 +556,18 @@ function(typeUtils, mTypes, Deferred) {
var emptyProtoName = this.newFleetingObject(newObjectName + "~proto");
// __proto__ points to Function
this._allTypes[newObjectName].$$proto = new typeUtils.Definition("Function",null,this.uid);
- // we store the function signature in $$fntype
+ // we store the function type itself in $$fntype
this._allTypes[newObjectName].$$fntype = functionTypeObj;
- // store 'prototype' in $$prototype
+ // store type of 'prototype' object in $$prototype
this._allTypes[newObjectName].$$prototype = new typeUtils.Definition(emptyProtoName,null,this.uid);
- // to handle writes to 'this' inside the function, we create another type thisType. thisType
- // has the empty object as its $$proto. And thisType is the type ascribed to a new invocation.
- // in this manner, writes to fields of this override types in the empty prototype.
+ // to handle writes to 'this' inside the function, we create another type $$newtype. $$newtype
+ // has the function's $$prototype type as its $$proto. And $$newtype is the type ascribed to an
+ // invocation of the function with the 'new' operator.
+ // in this manner, writes to fields of 'this' take precedence over fields defined
+ // in the prototype object.
+ // E.g., if we have
+ // var AAA = function() { this.foo = 0; }; AAA.prototype = { foo : '' }; var x = new AAA();
+ // the type of x.foo should be Number, not String
if (!newTypeName) {
newTypeName = newObjectName + "~new";
}
@@ -547,9 +596,6 @@ function(typeUtils, mTypes, Deferred) {
},
/**
* updates a function type to include a new return type.
- * function types are specified like this: ?returnType:[arg-n...]
- * return type is the name of the return type, arg-n is the name of
- * the nth argument.
*/
updateReturnType : function(typeObj,newReturnTypeObj) {
if (! typeObj) {
@@ -578,26 +624,21 @@ function(typeUtils, mTypes, Deferred) {
/**
* get the result type for invoking target via a 'new' expression.
*/
- getNewType : function(target) {
- var result = this.lookupTypeObj("$$newtype",target);
- if (!result) {
- // TODO MS get rid of this code once we fix types.js
- var inferredTypeObj = target.extras.inferredTypeObj;
- result = typeUtils.extractReturnType(inferredTypeObj);
- }
- return result;
+ getNewType : function(target) {
+ return this.lookupTypeObj("$$newtype",target);
},
/**
* get the result type for invoking target via a 'new' expression.
*/
getFnType : function(target) {
- var result = this.lookupTypeObj("$$fntype",target);
- if (!result) {
- // TODO MS get rid of this code once we fix types.js
- result = target.extras.inferredTypeObj;
- }
- return result;
+ var result = this.lookupTypeObj("$$fntype",target);
+ if (!result) {
+ // this can occur, e.g., when target is the type attached to a CallExpression
+ // invoking a non-existent function
+ result = target.extras.inferredTypeObj;
+ }
+ return result;
},
diff --git a/bundles/org.eclipse.orion.client.ui/web/plugins/esprima/typeInference.js b/bundles/org.eclipse.orion.client.ui/web/plugins/esprima/typeInference.js
index 7143f9e..a535248 100644
--- a/bundles/org.eclipse.orion.client.ui/web/plugins/esprima/typeInference.js
+++ b/bundles/org.eclipse.orion.client.ui/web/plugins/esprima/typeInference.js
@@ -658,12 +658,23 @@ define(["plugins/esprima/esprimaVisitor", "plugins/esprima/typeUtils", "plugins/
}
/**
+ * @param {String} name
+ */
+ function findBuiltInNodeModuleType(name, env) {
+ if (name.indexOf(".") !== -1 || name.indexOf("/") !== -1) {
+ return null;
+ }
+ var typeObj = typeUtils.ensureTypeObject(name);
+ return env.findType(typeObj) ? typeObj : null;
+ }
+
+ /**
* if this method call ast node is a call to require with a single string constant
* argument, then look that constant up in the indexer to get a summary
* if a summary is found, then apply it to the current scope
*/
function extractRequireModule(call, env) {
- if (!env.indexer) {
+ if (!env.indexer && !env.nodeJSModule) {
return;
}
if (call.type === "CallExpression" && call.callee.type === "Identifier" &&
@@ -672,20 +683,24 @@ define(["plugins/esprima/esprimaVisitor", "plugins/esprima/typeUtils", "plugins/
var arg = call["arguments"][0];
if (arg.type === "Literal" && typeof arg.value === "string") {
// we're in business
- var summary = env.indexer.retrieveSummary(arg.value);
- if (summary) {
- var typeName;
- var mergeTypeName;
- if (typeof summary.provided === "string") {
- mergeTypeName = typeName = summary.provided;
- } else {
- // module provides a composite type
- // must create a type to add the summary to
- mergeTypeName = typeName = env.newScope();
- env.popScope();
+ if (env.nodeJSModule) {
+ return findBuiltInNodeModuleType(arg.value, env);
+ } else {
+ var summary = env.indexer.retrieveSummary(arg.value);
+ if (summary) {
+ var typeName;
+ var mergeTypeName;
+ if (typeof summary.provided === "string") {
+ mergeTypeName = typeName = summary.provided;
+ } else {
+ // module provides a composite type
+ // must create a type to add the summary to
+ mergeTypeName = typeName = env.newScope();
+ env.popScope();
+ }
+ env.mergeSummary(summary, mergeTypeName);
+ return typeUtils.ensureTypeObject(typeName);
}
- env.mergeSummary(summary, mergeTypeName);
- return typeUtils.ensureTypeObject(typeName);
}
}
}
diff --git a/bundles/org.eclipse.orion.client.ui/web/plugins/esprima/typeUtils.js b/bundles/org.eclipse.orion.client.ui/web/plugins/esprima/typeUtils.js
index fc91332..754e293 100644
--- a/bundles/org.eclipse.orion.client.ui/web/plugins/esprima/typeUtils.js
+++ b/bundles/org.eclipse.orion.client.ui/web/plugins/esprima/typeUtils.js
@@ -451,7 +451,13 @@ function(proposalUtils, scriptedLogger/*, doctrine*/) {
// maybe should traverse the prototype
return;
}
+ if (key === '$$isBuiltin') {
+ return;
+ }
var prop = origFields[key];
+ // if we're already serializing an enclosing object type (depth > 0),
+ // and the field type is itself an object type, just represent the type
+ // with '...' rather than recursing further
var fieldType = depth > 0 && (prop.typeObj.type === 'NameExpression' && env.isSyntheticName(prop.typeObj.name) && !allTypes[prop.typeObj.name].$$fntype) ?
{ type : 'NameExpression', name : JUST_DOTS } :
self.convertJsDocType(prop.typeObj, env, doCombine, depth+1);
diff --git a/bundles/org.eclipse.orion.client.ui/web/plugins/esprima/typesFromIndexFile.js b/bundles/org.eclipse.orion.client.ui/web/plugins/esprima/typesFromIndexFile.js
index d827448..cb5997a 100644
--- a/bundles/org.eclipse.orion.client.ui/web/plugins/esprima/typesFromIndexFile.js
+++ b/bundles/org.eclipse.orion.client.ui/web/plugins/esprima/typesFromIndexFile.js
@@ -18,9 +18,9 @@
* to the type structure expected by esprimaJsContentAssist.js
*/
-/*global define require*/
-define("plugins/esprima/typesFromIndexFile", ["orion/Deferred", "plugins/esprima/typeUtils", "plugins/esprima/indexFiles/ecma5Index"],
- function (Deferred, typeUtils, ecma5) {
+/*global define require definitionForType doctrine*/
+define("plugins/esprima/typesFromIndexFile", ["orion/Deferred", "plugins/esprima/typeUtils", "doctrine/doctrine"],
+ function (Deferred, typeUtils) {
/**
@@ -67,10 +67,6 @@ define("plugins/esprima/typesFromIndexFile", ["orion/Deferred", "plugins/esprima
Types.prototype = typesPrototype;
-
- // NOTE: this works even with function types for arguments due to greediness in regexp matching
- var fnTypeRegexp = /fn\((.*)\)(\s*->\s*(.*))?/;
-
var primitiveTypeMap = {
"number": "Number",
"bool": "Boolean",
@@ -85,6 +81,140 @@ define("plugins/esprima/typesFromIndexFile", ["orion/Deferred", "plugins/esprima
return namePrefix + _typeCount++;
}
+ var idRegexp = /^[_$a-zA-Z\xA0-\uFFFF]([_$a-zA-Z0-9\.\xA0-\uFFFF])*$/;
+
+ /**
+ * checks if str is a name for which we wouldn't have discovered any properties.
+ * Currently, a JS identifier or a string starting with '[' (array) or '+'
+ * (user-defined type)
+ * @param {String} str
+ */
+ function emptyTypeName(str) {
+ return str && (idRegexp.test(str) || str.slice(0,1) === "[" || str.slice(0,1) === "+");
+ }
+
+ function convertArgTypeToClosureType(argType) {
+ var closureArgStr = null;
+ if (argType.typeObj.type === "FunctionType") {
+ closureArgStr = doctrine.type.stringify(argType.typeObj, {compact:true});
+ } else {
+ closureArgStr = argType.typeObj.name;
+ }
+ return closureArgStr;
+ }
+
+ /**
+ * @param {String} ternSig
+ * @param {String} returnTypeName
+ */
+ function ternSig2ClosureSigInternal(ternSig, returnTypeName, typeInfo) {
+ /**
+ * @param {String} str
+ */
+ function parseArgs(str) {
+ // get rid of "fn(" and strip all spaces
+ str = str.substring(3, str.length);
+ var leftToParse = str.replace(/\s+/g, '');
+ var result = "";
+ // need to be a bit smart here to handle
+ // arguments with function types
+ while (leftToParse.slice(0,1) !== ")") {
+ var colonInd = leftToParse.indexOf(":");
+ var argName = leftToParse.slice(0, colonInd);
+ var optional = argName[argName.length - 1] === '?';
+ if (optional) {
+ argName = argName.slice(0, argName.length - 1);
+ }
+ leftToParse = leftToParse.slice(colonInd + 1, leftToParse.length);
+ var commaInd = null, closeParenInd = null;
+ if (leftToParse.slice(0, 2) === "fn") {
+ // find the close paren. end of argument is next comma after
+ // that (or the end of the string)
+ closeParenInd = leftToParse.indexOf(")");
+ commaInd = leftToParse.indexOf(",", closeParenInd);
+ } else {
+ commaInd = leftToParse.indexOf(",");
+ }
+ var argTypeEndInd = null;
+ if (commaInd !== -1) {
+ argTypeEndInd = commaInd;
+ } else {
+ // depends on whether we have a return type
+ var returnArrowInd = null;
+ if (closeParenInd) {
+ // last argument type was a function type.
+ // to handle case where that function type has a return type,
+ // search from *next* close paren
+ returnArrowInd = leftToParse.indexOf("->", leftToParse.indexOf(")", closeParenInd+1));
+ } else {
+ returnArrowInd = leftToParse.indexOf("->");
+ }
+ if (returnArrowInd !== -1) {
+ argTypeEndInd = returnArrowInd - 1;
+ } else {
+ // just the end of the string, without the close paren
+ argTypeEndInd = leftToParse.length-1;
+ }
+ }
+ var argTypeStr = leftToParse.slice(0, argTypeEndInd);
+ // TODO for a function type we get undefined here as the type name; is that what we want
+ var argType = definitionForType(typeInfo, argTypeStr);
+ result += argName + ":" + convertArgTypeToClosureType(argType);
+ if (optional) {
+ result += "=";
+ }
+ if (commaInd !== -1) {
+ result += ",";
+ // use argTypeEndInd+1 to remove the comma
+ leftToParse = leftToParse.slice(argTypeEndInd+1, leftToParse.length);
+ } else {
+ leftToParse = leftToParse.slice(argTypeEndInd, leftToParse.length);
+ }
+ }
+ return { args: result, remaining: leftToParse.slice(1,leftToParse.length) };
+ }
+
+ /**
+ * @param {String} str
+ */
+ function parseRet(str) {
+ // get rid of "->"
+ str = str.substring(2, str.length);
+ return convertArgTypeToClosureType(definitionForType(typeInfo, str));
+ }
+ var argsAndRemaining = parseArgs(ternSig);
+ var remaining = argsAndRemaining.remaining;
+ var retString;
+ // HACK: if there is no return type in fnType,
+ // use name as the return type, if it is defined.
+ // Otherwise, use undefined
+ if (remaining !== "") {
+ retString = parseRet(remaining);
+ } else if (returnTypeName) {
+ retString = returnTypeName;
+ }
+ // use convention of upper-case names being constructors
+ var isConstructor = !remaining && retString && isUpperCaseChar(retString);
+ var defName = "function(";
+ if (isConstructor) {
+ defName += "new:" + retString;
+ if (argsAndRemaining.args) {
+ defName += ",";
+ }
+ }
+ defName += argsAndRemaining.args + "):" + retString;
+ return defName;
+ }
+
+ /**
+ * converts a function signature in the Tern index file format
+ * to a signature in the Closure format used internally by the
+ * JS content assist engine
+ */
+ function ternSig2ClosureSig(ternSig, constructorName) {
+ return ternSig2ClosureSigInternal(ternSig, constructorName, {});
+ }
+
/**
* creates a Definition object for the given type and name.
* As a side-effect, adds information about the type (e.g.,
@@ -119,21 +249,24 @@ define("plugins/esprima/typesFromIndexFile", ["orion/Deferred", "plugins/esprima
} else if (p[0] === '!') {
throw "didn't handle special property " + p;
} else if (p === "prototype") {
- if (typeof type[p] === "string") {
- propInfo.$$newtype = new typeUtils.Definition(type[p]);
- } else {
- var tmpProtoName = name ? name + "_prototype" : genObjName();
- propInfo.$$newtype = definitionForType(typeInfo, type[p], tmpProtoName);
- }
+ propInfo.$$prototype = definitionForType(typeInfo, type[p]);
+ // we set the $$newtype to be the same as the $$prototype.
+ // we need $$newtype in order to be consistent with the rest of
+ // the type system. we don't need it to be a fresh object, since
+ // we won't add properties to it while analyzing the constructor.
+ // setting $$newtype and $$prototype to be the same avoids some
+ // issues with naming of types (since we don't need to generate some
+ // different name for $$newtype)
+ propInfo.$$newtype = propInfo.$$prototype;
} else {
propInfo[p] = definitionForType(typeInfo, type[p]);
}
}
}
- if (propInfo.$$newtype && propInfo.$$fntype && typeof type.prototype === "string") {
+ if (propInfo.$$prototype && propInfo.$$fntype && typeof type.prototype === "string") {
// if we have a named prototype, use that name as the return type
// in $$fntype
- var protoName = propInfo.$$newtype.typeObj.name;
+ var protoName = propInfo.$$prototype.typeObj.name;
var funType = propInfo.$$fntype;
// if (!funType.new) { throw "something broken"; }
funType.result.name = protoName;
@@ -153,73 +286,6 @@ define("plugins/esprima/typesFromIndexFile", ["orion/Deferred", "plugins/esprima
};
}
- function definitionForFunctionType(fnType, name) {
- function parseArgs(str) {
- // strip all spaces
- var leftToParse = str.replace(/\s+/g, '');
- var result = "";
- // need to be a bit smart here to handle
- // arguments with function types
- while (leftToParse !== "") {
- var colonInd = leftToParse.indexOf(":");
- var argName = leftToParse.slice(0, colonInd);
- var optional = argName[argName.length - 1] === '?';
- if (optional) {
- argName = argName.slice(0, argName.length - 1);
- }
- leftToParse = leftToParse.slice(colonInd + 1, leftToParse.length);
- var commaInd;
- if (leftToParse.slice(0, 2) === "fn") {
- // find the close paren. end of argument is next comma after
- // that (or the end of the string)
- var closeParenInd = leftToParse.indexOf(")");
- commaInd = leftToParse.indexOf(",", closeParenInd);
- } else {
- commaInd = leftToParse.indexOf(",");
- }
- var argTypeEndInd = commaInd === -1 ? leftToParse.length : commaInd;
- var argTypeStr = leftToParse.slice(0, argTypeEndInd);
- result += argName + ":" + definitionForType(typeInfo, argTypeStr).typeObj.name;
- if (optional) {
- result += "=";
- }
- if (argTypeEndInd !== leftToParse.length) {
- result += ",";
- leftToParse = leftToParse.slice(argTypeEndInd + 1, leftToParse.length);
- } else {
- leftToParse = "";
- }
- }
- return result;
- }
-
- function parseRet(str) {
- return definitionForType(typeInfo, str).typeObj.name;
- }
- var match = fnTypeRegexp.exec(fnType);
- if (!match) {
- throw "unexpected function type " + fnType;
- }
- var argString = match[1] === "" ? "" : parseArgs(match[1]);
- var retString;
- // HACK: if there is no return type in fnType,
- // use name as the return type, if it is defined.
- // Otherwise, use undefined
- if (match[2]) {
- retString = parseRet(match[3]);
- } else if (name) {
- retString = name;
- }
- // use convention of upper-case names being constructors
- var isConstructor = !match[2] && retString && isUpperCaseChar(retString);
- var defName = "function(";
- if (isConstructor) {
- defName += "new:" + retString + ",";
- }
- defName += argString + "):" + retString;
- return new typeUtils.Definition(defName);
- }
-
if (typeof type === "string") {
if (primitiveTypeMap[type]) {
return new typeUtils.Definition(primitiveTypeMap[type]);
@@ -240,32 +306,31 @@ define("plugins/esprima/typesFromIndexFile", ["orion/Deferred", "plugins/esprima
// TODO handle these properly
return new typeUtils.Definition(name);
} else if (type.slice(0, 2) === "fn") {
- return definitionForFunctionType(type, name);
+ return new typeUtils.Definition(ternSig2ClosureSigInternal(type, name, typeInfo));
} else if (type[0] === "[") {
return new typeUtils.Definition("Array");
- } else if (type[0] === "+") {
- // a user-defined type. just assume it exists for now; probably should check
- return new typeUtils.Definition(type.slice(1, type.length));
} else if (type.slice(0, 7) === "!custom" || type.slice(0, 5) === "!this" || type.slice(0, 2) === "!0") {
// don't understand this; treat it as Object for now
return new typeUtils.Definition("Object");
- } else if (type.indexOf(".") !== -1) {
- var typeName = type.indexOf(".prototype") !== -1 ? type.replace(".", "_") : type;
- // TODO should we enforce this?
- // if (!typesPrototype[typeName]) {
- // throw "bad type name " + typeName;
- // }
- return new typeUtils.Definition(typeName);
- } else {
- if (type.slice(0, 1) === "!") {
- throw "unhandled special case " + type;
- }
- return name ? new typeUtils.Definition(name) : new typeUtils.Definition(type);
+ } else if (type.slice(0,1) === "!") {
+ throw "unhandled special case " + type;
}
+ if (type.indexOf(".") !== -1) {
+ // replace with ".." to avoid conflicting with "." syntax
+ // used in inferred types for constructor functions
+ type = type.replace(/\./g, "..");
+ }
+ if (type.slice(0,1) === "+") {
+ type = type.slice(1,type.length) + "..prototype";
+ }
+ return name ? new typeUtils.Definition(name) : new typeUtils.Definition(type);
} else { // an object type
var parsed = parseObjType(type, name);
var newTypeName = parsed.def.typeObj.name;
- if (newTypeName) {
+ // here we check if type["!type"] is a plain type name. if so,
+ // we just have an empty type description for it (with no
+ // properties), and there is no need to update the type object
+ if (newTypeName && !emptyTypeName(type["!type"])) {
if (newTypeName === "Object") {
// need to mangle the property names as in original types.js
var mangled = {};
@@ -280,11 +345,12 @@ define("plugins/esprima/typesFromIndexFile", ["orion/Deferred", "plugins/esprima
} else {
// don't overwrite property info with empty types
- if (!typeInfo[newTypeName] || Object.keys(parsed.propInfo).length > 0) {
- // mark as built-in so not mucked up by inference
- parsed.propInfo.$$isBuiltin = true;
- typeInfo[newTypeName] = parsed.propInfo;
+ if (typeInfo[newTypeName]) {
+ throw "type " + newTypeName + " defined twice in index file";
}
+ // mark as built-in so not mucked up by inference
+ parsed.propInfo.$$isBuiltin = true;
+ typeInfo[newTypeName] = parsed.propInfo;
}
}
return parsed.def;
@@ -293,6 +359,18 @@ define("plugins/esprima/typesFromIndexFile", ["orion/Deferred", "plugins/esprima
/**
+ * for unit testing. given a type object with properties as in an index file,
+ * and a name for the type, returns an object { def: d, typeInfo: t }, where d
+ * is a Definition for the type and t contains auxiliary type information (e.g.,
+ * types of properties.
+ */
+ function parseType(type, name) {
+ var typeInfo = {};
+ var def = definitionForType(typeInfo, type, name);
+ return { def: def, typeInfo: typeInfo };
+ }
+
+ /**
* adds the info from the given json index file. global variables are added to globals,
* and type information to typeInfo
*/
@@ -329,16 +407,30 @@ define("plugins/esprima/typesFromIndexFile", ["orion/Deferred", "plugins/esprima
// prototype of global object is Object
globalPrototype.$$proto = new typeUtils.Definition("Object");
- // add information for core libraries directly to Global.prototype
- // and Types.prototype
- addIndexInfo(ecma5, globalPrototype, typesPrototype);
-
+ var initResult = null;
+ /**
+ * adds type information for core ecma5 libraries.
+ * returns a promise that is resolved when the info is loaded.
+ */
+ function init() {
+ if (!initResult) {
+ var d = new Deferred();
+ require(["plugins/esprima/indexFiles/ecma5Index"], function (ecma5) {
+ // add information for core libraries directly to Global.prototype
+ // and Types.prototype
+ addIndexInfo(ecma5, globalPrototype, typesPrototype);
+ d.resolve();
+ });
+ initResult = d.promise;
+ }
+ return initResult;
+ }
/////////////////////////
// code for adding other index files
//
// Strategy: when someone asks for another index file, we parse that
// file, and then add the results to a *particular* Types object. This
- // is in contrast to types.js, which keeps three separate global object
+ // is in contrast to types.js, which kept three separate global object
// representations (for standard js, browser, and node) and keeps relevant
// type info on each of their prototypes.
//
@@ -348,6 +440,38 @@ define("plugins/esprima/typesFromIndexFile", ["orion/Deferred", "plugins/esprima
var parsedIndexFileCache = {};
/**
+ * update knownTypes with type and global information
+ * from globalsAndTypes
+ */
+ function updateKnownTypes(knownTypes, globalsAndTypes) {
+ // now, add the globals and types for the index file to knownTypes
+ // we want globals on the *prototype* of knownTypes.Global. (We
+ // need them on the prototype so their types cannot be overwritten
+ // by user code.) So, we create a new prototype object with extant
+ // globals and the new ones from the index file, and then re-allocate
+ // knownTypes.Global. (gross)
+ var newProto = {};
+ var knownGlobals = Object.getPrototypeOf(knownTypes.Global);
+ Object.keys(knownGlobals).forEach(function (globName) {
+ newProto[globName] = knownGlobals[globName];
+ });
+ Object.keys(globalsAndTypes.globals).forEach(function (globName) {
+ newProto[globName] = globalsAndTypes.globals[globName];
+ });
+ Global.prototype = newProto;
+ knownTypes.Global = new Global();
+ Global.prototype = globalPrototype;
+
+ // we want types on knownTypes itself
+ Object.keys(globalsAndTypes.types).forEach(function (typeName) {
+ if (typeName !== "Global") {
+ knownTypes[typeName] = globalsAndTypes.types[typeName];
+ }
+ });
+ return knownTypes;
+
+ }
+ /**
* Add information for library libName to the knownTypes object.
*
* Returns a promise, as the library index file may need to be loaded
@@ -378,37 +502,27 @@ define("plugins/esprima/typesFromIndexFile", ["orion/Deferred", "plugins/esprima
d.resolve(globalsAndTypes);
}
var result = d.then(function (globalsAndTypes) {
- // now, add the globals and types for the index file to knownTypes
- // we want globals on the *prototype* of knownTypes.Global. (We
- // need them on the prototype so their types cannot be overwritten
- // by user code.) So, we create a new prototype object with extant
- // globals and the new ones from the index file, and then re-allocate
- // knownTypes.Global. (gross)
- var newProto = {};
- var knownGlobals = Object.getPrototypeOf(knownTypes.Global);
- Object.keys(knownGlobals).forEach(function (globName) {
- newProto[globName] = knownGlobals[globName];
- });
- Object.keys(globalsAndTypes.globals).forEach(function (globName) {
- newProto[globName] = globalsAndTypes.globals[globName];
- });
- Global.prototype = newProto;
- knownTypes.Global = new Global();
- Global.prototype = globalPrototype;
-
- // we want types on knownTypes itself
- Object.keys(globalsAndTypes.types).forEach(function (typeName) {
- if (typeName !== "Global") {
- knownTypes[typeName] = globalsAndTypes.types[typeName];
- }
- });
- return knownTypes;
+ return updateKnownTypes(knownTypes, globalsAndTypes);
});
return result;
}
+ /**
+ * add some index file data to the knownTypes object.
+ * Mutates knownTypes.
+ */
+ function addIndexData(indexData, knownTypes) {
+ var globalsAndTypes = { globals: {}, types: {} };
+ addIndexInfo(indexData, globalsAndTypes.globals, globalsAndTypes.types);
+ updateKnownTypes(knownTypes, globalsAndTypes);
+ }
+
return {
Types: Types,
- addLibrary: addLibrary
+ addLibrary: addLibrary,
+ ternSig2ClosureSig: ternSig2ClosureSig,
+ init: init,
+ parseType: parseType,
+ addIndexData: addIndexData
};
}); \ No newline at end of file