1 | {"version":3,"file":"docs.js","sourceRoot":"","sources":["../src/docs.ts"],"names":[],"mappings":"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","sourcesContent":["/**\n * Doc Comment parsing\n *\n * I tried using TSDoc here.\n *\n * Pro:\n * - Future standard.\n * - Does validating parsing and complains on failure.\n * - Has a more flexible interpretation of the @example tag (starts in text mode).\n *\n * Con:\n * - Different tags from JSDoc (@defaultValue instead of @default, \"@param name\n * description\" instead \"@param name description\".\n * - @example tag has a different interpretation than VSCode and JSDoc\n * (VSCode/JSDoc starts in code mode), which is confusing for syntax\n * highlighting in the editor.\n * - Allows no unknown tags.\n * - Wants to be in charge of parsing TypeScript, integrating into other build is\n * possible but harder.\n * - Parse to a DOM with no easy way to roundtrip back to equivalent MarkDown.\n *\n * Especially the last point: while parsing to and storing the parsed docs DOM\n * in the jsii assembly is superior in the long term (for example for\n * converting to different output formats, JavaDoc, C# docs, refdocs which all\n * accept slightly different syntaxes), right now we can get 80% of the bang\n * for 10% of the buck by just reading, storing and reproducing MarkDown, which\n * is Readable Enough(tm).\n *\n * If we ever want to attempt TSDoc again, this would be a good place to look at:\n *\n * https://github.com/Microsoft/tsdoc/blob/master/api-demo/src/advancedDemo.ts\n */\nimport * as spec from '@jsii/spec';\nimport * as ts from 'typescript';\n\n/**\n * Tags that we recognize\n */\nenum DocTag {\n PARAM = 'param',\n DEFAULT = 'default',\n DEFAULT_VALUE = 'defaultValue',\n DEPRECATED = 'deprecated',\n RETURNS = 'returns',\n RETURN = 'return',\n STABLE = 'stable',\n EXPERIMENTAL = 'experimental',\n SEE = 'see',\n SUBCLASSABLE = 'subclassable',\n EXAMPLE = 'example',\n STABILITY = 'stability',\n STRUCT = 'struct',\n\n // Not forwarded, this is compiler-internal.\n JSII = 'jsii',\n}\n\nconst RECOGNIZED_TAGS: ReadonlySet<String> = new Set(Object.values(DocTag));\n\n/**\n * Parse all doc comments that apply to a symbol into JSIIDocs format\n */\nexport function parseSymbolDocumentation(sym: ts.Symbol, typeChecker: ts.TypeChecker): DocsParsingResult {\n const comment = ts.displayPartsToString(sym.getDocumentationComment(typeChecker)).trim();\n const tags = reabsorbExampleTags(sym.getJsDocTags());\n\n // Right here we'll just guess that the first declaration site is the most important one.\n return parseDocParts(comment, tags);\n}\n\n/**\n * Return the list of parameter names that are referenced in the docstring for this symbol\n */\nexport function getReferencedDocParams(sym: ts.Symbol): string[] {\n const ret = new Array<string>();\n for (const tag of sym.getJsDocTags()) {\n if (tag.name === DocTag.PARAM) {\n const parts = ts.displayPartsToString(tag.text).split(' ');\n ret.push(parts[0]);\n }\n }\n return ret;\n}\n\nfunction parseDocParts(comments: string | undefined, tags: ts.JSDocTagInfo[]): DocsParsingResult {\n const diagnostics = new Array<string>();\n const docs: spec.Docs = {};\n const hints: TypeSystemHints = {};\n\n [docs.summary, docs.remarks] = splitSummary(comments);\n\n const tagNames = new Map<string, string | undefined>();\n for (const tag of tags) {\n // 'param' gets parsed as a tag and as a comment for a method\n // 'jsii' is internal-only and shouldn't surface in the API doc\n if (tag.name !== DocTag.PARAM && tag.name !== DocTag.JSII) {\n tagNames.set(tag.name, tag.text && ts.displayPartsToString(tag.text));\n }\n }\n\n function eatTag(...names: string[]): string | undefined {\n for (const name of names) {\n if (tagNames.has(name)) {\n const ret = tagNames.get(name);\n tagNames.delete(name);\n return ret ?? '';\n }\n }\n return undefined;\n }\n\n if (eatTag(DocTag.STRUCT) != null) {\n hints.struct = true;\n }\n\n docs.default = eatTag(DocTag.DEFAULT, DocTag.DEFAULT_VALUE);\n docs.deprecated = eatTag(DocTag.DEPRECATED);\n docs.example = eatTag(DocTag.EXAMPLE);\n docs.returns = eatTag(DocTag.RETURNS, DocTag.RETURN);\n docs.see = eatTag(DocTag.SEE);\n docs.subclassable = eatTag(DocTag.SUBCLASSABLE) !== undefined ? true : undefined;\n\n docs.stability = parseStability(eatTag(DocTag.STABILITY), diagnostics);\n // @experimental is a shorthand for '@stability experimental', same for '@stable'\n const experimental = eatTag(DocTag.EXPERIMENTAL) !== undefined;\n const stable = eatTag(DocTag.STABLE) !== undefined;\n // Can't combine them\n if (countBools(docs.stability !== undefined, experimental, stable) > 1) {\n diagnostics.push('Use only one of @stability, @experimental or @stable');\n }\n if (experimental) {\n docs.stability = spec.Stability.Experimental;\n }\n if (stable) {\n docs.stability = spec.Stability.Stable;\n }\n\n // Can combine '@stability deprecated' with '@deprecated <reason>'\n if (docs.deprecated !== undefined) {\n if (docs.stability !== undefined && docs.stability !== spec.Stability.Deprecated) {\n diagnostics.push(\"@deprecated tag requires '@stability deprecated' or no @stability at all.\");\n }\n docs.stability = spec.Stability.Deprecated;\n }\n\n if (docs.example?.includes('```')) {\n // This is currently what the JSDoc standard expects, and VSCode highlights it in\n // this way as well. TSDoc disagrees and says that examples start in text mode\n // which I tend to agree with, but that hasn't become a widely used standard yet.\n //\n // So we conform to existing reality.\n diagnostics.push('@example must be code only, no code block fences allowed.');\n }\n\n if (docs.deprecated?.trim() === '') {\n diagnostics.push('@deprecated tag needs a reason and/or suggested alternatives.');\n }\n\n if (tagNames.size > 0) {\n docs.custom = {};\n for (const [key, value] of tagNames.entries()) {\n docs.custom[key] = value ?? 'true'; // Key must have a value or it will be stripped from the assembly\n }\n }\n\n return { docs, diagnostics, hints };\n}\n\nexport interface DocsParsingResult {\n docs: spec.Docs;\n hints: TypeSystemHints;\n diagnostics?: string[];\n}\n\nexport interface TypeSystemHints {\n /**\n * Only present on interfaces. This indicates that interface must be handled as a struct/data type\n * even through it's name starts with a capital letter `I`.\n */\n struct?: boolean;\n}\n\n/**\n * Split the doc comment into summary and remarks\n *\n * Normally, we'd expect people to split into a summary line and detail lines using paragraph\n * markers. However, a LOT of people do not do this, and just paste a giant comment block into\n * the docstring. If we detect that situation, we will try and extract the first sentence (using\n * a period) as the summary.\n */\nexport function splitSummary(docBlock: string | undefined): [string | undefined, string | undefined] {\n if (!docBlock) {\n return [undefined, undefined];\n }\n const summary = summaryLine(docBlock);\n const remarks = uberTrim(docBlock.slice(summary.length));\n return [endWithPeriod(noNewlines(summary.trim())), remarks];\n}\n\n/**\n * Replace newlines with spaces for use in tables\n */\nfunction noNewlines(s: string) {\n return s.replace(/\\r?\\n/g, ' ');\n}\n\nfunction endWithPeriod(s: string) {\n return ENDS_WITH_PUNCTUATION_REGEX.test(s) ? s : `${s}.`;\n}\n\n/**\n * Trims a string and turns it into `undefined` if the result would have been an\n * empty string.\n */\nfunction uberTrim(str: string): string | undefined {\n str = str.trim();\n return str === '' ? undefined : str;\n}\n\nconst SUMMARY_MAX_WORDS = 20;\n\n/**\n * Find the summary line for a doc comment\n *\n * In principle we'll take the first paragraph, but if there are no paragraphs\n * (because people don't put in paragraph breaks) or the first paragraph is too\n * long, we'll take the first sentence (terminated by a punctuation).\n */\nfunction summaryLine(str: string) {\n const paras = str.split('\\n\\n');\n if (paras.length > 1 && paras[0].split(' ').length < SUMMARY_MAX_WORDS) {\n return paras[0];\n }\n\n const m = FIRST_SENTENCE_REGEX.exec(str);\n if (m) {\n return m[1];\n }\n\n return paras[0];\n}\n\nconst PUNCTUATION = ['!', '?', '.', ';'].map((s) => `\\\\${s}`).join('');\nconst ENDS_WITH_PUNCTUATION_REGEX = new RegExp(`[${PUNCTUATION}]$`);\nconst FIRST_SENTENCE_REGEX = new RegExp(`^([^${PUNCTUATION}]+[${PUNCTUATION}][ \\n\\r])`); // Needs a whitespace after the punctuation.\n\nfunction intBool(x: boolean): number {\n return x ? 1 : 0;\n}\n\nfunction countBools(...x: boolean[]) {\n return x.map(intBool).reduce((a, b) => a + b, 0);\n}\n\nfunction parseStability(s: string | undefined, diagnostics: string[]): spec.Stability | undefined {\n if (s === undefined) {\n return undefined;\n }\n\n switch (s) {\n case 'stable':\n return spec.Stability.Stable;\n case 'experimental':\n return spec.Stability.Experimental;\n case 'external':\n return spec.Stability.External;\n case 'deprecated':\n return spec.Stability.Deprecated;\n }\n diagnostics.push(`Unrecognized @stability: '${s}'`);\n return undefined;\n}\n\n/**\n * Unrecognized tags that follow an '@ example' tag will be absorbed back into the example value\n *\n * The TypeScript parser by itself is naive and will start parsing a new tag there.\n *\n * We do this until we encounter a supported @ keyword.\n */\nfunction reabsorbExampleTags(tags: ts.JSDocTagInfo[]): ts.JSDocTagInfo[] {\n const ret = [...tags];\n\n let i = 0;\n while (i < ret.length) {\n if (ret[i].name === 'example') {\n while (i + 1 < ret.length && !RECOGNIZED_TAGS.has(ret[i + 1].name)) {\n // Incorrectly classified as @tag, absorb back into example\n ret[i].text ??= [];\n ret[i].text!.push({\n text: `@${ret[i + 1].name}${ret[i + 1].text}`,\n kind: '',\n });\n ret.splice(i + 1, 1);\n }\n }\n i++;\n }\n\n return ret;\n}\n"]} |