alm
Version:
The best IDE for TypeScript
137 lines (121 loc) • 4.28 kB
text/typescript
/**
* NOTE: Pulled straight out of typedoc 🌹
* https://github.com/TypeStrong/typedoc/blob/2e855cf8c62c7813ac62cb1ef911c9a0c5e034c2/src/lib/converter/factories/comment.ts
*/
/**
* Returns the parsed comment for a given node.
*/
export function getParsedComment(node: ts.Node, sourceFile: ts.SourceFile): string | null {
const rawComment = getRawComment(node, sourceFile);
if (!rawComment) {
return rawComment;
}
return parseComment(rawComment);
}
/**
* Resurected from
* https://github.com/Microsoft/TypeScript/commit/bffde588cc60c524ba120413681871c6d969274b
*/
export function getCommentsFromJSDoc(node: ts.Node): string[] {
// return ts.map(ts.getAllJSDocs(node), doc => doc.comment); // Its dead jim. Let it go.
return ['Feature disabled as it was deleted from TS https://github.com/Microsoft/TypeScript/pull/21119#discussion_r160754254'];
}
/**
* Return the raw comment string for the given node.
*
* @param node The node whose comment should be resolved.
* @returns The raw comment string or NULL if no comment could be found.
*/
export function getRawComment(node: ts.Node, sourceFile: ts.SourceFile): string | null {
if (node.parent && node.parent.kind === ts.SyntaxKind.VariableDeclarationList) {
node = node.parent.parent;
} else if (node.kind === ts.SyntaxKind.ModuleDeclaration) {
if (!isTopmostModuleDeclaration(<ts.ModuleDeclaration>node)) {
return null;
} else {
node = getRootModuleDeclaration(<ts.ModuleDeclaration>node);
}
}
var comments = getCommentsFromJSDoc(node);
if (comments && comments.length) {
var comment: string;
if (node.kind == ts.SyntaxKind.SourceFile) {
if (comments.length == 1) return null;
comment = comments[0];
} else {
comment = comments[comments.length - 1];
}
return comment;
} else {
return null;
}
}
/**
* Return the root module declaration of the given module declaration.
*
* In the following example this function would always return module
* <code>A</code> no matter which of the modules was passed in.
*
* ```
* module A.B.C { }
* ```
*/
function getRootModuleDeclaration(node: ts.ModuleDeclaration): ts.Node {
while (node.parent && node.parent.kind == ts.SyntaxKind.ModuleDeclaration) {
let parent = <ts.ModuleDeclaration>node.parent;
if (node.name.pos == parent.name.end + 1) {
node = parent;
} else {
break;
}
}
return node;
}
/**
* Check whether the given module declaration is the topmost.
*
* This funtion returns TRUE if there is no trailing module defined, in
* the following example this would be the case only for module <code>C</code>.
*
* ```
* module A.B.C { }
* ```
*
* @param node The module definition that should be tested.
* @return TRUE if the given node is the topmost module declaration, FALSE otherwise.
*/
function isTopmostModuleDeclaration(node: ts.ModuleDeclaration): boolean {
if (node.nextContainer && node.nextContainer.kind == ts.SyntaxKind.ModuleDeclaration) {
let next = <ts.ModuleDeclaration>node.nextContainer;
if (node.name.end + 1 == next.name.pos) {
return false;
}
}
return true;
}
/**
* Modified from original to return `string` instead of `Comment` class
* We lose `tag` information, but that is fine by me for now.
*/
export function parseComment(text: string): string {
let comment = '';
function consumeTypeData(line: string): string {
line = line.replace(/^\{[^\}]*\}+/, '');
line = line.replace(/^\[[^\[][^\]]*\]+/, '');
return line.trim();
}
function readBareLine(line: string) {
comment += (comment == '' ? '' : '\n') + line;
}
function readLine(line: string) {
line = line.replace(/^\s*\*? ?/, '');
line = line.replace(/\s*$/, '');
readBareLine(line);
}
// text = text.replace(/^\s*\/\*+\s*(\r\n?|\n)/, '');
// text = text.replace(/(\r\n?|\n)\s*\*+\/\s*$/, '');
text = text.replace(/^\s*\/\*+/, '');
text = text.replace(/\*+\/\s*$/, '');
text.split(/\r\n?|\n/).forEach(readLine);
return comment;
}