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 | import CommentsDocBuilder from './CommentsDocBuilder.js'; |
27 | import { MethodOrPropertyDoc, ClassDoc } from './Docs.js'; |
28 | |
29 | |
30 | |
31 | |
32 | |
33 | |
34 | |
35 | class ClassDocBuilder { |
36 | |
37 | |
38 | |
39 | |
40 | |
41 | |
42 | #rootPath; |
43 | |
44 | |
45 | |
46 | |
47 | |
48 | |
49 | #fileName; |
50 | |
51 | |
52 | |
53 | |
54 | |
55 | |
56 | #commentsDocBuilder; |
57 | |
58 | |
59 | |
60 | |
61 | |
62 | constructor ( ) { |
63 | Object.freeze ( this ); |
64 | this.#commentsDocBuilder = new CommentsDocBuilder ( ); |
65 | } |
66 | |
67 | |
68 | |
69 | |
70 | |
71 | |
72 | |
73 | |
74 | |
75 | #buildMethodOrPropertyDoc ( methodOrPropertyNode ) { |
76 | |
77 | const methodOrPropertyDoc = new MethodOrPropertyDoc ( ); |
78 | |
79 | methodOrPropertyDoc.name = methodOrPropertyNode?.key?.name || methodOrPropertyNode?.key?.id?.name; |
80 | methodOrPropertyDoc.static = methodOrPropertyNode?.static; |
81 | methodOrPropertyDoc.async = methodOrPropertyNode?.async; |
82 | methodOrPropertyDoc.kind = methodOrPropertyNode?.kind; |
83 | methodOrPropertyDoc.file = this.#fileName; |
84 | methodOrPropertyDoc.rootPath = this.#rootPath; |
85 | methodOrPropertyDoc.line = methodOrPropertyNode?.loc?.start?.line; |
86 | methodOrPropertyDoc.commentsDoc = this.#commentsDocBuilder.build ( methodOrPropertyNode?.leadingComments ); |
87 | |
88 | if ( methodOrPropertyNode?.params?.length ) { |
89 | methodOrPropertyDoc.params = []; |
90 | methodOrPropertyNode.params.forEach ( |
91 | param => { methodOrPropertyDoc.params.push ( param?.name ); } |
92 | ); |
93 | } |
94 | |
95 | switch ( methodOrPropertyNode.type ) { |
96 | case 'ClassPrivateProperty' : |
97 | methodOrPropertyDoc.private = true; |
98 | methodOrPropertyDoc.isA = 'property'; |
99 | break; |
100 | case 'ClassProperty' : |
101 | methodOrPropertyDoc.private = false; |
102 | methodOrPropertyDoc.isA = 'property'; |
103 | break; |
104 | case 'ClassPrivateMethod' : |
105 | methodOrPropertyDoc.private = true; |
106 | methodOrPropertyDoc.isA = 'method'; |
107 | break; |
108 | case 'ClassMethod' : |
109 | methodOrPropertyDoc.private = false; |
110 | methodOrPropertyDoc.isA = 'method'; |
111 | break; |
112 | default : |
113 | break; |
114 | } |
115 | |
116 | return Object.freeze ( methodOrPropertyDoc ); |
117 | } |
118 | |
119 | |
120 | |
121 | |
122 | |
123 | |
124 | |
125 | |
126 | build ( classDeclarationNode, fileName ) { |
127 | |
128 | |
129 | this.#fileName = fileName; |
130 | |
131 | |
132 | this.#rootPath = ''; |
133 | let rootPathCounter = this.#fileName.split ( '/' ).length - 1; |
134 | while ( 0 < rootPathCounter ) { |
135 | this.#rootPath += '../'; |
136 | rootPathCounter --; |
137 | } |
138 | |
139 | |
140 | const classDoc = new ClassDoc; |
141 | classDoc.name = classDeclarationNode.id.name; |
142 | classDoc.file = this.#fileName; |
143 | classDoc.rootPath = this.#rootPath; |
144 | classDoc.line = classDeclarationNode.loc.start.line; |
145 | |
146 | if ( classDeclarationNode?.superClass?.name ) { |
147 | classDoc.superClass = classDeclarationNode.superClass.name; |
148 | } |
149 | |
150 | classDoc.commentsDoc = this.#commentsDocBuilder.build ( classDeclarationNode.leadingComments ); |
151 | |
152 | |
153 | classDeclarationNode.body.body.forEach ( |
154 | methodOrPropertyNode => { |
155 | const methodOrPropertyDoc = this.#buildMethodOrPropertyDoc ( methodOrPropertyNode, this.#fileName ); |
156 | if ( methodOrPropertyDoc.isA && ! methodOrPropertyDoc?.commentsDoc?.ignore ) { |
157 | classDoc.methodsAndProperties = ( classDoc.methodsAndProperties ?? [] ); |
158 | classDoc.methodsAndProperties.push ( methodOrPropertyDoc ); |
159 | } |
160 | } |
161 | ); |
162 | |
163 | Object.freeze ( classDoc.methodsAndProperties ); |
164 | Object.freeze ( classDoc ); |
165 | |
166 | return classDoc; |
167 | } |
168 | } |
169 | |
170 | export default ClassDocBuilder; |
171 | |
172 | |
173 | |