aboutsummaryrefslogtreecommitdiff
path: root/scripts/apidocs/processing/jsdocs.ts
blob: 0999abca845b79a0aee8f6d55975aeefd348a8d8 (plain)
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
import type { JSDoc, JSDocTag, JSDocableNode } from 'ts-morph';
import { JSDocParameterTag, JSDocTemplateTag } from 'ts-morph';
import {
  allRequired,
  exactlyOne,
  optionalOne,
  required,
} from '../utils/value-checks';

export type JSDocableLikeNode = Pick<JSDocableNode, 'getJsDocs'>;

export function getJsDocs(node: JSDocableLikeNode): JSDoc {
  return exactlyOne(
    node.getJsDocs(),
    'jsdocs',
    'Please ensure that each method signature has JSDocs, and that all properties of option/object parameters are documented with both @param tags and inline JSDocs.'
  );
}

export function getDeprecated(jsdocs: JSDoc): string | undefined {
  return getOptionalTagFromJSDoc(jsdocs, 'deprecated');
}

export function getDescription(jsdocs: JSDoc | JSDocTag): string {
  return required(jsdocs.getCommentText(), 'jsdocs description');
}

export function getSince(jsdocs: JSDoc): string {
  return getExactlyOneTagFromJSDoc(jsdocs, 'since');
}

export function getTypeParameterTags(jsdocs: JSDoc): Record<string, JSDocTag> {
  return Object.fromEntries(
    jsdocs
      .getTags()
      .filter((tag) => tag.getTagName() === 'template')
      .filter((tag) => tag instanceof JSDocTemplateTag)
      .map((tag) => [tag.getTypeParameters()[0].getName(), tag] as const)
  );
}

export function getParameterTags(jsdocs: JSDoc): Record<string, JSDocTag> {
  return Object.fromEntries(
    jsdocs
      .getTags()
      .filter((tag) => tag.getTagName() === 'param')
      .filter((tag) => tag instanceof JSDocParameterTag)
      .map((tag) => [tag.getName(), tag] as const)
  );
}

export function getDefault(jsdocs: JSDoc): string | undefined {
  return getOptionalTagFromJSDoc(jsdocs, `default`);
}

export function getThrows(jsdocs: JSDoc): string[] {
  return getTagsFromJSDoc(jsdocs, 'throws');
}

export function getExamples(jsdocs: JSDoc): string[] {
  return getTagsFromJSDoc(jsdocs, 'example');
}

export function getSeeAlsos(jsdocs: JSDoc): string[] {
  return getTagsFromJSDoc(jsdocs, 'see', true);
}

function getOptionalTagFromJSDoc(
  jsdocs: JSDoc,
  type: string
): string | undefined {
  return optionalOne(getTagsFromJSDoc(jsdocs, type), `@${type}`);
}

function getExactlyOneTagFromJSDoc(jsdocs: JSDoc, type: string): string {
  return exactlyOne(getTagsFromJSDoc(jsdocs, type), `@${type}`);
}

function getTagsFromJSDoc(
  jsdocs: JSDoc,
  type: string,
  full: boolean = false
): string[] {
  return allRequired(
    jsdocs
      .getTags()
      .filter((tag) => tag.getTagName() === type)
      .map((tag) =>
        full ? tag.getStructure().text?.toString() : tag.getCommentText()
      ),
    `@${type}`
  );
}