Skip to content
6 changes: 4 additions & 2 deletions bin/condense
Original file line number Diff line number Diff line change
Expand Up @@ -2,13 +2,14 @@

var tern = require("../lib/tern"), condense = require("../lib/condense");
var path = require("path"), fs = require("fs");
require("../plugin/doc_comment");
var disableDocComment = process.argv.indexOf("--disable-doc-comment") > -1;
if (!disableDocComment) require("../plugin/doc_comment");

var localDir = process.cwd(), ourDir = path.resolve(__dirname, "..");
var spans = true;

function usage(exit) {
console.error("usage: " + process.argv[1] + " [--name name] [--plugin name]* [--def name]* [+extrafile.js]* [file.js]+");
console.error("usage: " + process.argv[1] + " [--no-spans] [--disable-doc-comment] [--name name] [--plugin name]* [--def name]* [+extrafile.js]* [file.js]+");
if (exit != null) process.exit(exit);
}

Expand Down Expand Up @@ -60,6 +61,7 @@ for (var i = 2, len = process.argv.length; i < len; ++i) {
loadDef(process.argv[++i]);
} else if (cur == "--name" && i < len - 1) {
name = process.argv[++i];
} else if (cur == "--disable-doc-comment") {
} else if (cur == "--no-spans") {
spans = false;
} else if (cur.charAt(0) == "-") {
Expand Down
1 change: 1 addition & 0 deletions bin/test
Original file line number Diff line number Diff line change
Expand Up @@ -7,5 +7,6 @@ require("../test/fragments").runTests(filter);
require("../test/condense").runTests(filter);
require("../test/timeout").runTests(filter);
require("../test/reload").runTests(filter);
require("../test/def-parser").runTests(filter);

process.exit(require("../test/util").hasFailed());
10 changes: 9 additions & 1 deletion lib/condense.js
Original file line number Diff line number Diff line change
Expand Up @@ -94,6 +94,10 @@

function reach(type, path, id, state, byName) {
var actual = type.getType(false);
if (!actual && type.path && type.path !== "?") {
state.altPaths[id] = type;
return;
}
if (!actual) return;
var orig = type.origin || actual.origin, relevant = false;
if (orig) {
Expand All @@ -113,7 +117,7 @@
state.altPaths[oldPath] = actual;
} else data = {type: actual};
data.span = state.getSpan(type) || (actual != type && state.isTarget(actual.origin) && state.getSpan(actual)) || data.span;
data.doc = type.doc || (actual != type && state.isTarget(actual.origin) && type.doc) || data.doc;
data.doc = type.doc || (actual != type && state.isTarget(actual.origin) && actual.doc) || data.doc;
data.data = actual.metaData;
data.byName = data.byName == null ? !!byName : data.byName && byName;
state.types[newPath] = data;
Expand All @@ -129,6 +133,8 @@

infer.Prim.prototype.reached = function() {return true;};

infer.UnionType.prototype.reached = function() {return true;};

infer.Arr.prototype.reached = function(path, state, concrete) {
if (!concrete) reachByName(this.getProp("<i>"), path, "<i>", state);
return true;
Expand Down Expand Up @@ -226,6 +232,8 @@
return name;
}

infer.UnionType.prototype.typeName = function () { return this.toString(); }

infer.Prim.prototype.typeName = function() { return this.name; };

infer.Arr.prototype.typeName = function() {
Expand Down
12 changes: 12 additions & 0 deletions lib/def.js
Original file line number Diff line number Diff line change
Expand Up @@ -76,7 +76,18 @@
if (computeRetStart != null) fn.computeRetSource = this.spec.slice(computeRetStart, this.pos);
return fn;
},
parseUnionType: function(name, top) {
var types = [];
while (true) {
types.push(this.parseType());
if(!this.eat("|")) break;
}
return new infer.UnionType(types);
},
parseType: function(name, top) {
if (this.eat("(")) {
return this.parseUnionType(name, top);
}
if (this.eat("fn(")) {
return this.parseFnType(name, top);
} else if (this.eat("[")) {
Expand Down Expand Up @@ -332,6 +343,7 @@
if (typeof inner == "string") {
if (type) continue;
parseType(inner, innerPath).propagate(known);
known.path = inner;
} else {
if (!isSimpleAnnotation(inner)) {
passTwo(type, inner, innerPath);
Expand Down
18 changes: 18 additions & 0 deletions lib/infer.js
Original file line number Diff line number Diff line change
Expand Up @@ -410,6 +410,24 @@
if (this.proto) this.proto.gatherProperties(f, depth);
}
});

var UnionType = exports.UnionType = function(array) { this.value = array; }
UnionType.prototype = extend(Type.prototype, {
constructor: UnionType,
toString: function() {
var format = "(";
for (var i = 0; i < this.value.length; i++) {
format += this.value[i].getType().toString();
if (i < this.value.length-1 ) format += "|";
}
format += ")";
return format;
},
gatherProperties: function(f, depth) {
for (var i = 0; i < this.value.length; ++i)
this.value[i].gatherProperties(f, depth);
}
})

var Obj = exports.Obj = function(proto, name) {
if (!this.props) this.props = Object.create(null);
Expand Down
59 changes: 59 additions & 0 deletions test/condense-utils.js
Original file line number Diff line number Diff line change
@@ -0,0 +1,59 @@
var util = require("./util");
var tern = require("../lib/tern"), condense = require("../lib/condense");
var fs = require("fs"), path = require("path");

var condenseDir = "test/condense";
exports.condenseConf = {
projectDir: path.resolve(__dirname, ".."),
resolve: function(pth) { return path.resolve(this.projectDir, pth); },
jsonFile: function(name) { return this.resolve(condenseDir + "/" + name.replace(/\.js$/, ".json")) }
}

exports.runTest = function(conf,options) {
var server = new tern.Server({
defs: [util.ecma5, util.browser],
plugins: options.plugins,
projectDir: conf.resolve(condenseDir),
getFile: function(name) {
return fs.readFileSync(path.resolve(condenseDir, name), "utf8");
}
});
options.load.forEach(function(file) {
server.addFile(file);
});
server.flush(function() {
var origins = options.include || options.load;
var condensed = condense.condense(origins, null, {sortOutput: true});
var out = JSON.stringify(condensed, null, 2);
var expect = fs.readFileSync(conf.jsonFile(origins[0]), "utf8").trim();
if (out != expect)
return util.failure("condense/" + origins[0] + ": Mismatch in condense output.\nGot " +
out + "\nExpected " + expect);

// Test loading the condensed defs.
var server2 = new tern.Server({
defs: [util.ecma5, util.browser, condensed],
plugins: options.plugins
});
server2.flush(function() {
var condensed = condense.condense(origins, null, {sortOutput: true});
var out = JSON.stringify(condensed, null, 2);
if (out != expect)
util.failure("condense/" + origins[0] + ": Mismatch in condense output after loading defs. Got " +
out + "\nExpected " + expect);
});
});
}

function jsFile(f) {
return f + ".js";
}
exports.testConf = function(condenseConf,filter,options) {
if (typeof options == "string") options = {load: [options]};
options.load = options.load.map(jsFile);
if (options.include) options.include = options.include.map(jsFile);
if (filter && options.load[0].indexOf(filter) == -1) return;
util.addTest();
util.addFile();
exports.runTest(condenseConf,options);
}
58 changes: 3 additions & 55 deletions test/condense.js
Original file line number Diff line number Diff line change
@@ -1,61 +1,9 @@
var util = require("./util");
var tern = require("../lib/tern"), condense = require("../lib/condense");
var fs = require("fs"), path = require("path");
require("../plugin/angular");
require("../plugin/node");

var condenseDir = "test/condense";
function jsonFile(name) { return util.resolve(condenseDir + "/" + name.replace(/\.js$/, ".json")); }

function runTest(options) {
var server = new tern.Server({
defs: [util.ecma5, util.browser],
plugins: options.plugins,
projectDir: util.resolve(condenseDir),
getFile: function(name) {
return fs.readFileSync(path.resolve(condenseDir, name), "utf8");
}
});
options.load.forEach(function(file) {
server.addFile(file);
});
server.flush(function() {
var origins = options.include || options.load;
var condensed = condense.condense(origins, null, {sortOutput: true});
var out = JSON.stringify(condensed, null, 2);
var expect = fs.readFileSync(jsonFile(origins[0]), "utf8").trim();
if (out != expect)
return util.failure("condense/" + origins[0] + ": Mismatch in condense output. Got " +
out + "\nExpected " + expect);

// Test loading the condensed defs.
var server2 = new tern.Server({
defs: [util.ecma5, util.browser, condensed],
plugins: options.plugins
});
server2.flush(function() {
var condensed = condense.condense(origins, null, {sortOutput: true});
var out = JSON.stringify(condensed, null, 2);
if (out != expect)
util.failure("condense/" + origins[0] + ": Mismatch in condense output after loading defs. Got " +
out + "\nExpected " + expect);
});
});
}
var condenseUtils = require("./condense-utils");

exports.runTests = function(filter) {
function jsFile(f) {
return f + ".js";
}
function test(options) {
if (typeof options == "string") options = {load: [options]};
options.load = options.load.map(jsFile);
if (options.include) options.include = options.include.map(jsFile);
if (filter && options.load[0].indexOf(filter) == -1) return;
util.addTest();
util.addFile();
runTest(options);
}
function test(options) { condenseUtils.testConf(condenseUtils.condenseConf, filter, options) };

test("basic");
test("fn");
Expand Down Expand Up @@ -86,4 +34,4 @@ exports.runTests = function(filter) {
test({load: ["requirejs_const", "requirejs_dep"], include: ["requirejs_dep", "requirejs_const"], plugins: {requirejs: true}});

test("recursive");
};
}
30 changes: 30 additions & 0 deletions test/def-parser.js
Original file line number Diff line number Diff line change
@@ -0,0 +1,30 @@
var util = require("./util");

var infer = require("../lib/infer");
var def = require("../lib/def").init({}, infer);

exports.runTests = function(filter) {
var cx = new infer.Context([],null);
infer.withContext(cx, function() {
cx.protos.Object = new infer.Obj(null, "Object.prototype");
cx.topScope = new infer.Scope();
cx.topScope.name = "<top>";
cx.protos.Array = new infer.Obj(true, "Array.prototype");
cx.protos.Function = new infer.Obj(true, "Function.prototype");
cx.protos.RegExp = new infer.Obj(true, "RegExp.prototype");
cx.protos.String = new infer.Obj(true, "String.prototype");
cx.protos.Number = new infer.Obj(true, "Number.prototype");
cx.protos.Boolean = new infer.Obj(true, "Boolean.prototype");
cx.str = new infer.Prim(cx.protos.String, "string");
cx.bool = new infer.Prim(cx.protos.Boolean, "bool");
cx.num = new infer.Prim(cx.protos.Number, "number");
cx.curOrigin = null;

var typeString = "(number|string)";
var unionType = new def.TypeParser(typeString, "", null, true).parseType("??", true);
util.addTest();
util.addFile();
if (unionType.toString() !== "(number|string)") util.failure("parsing " + typeString + " failed, got: " + unionType.toString());
});

}