Skip to content
File

Blob: types/src/transforms/comments.ts

typescript83 lines
1// Copyright (c) 2022-2023 Cloudflare, Inc.
2// Licensed under the Apache 2.0 license found in the LICENSE file or at:
3// https://opensource.org/licenses/Apache-2.0
4import ts from "typescript";
5import { hasModifier } from "./helpers";
6 
7// Refer to `collateStandardComments()` in `standards.ts` for construction
8export type CommentsData = Record<
9 /* globalName */ string,
10 // eslint-disable-next-line @typescript-eslint/no-redundant-type-constituents
11 | Record</* root */ "$" | /* memberName */ string, string | undefined>
12 | undefined
13>;
14 
15export function createCommentsTransformer(
16 comments: CommentsData
17): ts.TransformerFactory<ts.SourceFile> {
18 return (ctx) => {
19 return (node) => {
20 const visitor = createVisitor(comments);
21 return ts.visitEachChild(node, visitor, ctx);
22 };
23 };
24}
25 
26function maybeAddComment(node: ts.Node, comment?: string): void {
27 if (comment === undefined) return;
28 ts.addSyntheticLeadingComment(
29 node,
30 ts.SyntaxKind.MultiLineCommentTrivia,
31 comment,
32 /* hasTrailingNewLine */ true
33 );
34}
35 
36function createVisitor(data: CommentsData): ts.Visitor {
37 return (node) => {
38 if (
39 (ts.isClassDeclaration(node) || ts.isInterfaceDeclaration(node)) &&
40 node.name !== undefined &&
41 ts.isIdentifier(node.name)
42 ) {
43 const comments = data[node.name.text];
44 maybeAddComment(node, comments?.["$"]);
45 for (const member of node.members) {
46 if (member.name !== undefined && ts.isIdentifier(member.name)) {
47 let key = member.name.text;
48 
49 const isStatic =
50 ts.canHaveModifiers(member) &&
51 hasModifier(ts.getModifiers(member), ts.SyntaxKind.StaticKeyword);
52 if (isStatic) key = `static:${key}`;
53 
54 maybeAddComment(member, comments?.[key]);
55 }
56 }
57 }
58 
59 if (
60 ts.isFunctionDeclaration(node) &&
61 node.name !== undefined &&
62 ts.isIdentifier(node.name)
63 ) {
64 const comments = data[node.name.text];
65 maybeAddComment(node, comments?.["$"]);
66 }
67 
68 if (
69 ts.isVariableStatement(node) &&
70 node.declarationList.declarations.length === 1
71 ) {
72 const declaration = node.declarationList.declarations[0];
73 const name = declaration.name;
74 if (ts.isIdentifier(name)) {
75 const comments = data[name.text];
76 maybeAddComment(node, comments?.["$"]);
77 }
78 }
79 
80 return node;
81 };
82}