Skip to content

Commit

Permalink
fix(app): main comment parsing for ```
Browse files Browse the repository at this point in the history
fix #1059
  • Loading branch information
vogloblinsky committed Jul 5, 2021
1 parent 909ae8a commit 3226d01
Show file tree
Hide file tree
Showing 3 changed files with 129 additions and 23 deletions.
46 changes: 28 additions & 18 deletions src/app/compiler/angular/deps/helpers/class-helper.ts
Expand Up @@ -447,8 +447,12 @@ export class ClassHelper {
let description = '';
let jsdoctags = [];
if (symbol) {
rawdescription = this.jsdocParserUtil.getMainCommentOfNode(classDeclaration);
description = marked(rawdescription);
rawdescription = this.jsdocParserUtil.getMainCommentOfNode(
classDeclaration,
sourceFile
);
const cleanedDescription = this.jsdocParserUtil.parseComment(rawdescription);
description = marked(cleanedDescription);
if (symbol.valueDeclaration && isIgnore(symbol.valueDeclaration)) {
return [{ ignore: true }];
}
Expand Down Expand Up @@ -958,9 +962,10 @@ export class ClassHelper {
deprecationMessage: ''
};
if (method.jsDoc) {
const rawDescription = this.jsdocParserUtil.getMainCommentOfNode(method);
const rawDescription = this.jsdocParserUtil.getMainCommentOfNode(method, sourceFile);
result.rawdescription = rawDescription;
result.description = marked(rawDescription);
const cleanedDescription = this.jsdocParserUtil.parseComment(rawDescription);
result.description = marked(cleanedDescription);
}
let jsdoctags = this.jsdocParserUtil.getJSDocs(method);
if (jsdoctags && jsdoctags.length >= 1 && jsdoctags[0].tags) {
Expand All @@ -986,10 +991,10 @@ export class ClassHelper {
};
const jsdoctags = this.jsdocParserUtil.getJSDocs(method);
if (method.jsDoc) {
const rawDescription = this.jsdocParserUtil.getMainCommentOfNode(method);

const rawDescription = this.jsdocParserUtil.getMainCommentOfNode(method, sourceFile);
result.rawdescription = rawDescription;
result.description = marked(rawDescription);
const cleanedDescription = this.jsdocParserUtil.parseComment(rawDescription);
result.description = marked(cleanedDescription);
}

if (jsdoctags && jsdoctags.length >= 1) {
Expand Down Expand Up @@ -1022,9 +1027,10 @@ export class ClassHelper {
let jsdoctags = this.jsdocParserUtil.getJSDocs(method);

if (method.jsDoc) {
const rawDescription = this.jsdocParserUtil.getMainCommentOfNode(method);
const rawDescription = this.jsdocParserUtil.getMainCommentOfNode(method, sourceFile);
result.rawdescription = rawDescription;
result.description = marked(rawDescription);
const cleanedDescription = this.jsdocParserUtil.parseComment(rawDescription);
result.description = marked(cleanedDescription);
}

if (method.modifiers) {
Expand Down Expand Up @@ -1079,9 +1085,10 @@ export class ClassHelper {
jsdoctags = this.jsdocParserUtil.getJSDocs(property);

if (property.jsDoc) {
const rawDescription = this.jsdocParserUtil.getMainCommentOfNode(property);
const rawDescription = this.jsdocParserUtil.getMainCommentOfNode(property, sourceFile);
result.rawdescription = rawDescription;
result.description = marked(rawDescription);
const cleanedDescription = this.jsdocParserUtil.parseComment(rawDescription);
result.description = marked(cleanedDescription);
}

if (property.decorators) {
Expand Down Expand Up @@ -1196,9 +1203,10 @@ export class ClassHelper {
}

if (method.jsDoc) {
const rawDescription = this.jsdocParserUtil.getMainCommentOfNode(method);
const rawDescription = this.jsdocParserUtil.getMainCommentOfNode(method, sourceFile);
result.rawdescription = rawDescription;
result.description = marked(rawDescription);
const cleanedDescription = this.jsdocParserUtil.parseComment(rawDescription);
result.description = marked(cleanedDescription);
}

if (method.decorators) {
Expand Down Expand Up @@ -1246,11 +1254,11 @@ export class ClassHelper {
deprecationMessage: ''
};
if (property.jsDoc) {
const rawDescription = this.jsdocParserUtil.getMainCommentOfNode(property);
const rawDescription = this.jsdocParserUtil.getMainCommentOfNode(property, sourceFile);
const jsdoctags = this.jsdocParserUtil.getJSDocs(property);

_return.rawdescription = rawDescription;
_return.description = marked(rawDescription);
const cleanedDescription = this.jsdocParserUtil.parseComment(rawDescription);
_return.description = marked(cleanedDescription);

if (jsdoctags && jsdoctags.length >= 1 && jsdoctags[0].tags) {
this.checkForDeprecation(jsdoctags[0].tags, _return);
Expand Down Expand Up @@ -1395,10 +1403,12 @@ export class ClassHelper {
_return.deprecationMessage = '';
if (property.jsDoc) {
const jsdoctags = this.jsdocParserUtil.getJSDocs(property);
const rawDescription = this.jsdocParserUtil.getMainCommentOfNode(property);
const rawDescription = this.jsdocParserUtil.getMainCommentOfNode(property, sourceFile);

_return.rawdescription = rawDescription;
_return.description = marked(rawDescription);

const cleanedDescription = this.jsdocParserUtil.parseComment(rawDescription);
_return.description = marked(cleanedDescription);

if (jsdoctags && jsdoctags.length >= 1 && jsdoctags[0].tags) {
this.checkForDeprecation(jsdoctags[0].tags, _return);
Expand Down
94 changes: 89 additions & 5 deletions src/utils/jsdoc-parser.util.ts
@@ -1,6 +1,10 @@
import * as _ from 'lodash';
import { ts, SyntaxKind } from 'ts-simple-ast';

import * as _ts from './ts-internal';

import * as Handlebars from 'handlebars';

import { JSDocParameterTagExt } from '../app/nodes/jsdoc-parameter-tag.node';

export class JsdocParserUtil {
Expand All @@ -21,18 +25,98 @@ export class JsdocParserUtil {
return false;
}

public getMainCommentOfNode(node: ts.Node): string {
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;
}

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;
}

public getMainCommentOfNode(node: ts.Node, sourceFile?: ts.SourceFile): string {
let description: string = '';
if (node.jsDoc) {
if (node.jsDoc.length > 0) {
if (typeof node.jsDoc[0].comment !== 'undefined') {
description = node.jsDoc[0].comment;

if (node.parent && node.parent.kind === ts.SyntaxKind.VariableDeclarationList) {
node = node.parent.parent;
} else if (node.kind === ts.SyntaxKind.ModuleDeclaration) {
if (!this.isTopmostModuleDeclaration(<ts.ModuleDeclaration>node)) {
return null;
} else {
node = this.getRootModuleDeclaration(<ts.ModuleDeclaration>node);
}
}

const comments = _ts.getJSDocCommentRanges(node, sourceFile.text);
if (comments && comments.length) {
let comment: ts.CommentRange;
if (node.kind === ts.SyntaxKind.SourceFile) {
if (comments.length === 1) {
return null;
}
comment = comments[0];
} else {
comment = comments[comments.length - 1];
}

description = sourceFile.text.substring(comment.pos, comment.end);
}
return description;
}

public parseComment(text: string): string {
let comment = '';
let shortText = 0;

function readBareLine(line: string) {
comment += '\n' + Handlebars.escapeExpression(line);
if (line === '' && shortText === 0) {
// Ignore
} else if (line === '' && shortText === 1) {
shortText = 2;
} else {
if (shortText === 2) {
comment += (comment === '' ? '' : '\n') + line;
}
}
}

const CODE_FENCE = /^\s*```(?!.*```)/;
let inCode = false;
function readLine(line: string) {
line = line.replace(/^\s*\*? ?/, '');
line = line.replace(/\s*$/, '');

if (CODE_FENCE.test(line)) {
inCode = !inCode;
}

readBareLine(line);
}

text = text.replace(/^\s*\/\*+/, '');
text = text.replace(/\*+\/\s*$/, '');

text.split(/\r\n?|\n/).forEach(readLine);

return comment;
}

private getJSDocTags(node: ts.Node, kind: SyntaxKind): ts.JSDocTag[] {
const docs = this.getJSDocs(node);
if (docs) {
Expand Down
12 changes: 12 additions & 0 deletions src/utils/ts-internal.ts
@@ -0,0 +1,12 @@
import * as ts from 'typescript';
const tsany = ts as any;

// https://github.com/Microsoft/TypeScript/blob/v2.1.4/src/compiler/utilities.ts#L152
export function getSourceFileOfNode(node: ts.Node): ts.SourceFile {
return tsany.getSourceFileOfNode.apply(this, arguments);
}

// https://github.com/Microsoft/TypeScript/blob/v2.1.4/src/compiler/utilities.ts#L1423
export function getJSDocCommentRanges(node: ts.Node, text: string) {
return tsany.getJSDocCommentRanges.apply(this, arguments);
}

0 comments on commit 3226d01

Please sign in to comment.