1// @module: commonjs 2// @skipLibCheck: true 3// @noImplicitAny:true 4// @strictNullChecks:true 5 6// @filename: node_modules/typescript/package.json 7{ 8 "name": "typescript", 9 "types": "/.ts/typescript.d.ts" 10} 11 12// @filename: APISample_jsdoc.ts 13/* 14 * Note: This test is a public API sample. The original sources can be found 15 * at: https://github.com/YousefED/typescript-json-schema 16 * https://github.com/vega/ts-json-schema-generator 17 * Please log a "breaking change" issue for any API breaking change affecting this issue 18 */ 19 20declare var console: any; 21 22import * as ts from "typescript"; 23 24// excerpted from https://github.com/YousefED/typescript-json-schema 25// (converted from a method and modified; for example, `this: any` to compensate, among other changes) 26function parseCommentsIntoDefinition(this: any, 27 symbol: ts.Symbol, 28 definition: {description?: string, [s: string]: string | undefined}, 29 otherAnnotations: { [s: string]: true}): void { 30 if (!symbol) { 31 return; 32 } 33 34 // the comments for a symbol 35 let comments = symbol.getDocumentationComment(undefined); 36 37 if (comments.length) { 38 definition.description = comments.map(comment => comment.kind === "lineBreak" ? comment.text : comment.text.trim().replace(/\r\n/g, "\n")).join(""); 39 } 40 41 // jsdocs are separate from comments 42 const jsdocs = symbol.getJsDocTags(this.checker); 43 jsdocs.forEach(doc => { 44 // if we have @TJS-... annotations, we have to parse them 45 const { name, text } = doc; 46 if (this.userValidationKeywords[name]) { 47 definition[name] = this.parseValue(text); 48 } else { 49 // special annotations 50 otherAnnotations[doc.name] = true; 51 } 52 }); 53} 54 55 56// excerpted from https://github.com/vega/ts-json-schema-generator 57export interface Annotations { 58 [name: string]: any; 59} 60function getAnnotations(this: any, node: ts.Node): Annotations | undefined { 61 const symbol: ts.Symbol = (node as any).symbol; 62 if (!symbol) { 63 return undefined; 64 } 65 66 const jsDocTags: ts.JSDocTagInfo[] = symbol.getJsDocTags(this.checker); 67 if (!jsDocTags || !jsDocTags.length) { 68 return undefined; 69 } 70 71 const annotations: Annotations = jsDocTags.reduce((result: Annotations, jsDocTag: ts.JSDocTagInfo) => { 72 const value = this.parseJsDocTag(jsDocTag); 73 if (value !== undefined) { 74 result[jsDocTag.name] = value; 75 } 76 77 return result; 78 }, {}); 79 return Object.keys(annotations).length ? annotations : undefined; 80} 81 82// these examples are artificial and mostly nonsensical 83function parseSpecificTags(node: ts.Node) { 84 if (node.kind === ts.SyntaxKind.Parameter) { 85 return ts.getJSDocParameterTags(node as ts.ParameterDeclaration); 86 } 87 if (node.kind === ts.SyntaxKind.FunctionDeclaration) { 88 const func = node as ts.FunctionDeclaration; 89 if (ts.hasJSDocParameterTags(func)) { 90 const flat: ts.JSDocTag[] = []; 91 for (const tags of func.parameters.map(ts.getJSDocParameterTags)) { 92 if (tags) flat.push(...tags); 93 } 94 return flat; 95 } 96 } 97} 98 99function getReturnTypeFromJSDoc(node: ts.Node) { 100 if (node.kind === ts.SyntaxKind.FunctionDeclaration) { 101 return ts.getJSDocReturnType(node); 102 } 103 let type = ts.getJSDocType(node); 104 if (type && type.kind === ts.SyntaxKind.FunctionType) { 105 return (type as ts.FunctionTypeNode).type; 106 } 107} 108 109function getAllTags(node: ts.Node) { 110 ts.getJSDocTags(node); 111} 112 113function getSomeOtherTags(node: ts.Node) { 114 const tags: (ts.JSDocTag | undefined)[] = []; 115 tags.push(ts.getJSDocAugmentsTag(node)); 116 tags.push(ts.getJSDocClassTag(node)); 117 tags.push(ts.getJSDocReturnTag(node)); 118 const type = ts.getJSDocTypeTag(node); 119 if (type) { 120 tags.push(type); 121 } 122 tags.push(ts.getJSDocTemplateTag(node)); 123 return tags; 124} 125