react-dts-generator
Version:
Simple .d.ts generator for React components.
980 lines (979 loc) • 29.8 kB
JavaScript
;
Object.defineProperty(exports, "__esModule", { value: true });
var DeclarationFlags;
(function (DeclarationFlags) {
DeclarationFlags[DeclarationFlags["None"] = 0] = "None";
DeclarationFlags[DeclarationFlags["Private"] = 1] = "Private";
DeclarationFlags[DeclarationFlags["Protected"] = 2] = "Protected";
DeclarationFlags[DeclarationFlags["Static"] = 4] = "Static";
DeclarationFlags[DeclarationFlags["Optional"] = 8] = "Optional";
DeclarationFlags[DeclarationFlags["Export"] = 16] = "Export";
DeclarationFlags[DeclarationFlags["Abstract"] = 32] = "Abstract";
DeclarationFlags[DeclarationFlags["ExportDefault"] = 64] = "ExportDefault";
DeclarationFlags[DeclarationFlags["ReadOnly"] = 128] = "ReadOnly";
})(DeclarationFlags = exports.DeclarationFlags || (exports.DeclarationFlags = {}));
var ParameterFlags;
(function (ParameterFlags) {
ParameterFlags[ParameterFlags["None"] = 0] = "None";
ParameterFlags[ParameterFlags["Optional"] = 1] = "Optional";
ParameterFlags[ParameterFlags["Rest"] = 2] = "Rest";
})(ParameterFlags = exports.ParameterFlags || (exports.ParameterFlags = {}));
exports.config = {
wrapJsDocComments: true,
outputEol: '\r\n',
};
exports.create = {
interface(name, flags = DeclarationFlags.None) {
return {
name,
baseTypes: [],
kind: "interface",
members: [],
flags
};
},
class(name, flags = DeclarationFlags.None) {
return {
kind: 'class',
name,
members: [],
implements: [],
typeParameters: [],
flags
};
},
typeParameter(name, baseType) {
return {
kind: 'type-parameter',
name, baseType
};
},
enum(name, constant = false, flags = DeclarationFlags.None) {
return {
kind: 'enum',
name, constant,
members: [],
flags
};
},
enumValue(name, value) {
return {
kind: 'enum-value',
name,
value
};
},
property(name, type, flags = DeclarationFlags.None) {
return {
kind: "property",
name, type, flags
};
},
method(name, parameters, returnType, flags = DeclarationFlags.None) {
return {
kind: "method",
typeParameters: [],
name, parameters, returnType, flags
};
},
callSignature(parameters, returnType) {
return {
kind: "call-signature",
typeParameters: [],
parameters, returnType
};
},
function(name, parameters, returnType, flags = DeclarationFlags.None) {
return {
kind: "function",
typeParameters: [],
name, parameters, returnType, flags
};
},
functionType(parameters, returnType) {
return {
kind: "function-type",
parameters, returnType
};
},
parameter(name, type, flags = ParameterFlags.None) {
return {
kind: "parameter",
name, type, flags
};
},
constructor(parameters, flags = DeclarationFlags.None) {
return {
kind: "constructor",
parameters,
flags
};
},
const(name, type, flags = DeclarationFlags.None) {
return {
kind: "const", name, type, flags
};
},
variable(name, type) {
return {
kind: "var", name, type
};
},
alias(name, type, flags = DeclarationFlags.None) {
return {
kind: "alias", name, type,
typeParameters: [], flags
};
},
namespace(name) {
return {
kind: "namespace", name,
members: []
};
},
objectType(members) {
return {
kind: "object",
members
};
},
indexSignature(name, indexType, valueType) {
return {
kind: 'index-signature',
name, indexType, valueType
};
},
array(type) {
return {
kind: "array",
type
};
},
namedTypeReference(name) {
return {
kind: 'name',
name
};
},
exportEquals(target) {
return {
kind: 'export=',
target
};
},
exportDefault(name) {
return {
kind: 'exportDefault',
name
};
},
exportName(name, as) {
return {
kind: "exportName",
name,
as
};
},
module(name) {
return {
kind: 'module',
name,
members: []
};
},
importAll(name, from) {
return {
kind: 'importAll',
name,
from
};
},
importDefault(name, from) {
return {
kind: 'importDefault',
name,
from
};
},
importNamed(name, as, from) {
return {
kind: 'importNamed',
name,
as: typeof from !== 'undefined' ? as : undefined,
from: typeof from !== 'undefined' ? from : as
};
},
importEquals(name, from) {
return {
kind: 'import=',
name,
from
};
},
import(from) {
return {
kind: 'import',
from
};
},
imports(imports) {
return {
kind: 'imports',
members: imports
};
},
union(members) {
return {
kind: 'union',
members
};
},
intersection(members) {
return {
kind: 'intersection',
members
};
},
typeof(type) {
return {
kind: 'typeof',
type
};
},
tripleSlashReferencePathDirective(path) {
return {
kind: "triple-slash-reference-path",
path
};
},
tripleSlashReferenceTypesDirective(types) {
return {
kind: "triple-slash-reference-types",
types
};
},
tripleSlashReferenceNoDefaultLibDirective(value = true) {
return {
kind: "triple-slash-reference-no-default-lib",
value
};
},
tripleSlashAmdModuleDirective(name) {
return {
kind: "triple-slash-amd-module",
name
};
}
};
exports.type = {
array(type) {
return {
kind: "array",
type
};
},
stringLiteral(string) {
return {
kind: "string-literal",
value: string
};
},
numberLiteral(number) {
return {
kind: "number-literal",
value: number
};
},
string: "string",
number: "number",
boolean: "boolean",
any: "any",
void: "void",
object: "object",
null: "null",
undefined: "undefined",
true: "true",
false: "false",
this: "this"
};
exports.reservedWords = ['abstract', 'await', 'boolean', 'break', 'byte', 'case',
'catch', 'char', 'class', 'const', 'continue', 'debugger', 'default',
'delete', 'do', 'double', 'else', 'enum', 'export', 'extends', 'false',
'final', 'finally', 'float', 'for', 'function', 'goto', 'if', 'implements',
'import', 'in', 'instanceof', 'int', 'interface', 'let', 'long', 'native',
'new', 'null', 'package', 'private', 'protected', 'public', 'return', 'short',
'static', 'super', 'switch', 'synchronized', 'this', 'throw', 'throws',
'transient', 'true', 'try', 'typeof', 'var', 'void', 'volatile', 'while', 'with', 'yield'];
/** IdentifierName can be written as unquoted property names, but may be reserved words. */
function isIdentifierName(s) {
return /^[$A-Z_][0-9A-Z_$]*$/i.test(s);
}
exports.isIdentifierName = isIdentifierName;
/** Identifiers are e.g. legal variable names. They may not be reserved words */
function isIdentifier(s) {
return isIdentifierName(s) && exports.reservedWords.indexOf(s) < 0;
}
exports.isIdentifier = isIdentifier;
function quoteIfNeeded(s) {
if (isIdentifierName(s)) {
return s;
}
else {
// JSON.stringify handles escaping quotes for us. Handy!
return JSON.stringify(s);
}
}
var ContextFlags;
(function (ContextFlags) {
ContextFlags[ContextFlags["None"] = 0] = "None";
ContextFlags[ContextFlags["Module"] = 1] = "Module";
ContextFlags[ContextFlags["InAmbientNamespace"] = 2] = "InAmbientNamespace";
})(ContextFlags = exports.ContextFlags || (exports.ContextFlags = {}));
function emit(rootDecl, { rootFlags = ContextFlags.None, tripleSlashDirectives = [] } = {}) {
let output = "";
let indentLevel = 0;
const isModuleWithModuleFlag = rootDecl.kind === 'module' && rootFlags === ContextFlags.Module;
// For a module root declaration we must omit the module flag.
const contextStack = isModuleWithModuleFlag ? [] : [rootFlags];
tripleSlashDirectives.forEach(writeTripleSlashDirective);
writeDeclaration(rootDecl);
newline();
return output;
function getContextFlags() {
return contextStack.reduce((a, b) => a | b, ContextFlags.None);
}
function tab() {
for (let i = 0; i < indentLevel; i++) {
output = output + ' ';
}
}
function print(s) {
output = output + s;
}
function start(s) {
tab();
print(s);
}
function classFlagsToString(flags = DeclarationFlags.None) {
let out = '';
if (flags && flags & DeclarationFlags.Abstract) {
out += 'abstract ';
}
return out;
}
function memberFlagsToString(flags = DeclarationFlags.None) {
let out = '';
if (flags & DeclarationFlags.Private) {
out += 'private ';
}
else if (flags & DeclarationFlags.Protected) {
out += 'protected ';
}
if (flags & DeclarationFlags.Static) {
out += 'static ';
}
if (flags & DeclarationFlags.Abstract) {
out += 'abstract ';
}
if (flags & DeclarationFlags.ReadOnly) {
out += 'readonly ';
}
return out;
}
function startWithDeclareOrExport(s, flags = DeclarationFlags.None) {
if (getContextFlags() & ContextFlags.InAmbientNamespace) {
// Already in an all-export context
start(s);
}
else if (flags & DeclarationFlags.Export) {
start(`export ${s}`);
}
else if (flags & DeclarationFlags.ExportDefault) {
start(`export default ${s}`);
}
else if (getContextFlags() & ContextFlags.Module) {
start(s);
}
else {
start(`declare ${s}`);
}
}
function newline() {
output = output + exports.config.outputEol;
}
function needsParens(d) {
if (typeof d === 'string') {
return false;
}
switch (d.kind) {
case "array":
case "alias":
case "interface":
case "class":
case "union":
return true;
default:
return false;
}
}
function printDeclarationComments(decl) {
if (decl.comment) {
start(`// ${decl.comment}`);
newline();
}
if (decl.jsDocComment) {
if (exports.config.wrapJsDocComments) {
start('/**');
newline();
for (const line of decl.jsDocComment.split(/\r?\n/g)) {
start(` * ${line}`);
newline();
}
start(' */');
}
else {
start(decl.jsDocComment);
}
newline();
}
}
function hasFlag(haystack, needle) {
if (haystack === undefined) {
return false;
}
return !!(needle & haystack);
}
function printObjectTypeMembers(members) {
print('{');
newline();
indentLevel++;
for (const member of members) {
printMember(member);
}
indentLevel--;
tab();
print('}');
function printMember(member) {
switch (member.kind) {
case 'index-signature':
printDeclarationComments(member);
tab();
print(`[${member.name}: `);
writeReference(member.indexType);
print(']: ');
writeReference(member.valueType);
print(';');
newline();
return;
case "call-signature": {
printDeclarationComments(member);
tab();
writeTypeParameters(member.typeParameters);
print("(");
let first = true;
for (const param of member.parameters) {
if (!first)
print(", ");
first = false;
print(param.name);
print(": ");
writeReference(param.type);
}
print("): ");
writeReference(member.returnType);
print(";");
newline();
return;
}
case 'method':
printDeclarationComments(member);
tab();
print(quoteIfNeeded(member.name));
if (hasFlag(member.flags, DeclarationFlags.Optional))
print('?');
writeTypeParameters(member.typeParameters);
print('(');
let first = true;
for (const param of member.parameters) {
if (!first)
print(', ');
first = false;
writeParameter(param);
}
print('): ');
writeReference(member.returnType);
print(';');
newline();
return;
case 'property':
printDeclarationComments(member);
tab();
if (hasFlag(member.flags, DeclarationFlags.ReadOnly))
print('readonly ');
print(quoteIfNeeded(member.name));
if (hasFlag(member.flags, DeclarationFlags.Optional))
print('?');
print(': ');
writeReference(member.type);
print(';');
newline();
return;
}
throw new Error(`Unknown member kind ${member.kind}`);
}
}
function writeUnionReference(d) {
if (typeof d !== "string" && d.kind === "function-type") {
print('(');
writeReference(d);
print(')');
}
else {
writeReference(d);
}
}
function writeReference(d) {
if (typeof d === 'string') {
print(d);
}
else {
const e = d;
switch (e.kind) {
case "type-parameter":
case "class":
case "interface":
case "name":
case "alias":
print(e.name);
break;
case "array":
if (needsParens(e.type))
print('(');
writeReference(e.type);
if (needsParens(e.type))
print(')');
print('[]');
break;
case "object":
printObjectTypeMembers(e.members);
break;
case "string-literal":
print(JSON.stringify(e.value));
break;
case "number-literal":
if (isNaN(e.value))
print("typeof NaN");
else if (!isFinite(e.value))
print("typeof Infinity");
else
print(e.value.toString());
break;
case "function-type":
writeFunctionType(e);
break;
case "union":
writeDelimited(e.members, ' | ', writeUnionReference);
break;
case "intersection":
writeDelimited(e.members, ' & ', writeUnionReference);
break;
case "typeof":
print("typeof ");
writeReference(e.type);
break;
default:
throw new Error(`Unknown kind ${d.kind}`);
}
}
}
function writeTypeParameters(params) {
if (params.length === 0)
return;
print('<');
let first = true;
for (const p of params) {
if (!first)
print(', ');
print(p.name);
if (p.baseType) {
print(' extends ');
if (p.baseType.kind === 'type-parameter')
print(p.baseType.name);
else
writeReference(p.baseType);
}
first = false;
}
print('>');
}
function writeInterface(d) {
printDeclarationComments(d);
startWithDeclareOrExport(`interface ${d.name} `, d.flags);
if (d.baseTypes && d.baseTypes.length) {
print(`extends `);
let first = true;
for (const baseType of d.baseTypes) {
if (!first)
print(', ');
writeReference(baseType);
first = false;
}
}
printObjectTypeMembers(d.members);
newline();
}
function writeFunctionType(f) {
print('(');
writeDelimited(f.parameters, ', ', writeParameter);
print(')');
print('=>');
writeReference(f.returnType);
}
function writeFunction(f) {
printDeclarationComments(f);
if (!isIdentifier(f.name)) {
start(`/* Illegal function name '${f.name}' can't be used here`);
newline();
}
startWithDeclareOrExport(`function ${f.name}`, f.flags);
writeTypeParameters(f.typeParameters);
print('(');
writeDelimited(f.parameters, ', ', writeParameter);
print('): ');
writeReference(f.returnType);
print(';');
newline();
if (!isIdentifier(f.name)) {
start(`*/`);
newline();
}
}
function writeParameter(p) {
const flags = p.flags || DeclarationFlags.None;
print(`${flags & ParameterFlags.Rest ? '...' : ''}${p.name}${flags & ParameterFlags.Optional ? '?' : ''}: `);
writeReference(p.type);
}
function writeDelimited(arr, sep, printer) {
let first = true;
for (const el of arr) {
if (!first) {
print(sep);
}
printer(el);
first = false;
}
}
function writeClass(c) {
printDeclarationComments(c);
startWithDeclareOrExport(`${classFlagsToString(c.flags)}class ${c.name}`, c.flags);
writeTypeParameters(c.typeParameters);
if (c.baseType) {
print(' extends ');
writeReference(c.baseType);
}
if (c.implements && c.implements.length) {
print(' implements ');
let first = true;
for (const impl of c.implements) {
if (!first)
print(', ');
writeReference(impl);
first = false;
}
}
print(' {');
newline();
indentLevel++;
for (const m of c.members) {
writeClassMember(m);
newline();
}
indentLevel--;
start('}');
newline();
}
function writeClassMember(c) {
switch (c.kind) {
case "property":
return writePropertyDeclaration(c);
case "method":
return writeMethodDeclaration(c);
case "constructor":
return writeConstructorDeclaration(c);
}
}
function writeConstructorDeclaration(ctor) {
printDeclarationComments(ctor);
start('constructor(');
writeDelimited(ctor.parameters, ', ', writeParameter);
print(');');
newline();
}
function writePropertyDeclaration(p) {
printDeclarationComments(p);
start(`${memberFlagsToString(p.flags)}${quoteIfNeeded(p.name)}: `);
writeReference(p.type);
print(';');
newline();
}
function writeMethodDeclaration(m) {
printDeclarationComments(m);
start(`${memberFlagsToString(m.flags)}${quoteIfNeeded(m.name)}`);
writeTypeParameters(m.typeParameters);
print('(');
writeDelimited(m.parameters, ', ', writeParameter);
print('): ');
writeReference(m.returnType);
print(';');
}
function writeNamespace(ns) {
printDeclarationComments(ns);
startWithDeclareOrExport(`namespace ${ns.name} {`, ns.flags);
contextStack.push(ContextFlags.InAmbientNamespace);
newline();
indentLevel++;
for (const member of ns.members) {
writeDeclaration(member);
newline();
}
indentLevel--;
start(`}`);
contextStack.pop();
newline();
}
function writeConst(c) {
printDeclarationComments(c);
startWithDeclareOrExport(`const ${c.name}: `, c.flags);
writeReference(c.type);
print(';');
newline();
}
function writeVar(c) {
printDeclarationComments(c);
startWithDeclareOrExport(`var ${c.name}: `, c.flags);
writeReference(c.type);
print(';');
newline();
}
function writeAlias(a) {
printDeclarationComments(a);
startWithDeclareOrExport(`type ${a.name}`, a.flags);
writeTypeParameters(a.typeParameters);
print(' = ');
writeReference(a.type);
print(';');
newline();
}
function writeExportEquals(e) {
start(`export = ${e.target};`);
newline();
}
function writeExportDefault(e) {
start(`export default ${e.name};`);
newline();
}
function writeExportName(e) {
start(`export { ${e.name}`);
if (e.as) {
print(` as ${e.as}`);
}
print(' };');
newline();
}
function writeModule(m) {
printDeclarationComments(m);
startWithDeclareOrExport(`module '${m.name}' {`, m.flags);
contextStack.push(ContextFlags.Module);
newline();
indentLevel++;
for (const member of m.members) {
writeDeclaration(member);
newline();
}
indentLevel--;
start(`}`);
contextStack.pop();
newline();
}
function groupBy(xs, key) {
return xs.reduce(function (rv, x) {
(rv[x[key]] = rv[x[key]] || []).push(x);
return rv;
}, {});
}
;
function writeImports(i) {
const groups = groupBy(i.members, 'from');
Object.keys(groups).forEach(key => {
const groupedImports = groups[key];
const namedImports = [];
let defaultImport;
let importAll;
groupedImports.forEach(i => {
if (i.kind === 'importNamed') {
const tmp = i;
const named = namedImports.find(x => x.name === tmp.name);
if (!named) {
namedImports.push(tmp);
}
}
else if (i.kind === 'importDefault' && !defaultImport) {
defaultImport = i;
}
else if (i.kind === 'importAll') {
importAll = i;
}
});
if (importAll) {
writeImportAll(importAll);
}
else if (defaultImport && namedImports.length > 0) {
writeNamedImportsWithDefault(namedImports, defaultImport);
}
else if (defaultImport) {
writeImportDefault(defaultImport);
}
else {
writeNamedImports(namedImports);
}
});
}
function writeImportAll(i) {
start(`import * as ${i.name} from '${i.from}';`);
newline();
}
function writeImportDefault(i) {
start(`import ${i.name} from '${i.from}';`);
newline();
}
function writeImportNamed(i) {
start(`import { ${i.name}`);
if (i.as) {
print(` as ${i.as}`);
}
print(` } from '${i.from}';`);
newline();
}
function writeNamedImports(i) {
let namedImports = '';
i.forEach(x => namedImports += `${x.name}, `);
namedImports = namedImports.slice(0, -2);
start(`import { ${namedImports}`);
print(` } from '${i[0].from}';`);
newline();
}
function writeNamedImportsWithDefault(i, d) {
let namedImports = '';
i.forEach(x => namedImports += `${x.name}, `);
namedImports = namedImports.slice(0, -2);
start(`import ${d.name}, { ${namedImports}`);
print(` } from '${d.from}';`);
newline();
}
function writeImportEquals(i) {
start(`import ${i.name} = require('${i.from}');`);
newline();
}
function writeImport(i) {
start(`import '${i.from}';`);
newline();
}
function writeEnum(e) {
printDeclarationComments(e);
startWithDeclareOrExport(`${e.constant ? 'const ' : ''}enum ${e.name} {`, e.flags);
newline();
indentLevel++;
for (const member of e.members) {
writeEnumValue(member);
}
indentLevel--;
start(`}`);
newline();
}
function writeEnumValue(e) {
printDeclarationComments(e);
start(e.name);
if (e.value !== undefined) {
if (typeof e.value === 'string') {
print(` = "${e.value}"`);
}
else {
print(` = ${e.value}`);
}
}
print(',');
newline();
}
function writeTripleSlashDirective(t) {
const type = t.kind === "triple-slash-amd-module" ? "amd-module" : "reference";
start(`/// <${type}`);
switch (t.kind) {
case "triple-slash-reference-path":
print(` path="${t.path}"`);
break;
case "triple-slash-reference-types":
print(` types="${t.types}"`);
break;
case "triple-slash-reference-no-default-lib":
print(` no-default-lib="${t.value}"`);
break;
case "triple-slash-amd-module":
if (t.name) {
print(` name="${t.name}"`);
}
break;
default:
throw new Error(`Unknown triple slash directive kind ${t.kind}`);
}
print(" />");
newline();
}
function writeDeclaration(d) {
if (typeof d === 'string') {
return print(d);
}
else {
switch (d.kind) {
case "interface":
return writeInterface(d);
case "function":
return writeFunction(d);
case "class":
return writeClass(d);
case "namespace":
return writeNamespace(d);
case "const":
return writeConst(d);
case "var":
return writeVar(d);
case "alias":
return writeAlias(d);
case "export=":
return writeExportEquals(d);
case "exportDefault":
return writeExportDefault(d);
case "exportName":
return writeExportName(d);
case "module":
return writeModule(d);
case "imports":
return writeImports(d);
case "importAll":
return writeImportAll(d);
case "importDefault":
return writeImportDefault(d);
case "importNamed":
return writeImportNamed(d);
case "import=":
return writeImportEquals(d);
case "import":
return writeImport(d);
case "enum":
return writeEnum(d);
default:
throw new Error(`Unknown declaration kind ${d.kind}`);
}
}
}
}
exports.emit = emit;