in jsstub-generator/generate.ts [313:510]
let visit = function(sourceFile: ts.SourceFile, modulePrefix: string, iface: string) {
return (node: ts.Node) => {
switch (node.kind) {
// Handle type aliases so that they can be resolved after parsing is done
case ts.SyntaxKind.TypeAliasDeclaration:
result.getModule(modulePrefix).aliases.set(
(node as ts.TypeAliasDeclaration).name.getText(),
(node as ts.TypeAliasDeclaration).type
);
break;
// Handle variable declarations - they are assumed to be instances
// declared at the module level
case ts.SyntaxKind.VariableStatement:
{
(<ts.VariableStatement>node).declarationList.declarations.forEach(decl => {
let declName = decl.name.getText();
if (declName !== '.prototype' && declName !== '.constructor') {
let propertySymbol = checker.getSymbolAtLocation(decl);
let propertydoc = '';
if (propertySymbol) {
propertydoc = ts.displayPartsToString(propertySymbol.getDocumentationComment(checker));
}
const propertyInfo = new MemberInfo(
false,
decl.type!,
propertydoc,
sourceFile.fileName
);
result.getModule(modulePrefix).variables.set(declName, propertyInfo);
};
});
}
break;
// Handle function declarations - they are assumed to be unbound
// functions declared at the module level
case ts.SyntaxKind.FunctionDeclaration:
if ((<ts.FunctionDeclaration>node).name) {
let functionName = propertyNameToString((<ts.FunctionDeclaration>node).name!);
let functionSymbol = ((node as any).symbol as ts.Symbol);
const parameters: { name: string, type: ts.TypeNode, doc: string, optional: boolean }[] = [];
for (const param of (<ts.MethodSignature>node).parameters) {
if (param.name.getText() == 'this') {
continue;
}
let paramSymbol = ((param as any).symbol) as ts.Symbol;
parameters.push({
name: param.name.getText(),
type: param.type!,
doc: ts.displayPartsToString(paramSymbol.getDocumentationComment(checker)),
optional: !!param.questionToken
});
}
const functionInfo = new MemberInfo(
true,
(<ts.PropertySignature>node).type!,
ts.displayPartsToString(functionSymbol.getDocumentationComment(checker)),
sourceFile.fileName,
parameters
);
result.getModule(modulePrefix).functions.set(functionName, functionInfo);
}
break;
// Handle constructors
case ts.SyntaxKind.ConstructSignature:
const parameters: { name: string, type: ts.TypeNode, doc: string, optional: boolean }[] = [];
for (const param of (<ts.ConstructSignatureDeclaration>node).parameters) {
if (param.name.getText() == 'this') {
continue;
}
let paramSymbol = ((param as any).symbol) as ts.Symbol;
parameters.push({
name: param.name.getText(),
type: param.type!,
doc: ts.displayPartsToString(paramSymbol.getDocumentationComment(checker)),
optional: !!param.questionToken
});
}
let ifaceBase = iface;
if(iface.endsWith('Constructor')) {
ifaceBase = iface.substring(0, iface.length - 11);
}
const mi = new MemberInfo(
true,
(<ts.ConstructSignatureDeclaration>node).type!,
'',
sourceFile.fileName,
parameters
);
result.getModule(modulePrefix).getClass(ifaceBase).addFile(sourceFile.fileName);
result.getModule(modulePrefix).getClass(ifaceBase).constructorInfo.push(mi);
break;
// Handle methods
case ts.SyntaxKind.MethodSignature:
let functionName = propertyNameToString((<ts.MethodSignature>node).name);
if (functionName !== '.prototype' && functionName !== '.constructor') {
let functionSymbol = ((node as any).symbol as ts.Symbol);
const parameters: { name: string, type: ts.TypeNode, doc: string, optional: boolean }[] = [];
for (const param of (<ts.MethodSignature>node).parameters) {
if (param.name.getText() == 'this') {
continue;
}
let paramSymbol = ((param as any).symbol) as ts.Symbol;
parameters.push({
name: param.name.getText(),
type: param.type!,
doc: ts.displayPartsToString(paramSymbol.getDocumentationComment(checker)),
optional: !!param.questionToken
});
}
const functionInfo = new MemberInfo(
true,
(<ts.PropertySignature>node).type!,
ts.displayPartsToString(functionSymbol.getDocumentationComment(checker)),
sourceFile.fileName,
parameters
);
result.getModule(modulePrefix).getClass(iface).addFile(sourceFile.fileName);
result.getModule(modulePrefix).getClass(iface).properties.set(functionName, functionInfo);
}
break;
// Handle properties
case ts.SyntaxKind.PropertySignature:
let propertyName = propertyNameToString((<ts.PropertySignature>node).name);
if (propertyName !== '.prototype' && propertyName !== '.constructor') {
let propertySymbol = checker.getSymbolAtLocation(node);
let propertydoc = '';
if (propertySymbol) {
propertydoc = ts.displayPartsToString(propertySymbol.getDocumentationComment(checker));
}
const propertyInfo = new MemberInfo(
false,
(<ts.PropertySignature>node).type!,
propertydoc,
sourceFile.fileName
);
result.getModule(modulePrefix).getClass(iface).addFile(sourceFile.fileName);
result.getModule(modulePrefix).getClass(iface).properties.set(propertyName, propertyInfo);
}
break;
// Handle module declarations - only handled to extract the name of the module
case ts.SyntaxKind.ModuleDeclaration:
let moduleName = (<ts.ModuleDeclaration>node).name.text;
modulePrefix = moduleName;
break;
// Handle interface declaration
case ts.SyntaxKind.InterfaceDeclaration:
iface = (<ts.InterfaceDeclaration>node).name.text;
break;
default:
}
switch (node.kind) {
// For modules decend into their children
case ts.SyntaxKind.ModuleBlock:
ts.forEachChild(node, visit(sourceFile, modulePrefix, iface));
break;
case ts.SyntaxKind.ModuleDeclaration:
ts.forEachChild(node, visit(sourceFile, modulePrefix, iface));
modulePrefix = '';
break;
// For interfaces decend into their children and extract the inheritence tree
case ts.SyntaxKind.InterfaceDeclaration:
ts.forEachChild(node, visit(sourceFile, modulePrefix, iface));
const id = node as ts.InterfaceDeclaration;
let idSymbol = ((id as any).symbol) as ts.Symbol;
let idDoc = '';
if (idSymbol) {
idDoc = ts.displayPartsToString(idSymbol.getDocumentationComment(checker));
result.getModule(modulePrefix).getClass(iface).doc = idDoc;
}
result.getModule(modulePrefix).getClass(iface).addFile(sourceFile.fileName);
if (id.heritageClauses) {
id.heritageClauses.forEach(hc => {
hc.types.forEach(t => result.getModule(modulePrefix).getClass(iface).addInterits(t.expression.getText()));
});
}
iface = '';
break;
}
}
};