UNPKG

react-dts-generator

Version:
980 lines (979 loc) 29.8 kB
"use strict"; 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;