babel/scripts/generate-interfaces.js
jbrown215 f4716dc816 Backport #6031 (#6112)
* Backport #6031

* Backport #6031

* Rebase on master, rerun scripts

* Update flowconfig
2017-08-15 17:42:01 -04:00

136 lines
3.4 KiB
JavaScript

var fs = require("fs");
var t = require("../packages/babel-types");
var NODE_PREFIX = "BabelNode";
var code = `// NOTE: This file is autogenerated. Do not modify.
// See scripts/generate-interfaces.js for script used.
declare class ${NODE_PREFIX}Comment {
value: string;
start: number;
end: number;
loc: ${NODE_PREFIX}SourceLocation;
}
declare class ${NODE_PREFIX}BlockComment extends ${NODE_PREFIX}Comment {
type: "BlockComment";
}
declare class ${NODE_PREFIX}LineComment extends ${NODE_PREFIX}Comment {
type: "LineComment";
}
declare class ${NODE_PREFIX}SourceLocation {
start: {
line: number;
column: number;
};
end: {
line: number;
column: number;
};
}
declare class ${NODE_PREFIX} {
leadingComments: ?Array<${NODE_PREFIX}Comment>;
innerComments: ?Array<${NODE_PREFIX}Comment>;
trailingComments: ?Array<${NODE_PREFIX}Comment>;
start: ?number;
end: ?number;
loc: ?${NODE_PREFIX}SourceLocation;
}\n\n`;
//
var lines = [];
for (var type in t.NODE_FIELDS) {
var fields = t.NODE_FIELDS[type];
var struct = ['type: "' + type + '";'];
var args = [];
Object.keys(t.NODE_FIELDS[type])
.sort((fieldA, fieldB) => {
const indexA = t.BUILDER_KEYS[type].indexOf(fieldA);
const indexB = t.BUILDER_KEYS[type].indexOf(fieldB);
if (indexA === indexB) return fieldA < fieldB ? -1 : 1;
if (indexA === -1) return 1;
if (indexB === -1) return -1;
return indexA - indexB;
})
.forEach(fieldName => {
const field = fields[fieldName];
let suffix = "";
if (field.optional || field.default != null) suffix += "?";
let typeAnnotation = "any";
const validate = field.validate;
if (validate) {
if (validate.oneOf) {
typeAnnotation = validate.oneOf
.map(function(val) {
return JSON.stringify(val);
})
.join(" | ");
}
if (validate.type) {
typeAnnotation = validate.type;
if (typeAnnotation === "array") {
typeAnnotation = "Array<any>";
}
}
if (validate.oneOfNodeTypes) {
const types = validate.oneOfNodeTypes.map(
type => `${NODE_PREFIX}${type}`
);
typeAnnotation = types.join(" | ");
if (suffix === "?") typeAnnotation = "?" + typeAnnotation;
}
}
if (typeAnnotation) {
suffix += ": " + typeAnnotation;
}
args.push(t.toBindingIdentifierName(fieldName) + suffix);
if (t.isValidIdentifier(fieldName)) {
struct.push(fieldName + suffix + ";");
}
});
code += `declare class ${NODE_PREFIX}${type} extends ${NODE_PREFIX} {
${struct.join("\n ").trim()}
}\n\n`;
// Flow chokes on super() and import() :/
if (type !== "Super" && type !== "Import") {
lines.push(`declare function ${type[0].toLowerCase() + type.slice(1)}(${args.join(", ")}): ${NODE_PREFIX}${type};`);
}
}
for (var i = 0; i < t.TYPES.length; i++) {
lines.push(`declare function is${t.TYPES[i]}(node: Object, opts?: Object): boolean;`);
}
for (var type in t.FLIPPED_ALIAS_KEYS) {
var types = t.FLIPPED_ALIAS_KEYS[type];
code += `type ${NODE_PREFIX}${type} = ${types.map(type => `${NODE_PREFIX}${type}`).join(" | ")};\n`;
}
code += `\ndeclare module "babel-types" {
${lines.join("\n").replace(/\n/g, "\n ").trim()}
}\n`;
//
fs.writeFileSync(__dirname + "/../lib/types.js", code);