Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
29 changes: 26 additions & 3 deletions src/__tests__/data/transformAST.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -8,7 +8,11 @@ export const exportedVar = 10;
/** unexportedVarFunction comment */
const unexportedVarFunction = (param1: string): number => 0
;
/** exportedVarFunction comment */
/** exportedVarFunction comment
*
* @tag1
* @tag2 partA partB partC
*/
export const exportedVarFunction = (param1: number, param2: string): string => "";

function unexportedFunction(param1: number): string {
Expand All @@ -22,8 +26,21 @@ function exportedFunction(param1: string, param2: number): number {
interface UnexportedInterface {
/** prop1 comment */
prop1: string;

/**
* prop2 comment
* @tag1
* @tag2 partA partB partC
*/
prop2?: string;
}

/**
* Interface comment
*
* @tag1
* @tag2 partA partB partC
*/
export interface ExportedInterface {
/** prop1 comment */
prop1: string;
Expand All @@ -46,7 +63,10 @@ class UnexportedClass extends OurBaseClass<ExportedInterface, {}> {
}
}

/** ExportedClass comment */
/** ExportedClass comment
* @tag1 partA partB
* @tag2
*/
export class ExportedClass {
method1(): string {
return "";
Expand All @@ -73,7 +93,10 @@ export const exportedExternalHoc1 = externalHoc(ExportedClass);
/** exportedExternalHoc2 comment */
export const exportedExternalHoc2 = externalHoc(exportedFunction);

/** exported intersection type */
/** exported intersection type
* @tag1 partA partB
* @tag2
*/
export type ExportedType1 = React.HTMLAttributes<HTMLImageElement> & {
/** the first property */
prop1: "value1" | "value2";
Expand Down
4 changes: 3 additions & 1 deletion src/__tests__/data/transformAST_external.ts
Original file line number Diff line number Diff line change
Expand Up @@ -2,7 +2,9 @@ export interface ExternalInterfaceBase {
prop1ExternalInterfaceBase: string;
}

/** ExternalInterface comment */
/** ExternalInterface comment
* @tag
*/
export interface ExternalInterface extends ExternalInterfaceBase {
/** prop1 comment */
prop1OnExternalInterface: string;
Expand Down
2 changes: 1 addition & 1 deletion src/__tests__/getFileDocumentation.spec.ts
Original file line number Diff line number Diff line change
Expand Up @@ -272,7 +272,7 @@ describe('getFileDocumentation', () => {
assert.isNotNull(r1.propInterface);
const p1 = r1.propInterface;
assert.equal(p1.name, 'Props');
assert.equal(p1.comment, 'Props comment ');
assert.equal(p1.comment, 'Props comment');
assert.equal(p1.members.length, 2);
assert.equal(p1.members[0].name, 'isFlippedX');
assert.equal(p1.members[0].comment, 'whether the image is flipped horizontally');
Expand Down
15 changes: 13 additions & 2 deletions src/__tests__/transformAST.spec.ts
Original file line number Diff line number Diff line change
Expand Up @@ -44,7 +44,7 @@ describe('transformAST', () => {
assert.equal(r4.name, 'exportedVarFunction');
assert.equal(r4.exported, true);
assert.equal(r4.kind, 'arrowFunction');
assert.equal(r4.comment, 'exportedVarFunction comment');
assert.equal(r4.comment, 'exportedVarFunction comment\n@tag1\n@tag2 partA partB partC');
assert.equal(r4.arrowFunctionType, 'string');
assert.deepEqual(r4.arrowFunctionParams, ['number', 'string']);

Expand Down Expand Up @@ -98,10 +98,18 @@ describe('transformAST', () => {
'isOwn': true,
'comment': 'prop1 comment',
'values': [],
}, {
'name': 'prop2',
'type': 'string',
'isRequired': false,
'isOwn': true,
'comment': 'prop2 comment\n@tag1\n@tag2 partA partB partC',
'values': [],
}]);

const r2 = result[1];
assert.equal(r2.name, 'ExportedInterface');
assert.equal(r2.comment, 'Interface comment\n@tag1\n@tag2 partA partB partC');
assert.equal(r2.exported, true);
assert.deepEqual(r2.properties, [{
'name': 'prop1',
Expand Down Expand Up @@ -147,6 +155,7 @@ describe('transformAST', () => {
const r4 = result[3];
assert.equal(r4.name, 'ExternalInterface');
assert.equal(r4.exported, true);
assert.equal(r4.comment, 'ExternalInterface comment\n@tag');
});

it('should provide data about classes', () => {
Expand All @@ -161,7 +170,7 @@ describe('transformAST', () => {
const r2 = result[2];
assert.equal(r2.name, 'ExportedClass');
assert.equal(r2.exported, true);
assert.equal(r2.comment, 'ExportedClass comment');
assert.equal(r2.comment, 'ExportedClass comment\n@tag1 partA partB\n@tag2');
assert.deepEqual(r2.methods, [{name: 'method1'}, {name: 'method2'}]);

const r4 = result[3];
Expand All @@ -175,6 +184,8 @@ describe('transformAST', () => {
assert.equal(target.types.length, 1);
const t1 = target.types[0];
assert.equal(t1.name, 'ExportedType1');
assert.equal(t1.comment, 'exported intersection type\n@tag1 partA partB\n@tag2');

// because ExportedType1 inherites from built in type and can
// change over time we don't use exact number here
assert.isTrue(t1.properties.length > 200);
Expand Down
5 changes: 5 additions & 0 deletions src/printUtils.ts
Original file line number Diff line number Diff line change
Expand Up @@ -77,6 +77,11 @@ export function simplePrint(checker: ts.TypeChecker, node: ts.Node, indent = 0)
if (comments.length > 0) {
info.push(prefix + 'comment: \'' + comments.map(i => i.text).join('; ') + '\'');
}
const jsdoctags = s.getJsDocTags();
if (jsdoctags.length > 0) {
info.push(prefix + 'jsdoctags: \'' +
jsdoctags.map(i => `@${i.name} ${i.text}`).join('; ') + '\'');
}
}

if (node.kind === ts.SyntaxKind.FunctionDeclaration) {
Expand Down
38 changes: 32 additions & 6 deletions src/transformAST.ts
Original file line number Diff line number Diff line change
Expand Up @@ -29,6 +29,32 @@ function isNodeExported(node: ts.Node): boolean {
return false;
}

/**
* Rebuilds a full JsDoc comment symbol, reconsitituting
* from the parts that TypeScript has broken it into.
*/
function getFullJsDocComment(symbol: ts.Symbol) {
if (!symbol) {
return '';
}

const mainComment = ts.displayPartsToString(symbol.getDocumentationComment());
const tags = symbol.getJsDocTags() || [];

// Transform { name: 'tag', text: 'text1 text2' } into
// '@tag text1 text2'
const tagComments = tags.map(t => {
let result = '@' + t.name;
if (t.text) {
result += ' ' + t.text;
}
return result;
});

const fullComment = mainComment + '\n' + tagComments.join('\n');
return fullComment.trim();
}

function getType(prop: ts.PropertySignature): MemberType {
const unionType = prop.type as ts.UnionTypeNode;
if (unionType && unionType.types) {
Expand Down Expand Up @@ -75,7 +101,7 @@ function getProperties(checker: ts.TypeChecker, type: ts.Type, parent: ts.Node):
type: typeInfo.type,
values: typeInfo.values || [],
isRequired: !prop.questionToken,
comment: ts.displayPartsToString(symbol.getDocumentationComment()).trim(),
comment: getFullJsDocComment(symbol),
};
});
}
Expand Down Expand Up @@ -145,7 +171,7 @@ export function transformAST(sourceFile: ts.SourceFile, checker: ts.TypeChecker)
return {
name: identifier.text,
exported: isNodeExported(i),
comment: symbol ? ts.displayPartsToString(symbol.getDocumentationComment()).trim() : '',
comment: getFullJsDocComment(symbol),
type: varType.symbol ? varType.symbol.getName() : 'unknown',
kind,
arrowFunctionType,
Expand All @@ -163,7 +189,7 @@ export function transformAST(sourceFile: ts.SourceFile, checker: ts.TypeChecker)
const type = checker.getTypeAtLocation(i.name);
return {
name: symbol.name,
comment: ts.displayPartsToString(symbol.getDocumentationComment()).trim(),
comment: getFullJsDocComment(symbol),
exported: isNodeExported(i),
properties: getProperties(checker, type, i),
};
Expand Down Expand Up @@ -196,7 +222,7 @@ export function transformAST(sourceFile: ts.SourceFile, checker: ts.TypeChecker)
name: i.name.getText(),
properties,
exported: isNodeExported(i),
comment: !symbol ? "" : ts.displayPartsToString(symbol.getDocumentationComment())
comment: getFullJsDocComment(symbol)
};
});

Expand Down Expand Up @@ -231,7 +257,7 @@ export function transformAST(sourceFile: ts.SourceFile, checker: ts.TypeChecker)
// in that case we need to include the interface explicitly
interfaces.push({
name: taType.symbol.name,
comment: ts.displayPartsToString(taType.symbol.getDocumentationComment()).trim(),
comment: getFullJsDocComment(taType.symbol),
exported: true, // it has to be exported in order to be used,
properties: getProperties(checker, taType, null),
});
Expand All @@ -251,7 +277,7 @@ export function transformAST(sourceFile: ts.SourceFile, checker: ts.TypeChecker)
name: symbol.name,
exported: isNodeExported(i),
baseType: baseType,
comment: ts.displayPartsToString(symbol.getDocumentationComment()).trim(),
comment: getFullJsDocComment(symbol),
methods: getMethods(checker, type, i),
};
});
Expand Down