• Home
  • Features
  • Pricing
  • Docs
  • Announcements
  • Sign In

reactjs / react-docgen / 15503494088

07 Jun 2025 02:52AM CUT coverage: 95.479% (-0.01%) from 95.49%
15503494088

Pull #999

github

web-flow
Merge c42d1b242 into ec11d1f1e
Pull Request #999: Packages ready to publish

1393 of 1494 branches covered (93.24%)

Branch coverage included in aggregate %.

4605 of 4788 relevant lines covered (96.18%)

522.91 hits per line

Source File
Press 'n' to go to next uncovered line, 'b' for previous

89.17
/packages/react-docgen/src/utils/parseJsDoc.ts
1
import doctrine from 'doctrine';
3✔
2
import type { Type, Annotation, Tag } from 'doctrine';
3

4
type ExcludesNullish = <T>(x: T | 0 | false | null | undefined) => x is T;
5
type JsDocType = JsDocBaseType | JsDocElementsType;
6

7
interface JsDocBaseType {
8
  name: string;
9
}
10

11
interface JsDocElementsType extends JsDocBaseType {
12
  elements: JsDocType[];
13
}
14

15
interface JsDocProperty {
16
  description: string | null;
17
  type: JsDocType | null;
18
}
19
interface JsDocParam extends JsDocProperty {
20
  name: string;
21
  optional?: boolean;
22
}
23

24
interface JsDoc {
25
  description: string | null;
26
  params: JsDocParam[];
27
  returns: JsDocProperty | null;
28
}
29

30
function getType(tagType: Type | null | undefined): JsDocType | null {
75✔
31
  if (!tagType) {
75✔
32
    return null;
15✔
33
  }
15✔
34

35
  switch (tagType.type) {
60✔
36
    case 'NameExpression':
69✔
37
      // {a}
38
      return { name: tagType.name };
42✔
39
    case 'UnionType':
75✔
40
      // {a|b}
41
      return {
3✔
42
        name: 'union',
3✔
43
        elements: tagType.elements
3✔
44
          .map((element) => getType(element))
3✔
45
          .filter(Boolean as unknown as ExcludesNullish),
3✔
46
      };
3✔
47
    case 'AllLiteral':
75✔
48
      // {*}
49
      return { name: 'mixed' };
3✔
50
    case 'TypeApplication':
75✔
51
      // {Array<string>} or {string[]}
52
      return {
3✔
53
        name: 'name' in tagType.expression ? tagType.expression.name : '',
3!
54
        elements: tagType.applications
3✔
55
          .map((element) => getType(element))
3✔
56
          .filter(Boolean as unknown as ExcludesNullish),
3✔
57
      };
3✔
58
    case 'ArrayType':
75✔
59
      // {[number, string]}
60
      return {
6✔
61
        name: 'tuple',
6✔
62
        elements: tagType.elements
6✔
63
          .map((element) => getType(element))
6✔
64
          .filter(Boolean as unknown as ExcludesNullish),
6✔
65
      };
6✔
66
    default: {
75✔
67
      const typeName =
3✔
68
        'name' in tagType && tagType.name
3!
69
          ? tagType.name
×
70
          : 'expression' in tagType &&
3✔
71
              tagType.expression &&
3✔
72
              'name' in tagType.expression
3✔
73
            ? tagType.expression.name
3!
74
            : null;
×
75

76
      if (typeName) {
3✔
77
        return { name: typeName };
3✔
78
      } else {
3!
79
        return null;
×
80
      }
×
81
    }
3✔
82
  }
75✔
83
}
75✔
84

85
function getOptional(tag: Tag): boolean {
27✔
86
  return !!(tag.type && tag.type.type && tag.type.type === 'OptionalType');
27✔
87
}
27✔
88

89
// Add jsdoc @return description.
90
function getReturnsJsDoc(jsDoc: Annotation): JsDocProperty | null {
57✔
91
  const returnTag = jsDoc.tags.find(
57✔
92
    (tag) => tag.title === 'return' || tag.title === 'returns',
57✔
93
  );
57✔
94

95
  if (returnTag) {
57✔
96
    return {
24✔
97
      description: returnTag.description,
24✔
98
      type: getType(returnTag.type),
24✔
99
    };
24✔
100
  }
24✔
101

102
  return null;
33✔
103
}
33✔
104

105
// Add jsdoc @param descriptions.
106
function getParamsJsDoc(jsDoc: Annotation): JsDocParam[] {
57✔
107
  if (!jsDoc.tags) {
57!
108
    return [];
×
109
  }
×
110

111
  return jsDoc.tags
57✔
112
    .filter((tag) => tag.title === 'param')
57✔
113
    .map((tag) => {
57✔
114
      return {
27✔
115
        name: tag.name || '',
27!
116
        description: tag.description,
27✔
117
        type: getType(tag.type),
27✔
118
        optional: getOptional(tag),
27✔
119
      };
27✔
120
    });
57✔
121
}
57✔
122

123
export default function parseJsDoc(docblock: string): JsDoc {
57✔
124
  const jsDoc = doctrine.parse(docblock);
57✔
125

126
  return {
57✔
127
    description: jsDoc.description || null,
57✔
128
    params: getParamsJsDoc(jsDoc),
57✔
129
    returns: getReturnsJsDoc(jsDoc),
57✔
130
  };
57✔
131
}
57✔
STATUS · Troubleshooting · Open an Issue · Sales · Support · CAREERS · ENTERPRISE · START FREE · SCHEDULE DEMO
ANNOUNCEMENTS · TWITTER · TOS & SLA · Supported CI Services · What's a CI service? · Automated Testing

© 2025 Coveralls, Inc