@typespec/tspd 0.70.0-dev.2 → 0.70.0
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/dist/src/cli.js +85 -103
- package/dist/src/gen-extern-signatures/components/decorator-signature-tests.d.ts +8 -0
- package/dist/src/gen-extern-signatures/components/decorator-signature-tests.d.ts.map +1 -0
- package/dist/src/gen-extern-signatures/components/decorator-signature-tests.js +16 -0
- package/dist/src/gen-extern-signatures/components/decorator-signature-tests.jsx +12 -0
- package/dist/src/gen-extern-signatures/components/decorator-signature-tests.jsx.map +1 -0
- package/dist/src/gen-extern-signatures/components/decorator-signature-type.d.ts +16 -0
- package/dist/src/gen-extern-signatures/components/decorator-signature-type.d.ts.map +1 -0
- package/dist/src/gen-extern-signatures/components/decorator-signature-type.js +404 -0
- package/dist/src/gen-extern-signatures/components/decorator-signature-type.jsx +316 -0
- package/dist/src/gen-extern-signatures/components/decorator-signature-type.jsx.map +1 -0
- package/dist/src/gen-extern-signatures/components/decorators-signatures.d.ts +12 -0
- package/dist/src/gen-extern-signatures/components/decorators-signatures.d.ts.map +1 -0
- package/dist/src/gen-extern-signatures/components/decorators-signatures.js +107 -0
- package/dist/src/gen-extern-signatures/components/decorators-signatures.jsx +60 -0
- package/dist/src/gen-extern-signatures/components/decorators-signatures.jsx.map +1 -0
- package/dist/src/gen-extern-signatures/components/dollar-decorators-type.d.ts +10 -0
- package/dist/src/gen-extern-signatures/components/dollar-decorators-type.d.ts.map +1 -0
- package/dist/src/gen-extern-signatures/components/dollar-decorators-type.js +39 -0
- package/dist/src/gen-extern-signatures/components/dollar-decorators-type.jsx +18 -0
- package/dist/src/gen-extern-signatures/components/dollar-decorators-type.jsx.map +1 -0
- package/dist/src/gen-extern-signatures/components/tspd-context.d.ts +10 -0
- package/dist/src/gen-extern-signatures/components/tspd-context.d.ts.map +1 -0
- package/dist/src/gen-extern-signatures/components/tspd-context.js +22 -0
- package/dist/src/gen-extern-signatures/components/tspd-context.js.map +1 -0
- package/dist/src/gen-extern-signatures/doc-builder.js +10 -12
- package/dist/src/gen-extern-signatures/external-packages/compiler.d.ts +17 -0
- package/dist/src/gen-extern-signatures/external-packages/compiler.d.ts.map +1 -0
- package/dist/src/gen-extern-signatures/external-packages/compiler.js +10 -0
- package/dist/src/gen-extern-signatures/external-packages/compiler.js.map +1 -0
- package/dist/src/gen-extern-signatures/gen-extern-signatures.d.ts.map +1 -1
- package/dist/src/gen-extern-signatures/gen-extern-signatures.js +109 -102
- package/dist/src/gen-extern-signatures/gen-extern-signatures.js.map +1 -1
- package/dist/src/gen-extern-signatures/types.js +1 -2
- package/dist/src/ref-doc/api-docs.js +56 -56
- package/dist/src/ref-doc/emitters/docusaurus.js +156 -209
- package/dist/src/ref-doc/emitters/markdown.js +278 -327
- package/dist/src/ref-doc/emitters/starlight.js +154 -190
- package/dist/src/ref-doc/experimental.js +48 -45
- package/dist/src/ref-doc/extractor.js +486 -449
- package/dist/src/ref-doc/index.js +1 -2
- package/dist/src/ref-doc/lib.js +29 -26
- package/dist/src/ref-doc/types.js +1 -2
- package/dist/src/ref-doc/utils/markdown.js +37 -44
- package/dist/src/ref-doc/utils/type-signature.js +89 -98
- package/package.json +12 -9
- package/dist/src/gen-extern-signatures/decorators-signatures.d.ts +0 -5
- package/dist/src/gen-extern-signatures/decorators-signatures.d.ts.map +0 -1
- package/dist/src/gen-extern-signatures/decorators-signatures.js +0 -338
- package/dist/src/gen-extern-signatures/decorators-signatures.js.map +0 -1
|
@@ -1,529 +1,566 @@
|
|
|
1
|
-
import { compile, compilerAssert, createDiagnosticCollector, getDeprecated, getDoc, getLocationContext, getSourceLocation, getTypeName, isDeclaredType, isTemplateDeclaration, joinPaths, navigateProgram, navigateTypesInNamespace, NodeHost, NoTarget, resolveLinterDefinition, resolvePath
|
|
1
|
+
import { compile, compilerAssert, createDiagnosticCollector, getDeprecated, getDoc, getLocationContext, getSourceLocation, getTypeName, isDeclaredType, isTemplateDeclaration, joinPaths, navigateProgram, navigateTypesInNamespace, NodeHost, NoTarget, resolveLinterDefinition, resolvePath } from "@typespec/compiler";
|
|
2
2
|
import { SyntaxKind } from "@typespec/compiler/ast";
|
|
3
3
|
import { readFile } from "fs/promises";
|
|
4
4
|
import { pathToFileURL } from "url";
|
|
5
5
|
import { reportDiagnostic } from "./lib.js";
|
|
6
6
|
import { getQualifier, getTypeSignature } from "./utils/type-signature.js";
|
|
7
|
+
|
|
8
|
+
/**
|
|
9
|
+
* The mutable equivalent of a type.
|
|
10
|
+
*/
|
|
11
|
+
|
|
12
|
+
//prettier-ignore
|
|
13
|
+
|
|
7
14
|
function getExport(pkgJson, path, condition) {
|
|
8
|
-
|
|
15
|
+
return pkgJson.exports?.[path]?.[condition];
|
|
9
16
|
}
|
|
10
17
|
export async function extractLibraryRefDocs(libraryPath) {
|
|
11
|
-
|
|
12
|
-
|
|
13
|
-
|
|
14
|
-
|
|
15
|
-
|
|
16
|
-
|
|
17
|
-
|
|
18
|
-
|
|
19
|
-
|
|
20
|
-
|
|
21
|
-
|
|
22
|
-
|
|
23
|
-
|
|
24
|
-
|
|
25
|
-
|
|
26
|
-
|
|
27
|
-
|
|
28
|
-
|
|
29
|
-
|
|
30
|
-
|
|
18
|
+
const diagnostics = createDiagnosticCollector();
|
|
19
|
+
const pkgJson = await readPackageJson(libraryPath);
|
|
20
|
+
const refDoc = {
|
|
21
|
+
name: pkgJson.name,
|
|
22
|
+
description: pkgJson.description,
|
|
23
|
+
packageJson: pkgJson,
|
|
24
|
+
namespaces: [],
|
|
25
|
+
getNamedTypeRefDoc: type => undefined
|
|
26
|
+
};
|
|
27
|
+
const tspMain = getExport(pkgJson, ".", "typespec");
|
|
28
|
+
if (tspMain) {
|
|
29
|
+
const main = resolvePath(libraryPath, tspMain);
|
|
30
|
+
const program = await compile(NodeHost, main, {
|
|
31
|
+
parseOptions: {
|
|
32
|
+
comments: true,
|
|
33
|
+
docs: true
|
|
34
|
+
}
|
|
35
|
+
});
|
|
36
|
+
const tspEmitter = diagnostics.pipe(extractRefDocs(program));
|
|
37
|
+
Object.assign(refDoc, tspEmitter);
|
|
38
|
+
for (const diag of program.diagnostics ?? []) {
|
|
39
|
+
diagnostics.add(diag);
|
|
31
40
|
}
|
|
32
|
-
|
|
33
|
-
|
|
34
|
-
|
|
35
|
-
|
|
36
|
-
|
|
37
|
-
|
|
38
|
-
|
|
39
|
-
|
|
40
|
-
|
|
41
|
-
|
|
42
|
-
|
|
43
|
-
|
|
44
|
-
|
|
41
|
+
}
|
|
42
|
+
const main = getExport(pkgJson, ".", "import") ?? getExport(pkgJson, ".", "default");
|
|
43
|
+
if (main) {
|
|
44
|
+
const entrypoint = await import(pathToFileURL(resolvePath(libraryPath, main)).href);
|
|
45
|
+
const lib = entrypoint.$lib;
|
|
46
|
+
if (lib?.emitter?.options) {
|
|
47
|
+
refDoc.emitter = {
|
|
48
|
+
options: extractEmitterOptionsRefDoc(lib.emitter.options)
|
|
49
|
+
};
|
|
50
|
+
}
|
|
51
|
+
const linter = entrypoint.$linter;
|
|
52
|
+
if (lib && linter) {
|
|
53
|
+
refDoc.linter = extractLinterRefDoc(lib.name, resolveLinterDefinition(lib.name, linter));
|
|
45
54
|
}
|
|
46
|
-
|
|
55
|
+
}
|
|
56
|
+
return diagnostics.wrap(refDoc);
|
|
47
57
|
}
|
|
48
58
|
async function readPackageJson(libraryPath) {
|
|
49
|
-
|
|
50
|
-
|
|
59
|
+
const buffer = await readFile(joinPaths(libraryPath, "package.json"));
|
|
60
|
+
return JSON.parse(buffer.toString());
|
|
51
61
|
}
|
|
52
62
|
function resolveNamespaces(program, options) {
|
|
53
|
-
|
|
54
|
-
|
|
55
|
-
|
|
56
|
-
|
|
57
|
-
|
|
58
|
-
|
|
59
|
-
|
|
63
|
+
const diagnostics = createDiagnosticCollector();
|
|
64
|
+
let namespaceTypes = [];
|
|
65
|
+
const {
|
|
66
|
+
include,
|
|
67
|
+
exclude
|
|
68
|
+
} = options?.namespaces ?? {};
|
|
69
|
+
if (include) {
|
|
70
|
+
namespaceTypes = include.map(x => diagnostics.pipe(program.resolveTypeReference(x))).filter(x => x !== undefined);
|
|
71
|
+
}
|
|
72
|
+
navigateProgram(program, {
|
|
73
|
+
namespace(namespace) {
|
|
74
|
+
if (getLocationContext(program, namespace).type !== "project") {
|
|
75
|
+
return;
|
|
76
|
+
}
|
|
77
|
+
if (namespace.name === "Private") {
|
|
78
|
+
return;
|
|
79
|
+
}
|
|
80
|
+
namespaceTypes.push(namespace);
|
|
60
81
|
}
|
|
61
|
-
|
|
62
|
-
|
|
63
|
-
|
|
64
|
-
|
|
65
|
-
}
|
|
66
|
-
if (namespace.name === "Private") {
|
|
67
|
-
return;
|
|
68
|
-
}
|
|
69
|
-
namespaceTypes.push(namespace);
|
|
70
|
-
},
|
|
82
|
+
});
|
|
83
|
+
if (exclude !== undefined) {
|
|
84
|
+
namespaceTypes = namespaceTypes.filter(x => {
|
|
85
|
+
return exclude.includes(getTypeName(x));
|
|
71
86
|
});
|
|
72
|
-
|
|
73
|
-
|
|
74
|
-
return exclude.includes(getTypeName(x));
|
|
75
|
-
});
|
|
76
|
-
}
|
|
77
|
-
return diagnostics.wrap(namespaceTypes);
|
|
87
|
+
}
|
|
88
|
+
return diagnostics.wrap(namespaceTypes);
|
|
78
89
|
}
|
|
79
90
|
export function extractRefDocs(program, options = {}) {
|
|
80
|
-
|
|
81
|
-
|
|
82
|
-
|
|
83
|
-
|
|
84
|
-
|
|
85
|
-
|
|
86
|
-
|
|
87
|
-
|
|
88
|
-
|
|
89
|
-
|
|
90
|
-
|
|
91
|
-
|
|
92
|
-
|
|
93
|
-
|
|
94
|
-
|
|
95
|
-
|
|
96
|
-
|
|
97
|
-
|
|
98
|
-
|
|
99
|
-
|
|
100
|
-
|
|
101
|
-
|
|
102
|
-
}
|
|
103
|
-
navigateTypesInNamespace(namespace, {
|
|
104
|
-
decorator(dec) {
|
|
105
|
-
collectType(dec, extractDecoratorRefDoc(program, dec), namespaceDoc.decorators);
|
|
106
|
-
},
|
|
107
|
-
operation(operation) {
|
|
108
|
-
if (!isDeclaredType(operation)) {
|
|
109
|
-
return;
|
|
110
|
-
}
|
|
111
|
-
if (operation.interface === undefined) {
|
|
112
|
-
collectType(operation, extractOperationRefDoc(program, operation, undefined), namespaceDoc.operations);
|
|
113
|
-
}
|
|
114
|
-
},
|
|
115
|
-
interface(iface) {
|
|
116
|
-
if (!isDeclaredType(iface)) {
|
|
117
|
-
return;
|
|
118
|
-
}
|
|
119
|
-
collectType(iface, extractInterfaceRefDocs(program, iface), namespaceDoc.interfaces);
|
|
120
|
-
},
|
|
121
|
-
model(model) {
|
|
122
|
-
if (!isDeclaredType(model)) {
|
|
123
|
-
return;
|
|
124
|
-
}
|
|
125
|
-
if (model.name === "") {
|
|
126
|
-
return;
|
|
127
|
-
}
|
|
128
|
-
collectType(model, extractModelRefDocs(program, model), namespaceDoc.models);
|
|
129
|
-
},
|
|
130
|
-
enum(e) {
|
|
131
|
-
if (!isDeclaredType(e)) {
|
|
132
|
-
return;
|
|
133
|
-
}
|
|
134
|
-
collectType(e, extractEnumRefDoc(program, e), namespaceDoc.enums);
|
|
135
|
-
},
|
|
136
|
-
union(union) {
|
|
137
|
-
if (!isDeclaredType(union)) {
|
|
138
|
-
return;
|
|
139
|
-
}
|
|
140
|
-
if (union.name !== undefined) {
|
|
141
|
-
collectType(union, extractUnionRefDocs(program, union), namespaceDoc.unions);
|
|
142
|
-
}
|
|
143
|
-
},
|
|
144
|
-
scalar(scalar) {
|
|
145
|
-
collectType(scalar, extractScalarRefDocs(program, scalar), namespaceDoc.scalars);
|
|
146
|
-
},
|
|
147
|
-
}, { includeTemplateDeclaration: true, skipSubNamespaces: true });
|
|
148
|
-
}
|
|
149
|
-
sort(namespaces);
|
|
150
|
-
for (const namespace of namespaces) {
|
|
151
|
-
sort(namespace.decorators);
|
|
152
|
-
sort(namespace.enums);
|
|
153
|
-
sort(namespace.interfaces);
|
|
154
|
-
sort(namespace.models);
|
|
155
|
-
sort(namespace.operations);
|
|
156
|
-
sort(namespace.unions);
|
|
157
|
-
sort(namespace.scalars);
|
|
158
|
-
}
|
|
159
|
-
function sort(arr) {
|
|
160
|
-
arr.sort((a, b) => a.id.localeCompare(b.id, "en"));
|
|
91
|
+
const diagnostics = createDiagnosticCollector();
|
|
92
|
+
const namespaceTypes = diagnostics.pipe(resolveNamespaces(program, options));
|
|
93
|
+
const typeMapping = new Map();
|
|
94
|
+
const namespaces = [];
|
|
95
|
+
for (const namespace of namespaceTypes) {
|
|
96
|
+
const name = getTypeName(namespace);
|
|
97
|
+
const namespaceDoc = {
|
|
98
|
+
kind: "namespace",
|
|
99
|
+
id: name,
|
|
100
|
+
name,
|
|
101
|
+
decorators: [],
|
|
102
|
+
operations: [],
|
|
103
|
+
interfaces: [],
|
|
104
|
+
models: [],
|
|
105
|
+
enums: [],
|
|
106
|
+
unions: [],
|
|
107
|
+
scalars: []
|
|
108
|
+
};
|
|
109
|
+
namespaces.push(namespaceDoc);
|
|
110
|
+
function collectType(type, refDoc, array) {
|
|
111
|
+
typeMapping.set(type, refDoc);
|
|
112
|
+
array.push(refDoc);
|
|
161
113
|
}
|
|
162
|
-
|
|
163
|
-
|
|
164
|
-
|
|
114
|
+
navigateTypesInNamespace(namespace, {
|
|
115
|
+
decorator(dec) {
|
|
116
|
+
collectType(dec, extractDecoratorRefDoc(program, dec), namespaceDoc.decorators);
|
|
117
|
+
},
|
|
118
|
+
operation(operation) {
|
|
119
|
+
if (!isDeclaredType(operation)) {
|
|
120
|
+
return;
|
|
121
|
+
}
|
|
122
|
+
if (operation.interface === undefined) {
|
|
123
|
+
collectType(operation, extractOperationRefDoc(program, operation, undefined), namespaceDoc.operations);
|
|
124
|
+
}
|
|
125
|
+
},
|
|
126
|
+
interface(iface) {
|
|
127
|
+
if (!isDeclaredType(iface)) {
|
|
128
|
+
return;
|
|
129
|
+
}
|
|
130
|
+
collectType(iface, extractInterfaceRefDocs(program, iface), namespaceDoc.interfaces);
|
|
131
|
+
},
|
|
132
|
+
model(model) {
|
|
133
|
+
if (!isDeclaredType(model)) {
|
|
134
|
+
return;
|
|
135
|
+
}
|
|
136
|
+
if (model.name === "") {
|
|
137
|
+
return;
|
|
138
|
+
}
|
|
139
|
+
collectType(model, extractModelRefDocs(program, model), namespaceDoc.models);
|
|
140
|
+
},
|
|
141
|
+
enum(e) {
|
|
142
|
+
if (!isDeclaredType(e)) {
|
|
143
|
+
return;
|
|
144
|
+
}
|
|
145
|
+
collectType(e, extractEnumRefDoc(program, e), namespaceDoc.enums);
|
|
146
|
+
},
|
|
147
|
+
union(union) {
|
|
148
|
+
if (!isDeclaredType(union)) {
|
|
149
|
+
return;
|
|
150
|
+
}
|
|
151
|
+
if (union.name !== undefined) {
|
|
152
|
+
collectType(union, extractUnionRefDocs(program, union), namespaceDoc.unions);
|
|
153
|
+
}
|
|
154
|
+
},
|
|
155
|
+
scalar(scalar) {
|
|
156
|
+
collectType(scalar, extractScalarRefDocs(program, scalar), namespaceDoc.scalars);
|
|
157
|
+
}
|
|
158
|
+
}, {
|
|
159
|
+
includeTemplateDeclaration: true,
|
|
160
|
+
skipSubNamespaces: true
|
|
165
161
|
});
|
|
162
|
+
}
|
|
163
|
+
sort(namespaces);
|
|
164
|
+
for (const namespace of namespaces) {
|
|
165
|
+
sort(namespace.decorators);
|
|
166
|
+
sort(namespace.enums);
|
|
167
|
+
sort(namespace.interfaces);
|
|
168
|
+
sort(namespace.models);
|
|
169
|
+
sort(namespace.operations);
|
|
170
|
+
sort(namespace.unions);
|
|
171
|
+
sort(namespace.scalars);
|
|
172
|
+
}
|
|
173
|
+
function sort(arr) {
|
|
174
|
+
arr.sort((a, b) => a.id.localeCompare(b.id, "en"));
|
|
175
|
+
}
|
|
176
|
+
return diagnostics.wrap({
|
|
177
|
+
namespaces,
|
|
178
|
+
getNamedTypeRefDoc: type => typeMapping.get(type)
|
|
179
|
+
});
|
|
166
180
|
}
|
|
167
181
|
function extractTemplateParameterDocs(program, type) {
|
|
168
|
-
|
|
169
|
-
|
|
170
|
-
|
|
171
|
-
|
|
172
|
-
|
|
173
|
-
|
|
174
|
-
|
|
175
|
-
|
|
176
|
-
|
|
177
|
-
|
|
178
|
-
|
|
179
|
-
|
|
180
|
-
|
|
181
|
-
name: x.id.sv,
|
|
182
|
-
doc: templateParamsDocs.get(x.id.sv) ?? "",
|
|
183
|
-
};
|
|
182
|
+
if (isTemplateDeclaration(type)) {
|
|
183
|
+
const templateParamsDocs = getTemplateParameterDocs(type);
|
|
184
|
+
return type.node.templateParameters.map(x => {
|
|
185
|
+
const doc = templateParamsDocs.get(x.id.sv);
|
|
186
|
+
if (doc === undefined || doc === "") {
|
|
187
|
+
reportDiagnostic(program, {
|
|
188
|
+
code: "documentation-missing",
|
|
189
|
+
messageId: "templateParam",
|
|
190
|
+
format: {
|
|
191
|
+
name: type.name ?? "",
|
|
192
|
+
param: x.id.sv
|
|
193
|
+
},
|
|
194
|
+
target: NoTarget
|
|
184
195
|
});
|
|
185
|
-
|
|
186
|
-
|
|
187
|
-
|
|
188
|
-
|
|
196
|
+
}
|
|
197
|
+
return {
|
|
198
|
+
name: x.id.sv,
|
|
199
|
+
doc: templateParamsDocs.get(x.id.sv) ?? ""
|
|
200
|
+
};
|
|
201
|
+
});
|
|
202
|
+
} else {
|
|
203
|
+
return undefined;
|
|
204
|
+
}
|
|
189
205
|
}
|
|
190
206
|
function extractInterfaceRefDocs(program, iface) {
|
|
191
|
-
|
|
192
|
-
|
|
193
|
-
|
|
194
|
-
|
|
195
|
-
|
|
196
|
-
|
|
197
|
-
|
|
198
|
-
|
|
199
|
-
|
|
200
|
-
|
|
201
|
-
|
|
202
|
-
|
|
203
|
-
|
|
204
|
-
|
|
205
|
-
|
|
206
|
-
|
|
207
|
-
|
|
208
|
-
|
|
209
|
-
|
|
207
|
+
const doc = extractMainDoc(program, iface);
|
|
208
|
+
if (doc === undefined || doc === "") {
|
|
209
|
+
reportDiagnostic(program, {
|
|
210
|
+
code: "documentation-missing",
|
|
211
|
+
messageId: "interface",
|
|
212
|
+
format: {
|
|
213
|
+
name: iface.name ?? ""
|
|
214
|
+
},
|
|
215
|
+
target: NoTarget
|
|
216
|
+
});
|
|
217
|
+
}
|
|
218
|
+
return {
|
|
219
|
+
kind: "interface",
|
|
220
|
+
...extractBase(program, iface),
|
|
221
|
+
signature: getTypeSignature(iface),
|
|
222
|
+
type: iface,
|
|
223
|
+
templateParameters: extractTemplateParameterDocs(program, iface),
|
|
224
|
+
interfaceOperations: [...iface.operations.values()].map(x => extractOperationRefDoc(program, x, iface.name)),
|
|
225
|
+
doc: doc,
|
|
226
|
+
examples: extractExamples(iface)
|
|
227
|
+
};
|
|
210
228
|
}
|
|
211
229
|
function extractBase(program, type) {
|
|
212
|
-
|
|
213
|
-
|
|
214
|
-
|
|
215
|
-
|
|
216
|
-
|
|
217
|
-
|
|
230
|
+
const deprecated = getDeprecated(program, type);
|
|
231
|
+
return {
|
|
232
|
+
id: getNamedTypeId(type),
|
|
233
|
+
name: type.name,
|
|
234
|
+
deprecated: deprecated ? {
|
|
235
|
+
message: deprecated
|
|
236
|
+
} : undefined
|
|
237
|
+
};
|
|
218
238
|
}
|
|
219
239
|
function extractOperationRefDoc(program, operation, interfaceName) {
|
|
220
|
-
|
|
221
|
-
|
|
222
|
-
|
|
223
|
-
|
|
224
|
-
|
|
225
|
-
|
|
226
|
-
|
|
227
|
-
|
|
228
|
-
|
|
229
|
-
|
|
230
|
-
|
|
231
|
-
|
|
232
|
-
|
|
233
|
-
|
|
234
|
-
|
|
235
|
-
|
|
236
|
-
|
|
237
|
-
}
|
|
240
|
+
const doc = extractMainDoc(program, operation);
|
|
241
|
+
if (doc === undefined || doc === "") {
|
|
242
|
+
if (operation.interface !== undefined) {
|
|
243
|
+
reportDiagnostic(program, {
|
|
244
|
+
code: "documentation-missing",
|
|
245
|
+
messageId: "interfaceOperation",
|
|
246
|
+
format: {
|
|
247
|
+
name: `${operation.interface.name}.${operation.name}`
|
|
248
|
+
},
|
|
249
|
+
target: NoTarget
|
|
250
|
+
});
|
|
251
|
+
} else {
|
|
252
|
+
reportDiagnostic(program, {
|
|
253
|
+
code: "documentation-missing",
|
|
254
|
+
messageId: "operation",
|
|
255
|
+
format: {
|
|
256
|
+
name: operation.name ?? ""
|
|
257
|
+
},
|
|
258
|
+
target: NoTarget
|
|
259
|
+
});
|
|
238
260
|
}
|
|
239
|
-
|
|
240
|
-
|
|
241
|
-
|
|
242
|
-
|
|
243
|
-
|
|
244
|
-
|
|
245
|
-
|
|
246
|
-
|
|
247
|
-
|
|
248
|
-
|
|
261
|
+
}
|
|
262
|
+
return {
|
|
263
|
+
kind: "operation",
|
|
264
|
+
...extractBase(program, operation),
|
|
265
|
+
name: interfaceName ? `${interfaceName}.${operation.name}` : operation.name,
|
|
266
|
+
signature: getTypeSignature(operation),
|
|
267
|
+
type: operation,
|
|
268
|
+
templateParameters: extractTemplateParameterDocs(program, operation),
|
|
269
|
+
doc: doc,
|
|
270
|
+
examples: extractExamples(operation)
|
|
271
|
+
};
|
|
249
272
|
}
|
|
250
273
|
function extractDecoratorRefDoc(program, decorator) {
|
|
251
|
-
|
|
252
|
-
|
|
253
|
-
|
|
254
|
-
|
|
255
|
-
|
|
256
|
-
|
|
257
|
-
|
|
258
|
-
|
|
259
|
-
|
|
260
|
-
|
|
261
|
-
}
|
|
262
|
-
|
|
263
|
-
|
|
264
|
-
type: x,
|
|
265
|
-
doc: paramDoc.get(x.name) ?? "",
|
|
266
|
-
name: x.name,
|
|
267
|
-
optional: x.optional,
|
|
268
|
-
rest: x.rest,
|
|
269
|
-
};
|
|
270
|
-
});
|
|
271
|
-
const examples = extractExamples(decorator);
|
|
272
|
-
const mainDoc = extractMainDoc(program, decorator);
|
|
273
|
-
if (mainDoc === undefined || mainDoc === "") {
|
|
274
|
-
reportDiagnostic(program, {
|
|
275
|
-
code: "documentation-missing",
|
|
276
|
-
messageId: "decorator",
|
|
277
|
-
format: { name: decorator.name },
|
|
278
|
-
target: NoTarget,
|
|
279
|
-
});
|
|
274
|
+
const paramDoc = getParmeterDocs(decorator);
|
|
275
|
+
const parameters = decorator.parameters.map(x => {
|
|
276
|
+
const docVal = paramDoc.get(x.name);
|
|
277
|
+
if (docVal === undefined || docVal === "") {
|
|
278
|
+
reportDiagnostic(program, {
|
|
279
|
+
code: "documentation-missing",
|
|
280
|
+
messageId: "decoratorParam",
|
|
281
|
+
format: {
|
|
282
|
+
name: decorator.name,
|
|
283
|
+
param: x.name
|
|
284
|
+
},
|
|
285
|
+
target: NoTarget
|
|
286
|
+
});
|
|
280
287
|
}
|
|
281
288
|
return {
|
|
282
|
-
|
|
283
|
-
|
|
284
|
-
|
|
285
|
-
|
|
286
|
-
|
|
287
|
-
|
|
288
|
-
examples,
|
|
289
|
-
otherTags: [],
|
|
290
|
-
target: {
|
|
291
|
-
type: decorator.target,
|
|
292
|
-
doc: paramDoc.get(decorator.target.name) ?? "",
|
|
293
|
-
name: decorator.target.name,
|
|
294
|
-
optional: decorator.target.optional,
|
|
295
|
-
rest: decorator.target.rest,
|
|
296
|
-
},
|
|
289
|
+
kind: "decorator",
|
|
290
|
+
type: x,
|
|
291
|
+
doc: paramDoc.get(x.name) ?? "",
|
|
292
|
+
name: x.name,
|
|
293
|
+
optional: x.optional,
|
|
294
|
+
rest: x.rest
|
|
297
295
|
};
|
|
296
|
+
});
|
|
297
|
+
const examples = extractExamples(decorator);
|
|
298
|
+
const mainDoc = extractMainDoc(program, decorator);
|
|
299
|
+
if (mainDoc === undefined || mainDoc === "") {
|
|
300
|
+
reportDiagnostic(program, {
|
|
301
|
+
code: "documentation-missing",
|
|
302
|
+
messageId: "decorator",
|
|
303
|
+
format: {
|
|
304
|
+
name: decorator.name
|
|
305
|
+
},
|
|
306
|
+
target: NoTarget
|
|
307
|
+
});
|
|
308
|
+
}
|
|
309
|
+
return {
|
|
310
|
+
kind: "decorator",
|
|
311
|
+
...extractBase(program, decorator),
|
|
312
|
+
type: decorator,
|
|
313
|
+
signature: getTypeSignature(decorator),
|
|
314
|
+
doc: mainDoc,
|
|
315
|
+
parameters,
|
|
316
|
+
examples,
|
|
317
|
+
otherTags: [],
|
|
318
|
+
target: {
|
|
319
|
+
type: decorator.target,
|
|
320
|
+
doc: paramDoc.get(decorator.target.name) ?? "",
|
|
321
|
+
name: decorator.target.name,
|
|
322
|
+
optional: decorator.target.optional,
|
|
323
|
+
rest: decorator.target.rest
|
|
324
|
+
}
|
|
325
|
+
};
|
|
298
326
|
}
|
|
299
327
|
function extractModelRefDocs(program, type) {
|
|
300
|
-
|
|
301
|
-
|
|
302
|
-
|
|
303
|
-
|
|
304
|
-
|
|
305
|
-
|
|
306
|
-
|
|
307
|
-
|
|
308
|
-
|
|
309
|
-
|
|
310
|
-
|
|
311
|
-
|
|
312
|
-
|
|
313
|
-
|
|
314
|
-
|
|
315
|
-
|
|
316
|
-
|
|
317
|
-
|
|
318
|
-
|
|
328
|
+
const doc = extractMainDoc(program, type);
|
|
329
|
+
if (doc === undefined || doc === "") {
|
|
330
|
+
reportDiagnostic(program, {
|
|
331
|
+
code: "documentation-missing",
|
|
332
|
+
messageId: "model",
|
|
333
|
+
format: {
|
|
334
|
+
name: type.name ?? ""
|
|
335
|
+
},
|
|
336
|
+
target: NoTarget
|
|
337
|
+
});
|
|
338
|
+
}
|
|
339
|
+
return {
|
|
340
|
+
kind: "model",
|
|
341
|
+
...extractBase(program, type),
|
|
342
|
+
signature: getTypeSignature(type),
|
|
343
|
+
type,
|
|
344
|
+
templateParameters: extractTemplateParameterDocs(program, type),
|
|
345
|
+
doc: doc,
|
|
346
|
+
examples: extractExamples(type),
|
|
347
|
+
properties: new Map([...type.properties.values()].map(x => [x.name, extractModelPropertyRefDocs(program, x)]))
|
|
348
|
+
};
|
|
319
349
|
}
|
|
320
350
|
function extractModelPropertyRefDocs(program, type) {
|
|
321
|
-
|
|
322
|
-
|
|
323
|
-
|
|
324
|
-
|
|
325
|
-
|
|
326
|
-
|
|
327
|
-
|
|
328
|
-
|
|
351
|
+
const doc = extractMainDoc(program, type);
|
|
352
|
+
return {
|
|
353
|
+
...extractBase(program, type),
|
|
354
|
+
signature: getTypeSignature(type),
|
|
355
|
+
type,
|
|
356
|
+
doc: doc,
|
|
357
|
+
examples: extractExamples(type)
|
|
358
|
+
};
|
|
329
359
|
}
|
|
330
360
|
function extractEnumRefDoc(program, type) {
|
|
331
|
-
|
|
332
|
-
|
|
333
|
-
|
|
334
|
-
|
|
335
|
-
|
|
336
|
-
|
|
337
|
-
|
|
338
|
-
|
|
339
|
-
|
|
340
|
-
|
|
341
|
-
|
|
342
|
-
|
|
343
|
-
|
|
344
|
-
|
|
345
|
-
|
|
346
|
-
|
|
347
|
-
|
|
348
|
-
|
|
361
|
+
const doc = extractMainDoc(program, type);
|
|
362
|
+
if (doc === undefined || doc === "") {
|
|
363
|
+
reportDiagnostic(program, {
|
|
364
|
+
code: "documentation-missing",
|
|
365
|
+
messageId: "enum",
|
|
366
|
+
format: {
|
|
367
|
+
name: type.name ?? ""
|
|
368
|
+
},
|
|
369
|
+
target: NoTarget
|
|
370
|
+
});
|
|
371
|
+
}
|
|
372
|
+
return {
|
|
373
|
+
kind: "enum",
|
|
374
|
+
...extractBase(program, type),
|
|
375
|
+
signature: getTypeSignature(type),
|
|
376
|
+
type,
|
|
377
|
+
doc: doc,
|
|
378
|
+
examples: extractExamples(type),
|
|
379
|
+
members: new Map([...type.members.values()].map(x => [x.name, extractEnumMemberRefDocs(program, x)]))
|
|
380
|
+
};
|
|
349
381
|
}
|
|
350
382
|
function extractEnumMemberRefDocs(program, type) {
|
|
351
|
-
|
|
352
|
-
|
|
353
|
-
|
|
354
|
-
|
|
355
|
-
|
|
356
|
-
|
|
357
|
-
|
|
358
|
-
|
|
383
|
+
const doc = extractMainDoc(program, type);
|
|
384
|
+
return {
|
|
385
|
+
...extractBase(program, type),
|
|
386
|
+
signature: getTypeSignature(type),
|
|
387
|
+
type,
|
|
388
|
+
doc: doc,
|
|
389
|
+
examples: extractExamples(type)
|
|
390
|
+
};
|
|
359
391
|
}
|
|
360
392
|
function extractUnionRefDocs(program, type) {
|
|
361
|
-
|
|
362
|
-
|
|
363
|
-
|
|
364
|
-
|
|
365
|
-
|
|
366
|
-
|
|
367
|
-
|
|
368
|
-
|
|
369
|
-
|
|
370
|
-
|
|
371
|
-
|
|
372
|
-
|
|
373
|
-
|
|
374
|
-
|
|
375
|
-
|
|
376
|
-
|
|
377
|
-
|
|
378
|
-
|
|
393
|
+
const doc = extractMainDoc(program, type);
|
|
394
|
+
if (doc === undefined || doc === "") {
|
|
395
|
+
reportDiagnostic(program, {
|
|
396
|
+
code: "documentation-missing",
|
|
397
|
+
messageId: "union",
|
|
398
|
+
format: {
|
|
399
|
+
name: type.name ?? ""
|
|
400
|
+
},
|
|
401
|
+
target: NoTarget
|
|
402
|
+
});
|
|
403
|
+
}
|
|
404
|
+
return {
|
|
405
|
+
kind: "union",
|
|
406
|
+
...extractBase(program, type),
|
|
407
|
+
signature: getTypeSignature(type),
|
|
408
|
+
type,
|
|
409
|
+
templateParameters: extractTemplateParameterDocs(program, type),
|
|
410
|
+
doc: doc,
|
|
411
|
+
examples: extractExamples(type)
|
|
412
|
+
};
|
|
379
413
|
}
|
|
380
414
|
function extractScalarRefDocs(program, type) {
|
|
381
|
-
|
|
382
|
-
|
|
383
|
-
|
|
384
|
-
|
|
385
|
-
|
|
386
|
-
|
|
387
|
-
|
|
388
|
-
|
|
389
|
-
|
|
390
|
-
|
|
391
|
-
|
|
392
|
-
|
|
393
|
-
|
|
394
|
-
|
|
395
|
-
|
|
396
|
-
|
|
397
|
-
|
|
415
|
+
const doc = extractMainDoc(program, type);
|
|
416
|
+
if (doc === undefined || doc === "") {
|
|
417
|
+
reportDiagnostic(program, {
|
|
418
|
+
code: "documentation-missing",
|
|
419
|
+
messageId: "scalar",
|
|
420
|
+
format: {
|
|
421
|
+
name: type.name ?? ""
|
|
422
|
+
},
|
|
423
|
+
target: NoTarget
|
|
424
|
+
});
|
|
425
|
+
}
|
|
426
|
+
return {
|
|
427
|
+
kind: "scalar",
|
|
428
|
+
...extractBase(program, type),
|
|
429
|
+
signature: getTypeSignature(type),
|
|
430
|
+
type,
|
|
431
|
+
doc: doc,
|
|
432
|
+
examples: extractExamples(type)
|
|
433
|
+
};
|
|
398
434
|
}
|
|
399
435
|
function extractMainDoc(program, type) {
|
|
400
|
-
|
|
401
|
-
|
|
402
|
-
|
|
403
|
-
|
|
404
|
-
}
|
|
436
|
+
const mainDocs = [];
|
|
437
|
+
for (const doc of type.node?.docs ?? []) {
|
|
438
|
+
for (const dContent of doc.content) {
|
|
439
|
+
mainDocs.push(dContent.text);
|
|
405
440
|
}
|
|
406
|
-
|
|
441
|
+
}
|
|
442
|
+
return mainDocs.length > 0 ? mainDocs.join("\n") : getDoc(program, type) ?? "";
|
|
407
443
|
}
|
|
408
444
|
function extractExamples(type) {
|
|
409
|
-
|
|
410
|
-
|
|
411
|
-
|
|
412
|
-
|
|
413
|
-
|
|
414
|
-
|
|
415
|
-
}
|
|
416
|
-
}
|
|
445
|
+
const examples = [];
|
|
446
|
+
for (const doc of type.node?.docs ?? []) {
|
|
447
|
+
for (const dTag of doc.tags) {
|
|
448
|
+
if (dTag.kind === SyntaxKind.DocUnknownTag) {
|
|
449
|
+
if (dTag.tagName.sv === "example") {
|
|
450
|
+
examples.push(extractExample(dTag));
|
|
417
451
|
}
|
|
452
|
+
}
|
|
418
453
|
}
|
|
419
|
-
|
|
454
|
+
}
|
|
455
|
+
return examples;
|
|
420
456
|
}
|
|
421
457
|
function getNamedTypeId(type) {
|
|
422
|
-
|
|
423
|
-
|
|
424
|
-
|
|
425
|
-
|
|
426
|
-
|
|
427
|
-
|
|
428
|
-
|
|
429
|
-
|
|
458
|
+
switch (type.kind) {
|
|
459
|
+
case "Decorator":
|
|
460
|
+
return getDecoratorId(type);
|
|
461
|
+
case "Operation":
|
|
462
|
+
return getQualifier(type.interface ?? type.namespace) + type.name;
|
|
463
|
+
default:
|
|
464
|
+
return "namespace" in type ? getQualifier(type.namespace) + type.name : type.name;
|
|
465
|
+
}
|
|
430
466
|
}
|
|
431
467
|
function getDecoratorId(decorator) {
|
|
432
|
-
|
|
468
|
+
return "@" + getQualifier(decorator.namespace) + decorator.name.slice(1);
|
|
433
469
|
}
|
|
434
470
|
function checkIfTagHasDocOnSameLine(tag) {
|
|
435
|
-
|
|
436
|
-
|
|
437
|
-
|
|
438
|
-
|
|
439
|
-
|
|
440
|
-
|
|
441
|
-
|
|
442
|
-
|
|
443
|
-
|
|
444
|
-
|
|
445
|
-
|
|
446
|
-
|
|
447
|
-
}
|
|
471
|
+
const start = tag.content[0]?.pos;
|
|
472
|
+
const end = tag.content[0]?.end;
|
|
473
|
+
const file = getSourceLocation(tag.content[0]).file;
|
|
474
|
+
let hasFirstLine = false;
|
|
475
|
+
for (let i = start; i < end; i++) {
|
|
476
|
+
const ch = file.text[i];
|
|
477
|
+
if (ch === "\n") {
|
|
478
|
+
break;
|
|
479
|
+
}
|
|
480
|
+
// Todo reuse compiler whitespace logic or have a way to get this info from the parser.
|
|
481
|
+
if (ch !== " ") {
|
|
482
|
+
hasFirstLine = true;
|
|
448
483
|
}
|
|
449
|
-
|
|
484
|
+
}
|
|
485
|
+
return hasFirstLine;
|
|
450
486
|
}
|
|
451
487
|
function extractExample(tag) {
|
|
452
|
-
|
|
453
|
-
|
|
454
|
-
|
|
455
|
-
|
|
456
|
-
|
|
457
|
-
|
|
458
|
-
|
|
459
|
-
|
|
460
|
-
|
|
488
|
+
const content = getDocContent(tag.content);
|
|
489
|
+
const hasInfoOnFirstLine = checkIfTagHasDocOnSameLine(tag);
|
|
490
|
+
if (hasInfoOnFirstLine) {
|
|
491
|
+
const [title, ...contents] = content.split("\n");
|
|
492
|
+
return {
|
|
493
|
+
title,
|
|
494
|
+
content: contents.join("\n")
|
|
495
|
+
};
|
|
496
|
+
} else {
|
|
497
|
+
return {
|
|
498
|
+
content
|
|
499
|
+
};
|
|
500
|
+
}
|
|
461
501
|
}
|
|
462
502
|
function getParmeterDocs(type) {
|
|
463
|
-
|
|
464
|
-
|
|
465
|
-
|
|
466
|
-
|
|
467
|
-
|
|
468
|
-
|
|
469
|
-
}
|
|
503
|
+
const map = new Map();
|
|
504
|
+
for (const d of type?.node?.docs ?? []) {
|
|
505
|
+
for (const tag of d.tags) {
|
|
506
|
+
if (tag.kind === SyntaxKind.DocParamTag) {
|
|
507
|
+
map.set(tag.paramName.sv, getDocContent(tag.content));
|
|
508
|
+
}
|
|
470
509
|
}
|
|
471
|
-
|
|
510
|
+
}
|
|
511
|
+
return map;
|
|
472
512
|
}
|
|
473
513
|
function getTemplateParameterDocs(type) {
|
|
474
|
-
|
|
475
|
-
|
|
476
|
-
|
|
477
|
-
|
|
478
|
-
|
|
479
|
-
|
|
480
|
-
}
|
|
514
|
+
const map = new Map();
|
|
515
|
+
for (const d of type?.node?.docs ?? []) {
|
|
516
|
+
for (const tag of d.tags) {
|
|
517
|
+
if (tag.kind === SyntaxKind.DocTemplateTag) {
|
|
518
|
+
map.set(tag.paramName.sv, getDocContent(tag.content));
|
|
519
|
+
}
|
|
481
520
|
}
|
|
482
|
-
|
|
521
|
+
}
|
|
522
|
+
return map;
|
|
483
523
|
}
|
|
484
524
|
function getDocContent(content) {
|
|
485
|
-
|
|
486
|
-
|
|
487
|
-
|
|
488
|
-
|
|
489
|
-
|
|
490
|
-
|
|
525
|
+
const docs = [];
|
|
526
|
+
for (const node of content) {
|
|
527
|
+
compilerAssert(node.kind === SyntaxKind.DocText, "No other doc content node kinds exist yet. Update this code appropriately when more are added.");
|
|
528
|
+
docs.push(node.text);
|
|
529
|
+
}
|
|
530
|
+
return docs.join("");
|
|
491
531
|
}
|
|
492
532
|
function extractEmitterOptionsRefDoc(options) {
|
|
493
|
-
|
|
494
|
-
return {
|
|
495
|
-
name,
|
|
496
|
-
type: value.enum
|
|
497
|
-
? value.enum.map((x) => (typeof x === "string" ? `"${x}"` : x)).join(" | ")
|
|
498
|
-
: value.type,
|
|
499
|
-
doc: value.description ?? "",
|
|
500
|
-
};
|
|
501
|
-
});
|
|
502
|
-
}
|
|
503
|
-
function extractLinterRefDoc(libName, linter) {
|
|
533
|
+
return Object.entries(options.properties).map(([name, value]) => {
|
|
504
534
|
return {
|
|
505
|
-
|
|
506
|
-
|
|
535
|
+
name,
|
|
536
|
+
type: value.enum ? value.enum.map(x => typeof x === "string" ? `"${x}"` : x).join(" | ") : value.type,
|
|
537
|
+
doc: value.description ?? ""
|
|
507
538
|
};
|
|
539
|
+
});
|
|
508
540
|
}
|
|
509
|
-
function
|
|
510
|
-
|
|
511
|
-
|
|
512
|
-
|
|
513
|
-
|
|
514
|
-
id: fullName,
|
|
515
|
-
name: fullName,
|
|
516
|
-
ruleSet,
|
|
517
|
-
};
|
|
518
|
-
});
|
|
541
|
+
function extractLinterRefDoc(libName, linter) {
|
|
542
|
+
return {
|
|
543
|
+
ruleSets: linter.ruleSets && extractLinterRuleSetsRefDoc(libName, linter.ruleSets),
|
|
544
|
+
rules: linter.rules.map(rule => extractLinterRuleRefDoc(libName, rule))
|
|
545
|
+
};
|
|
519
546
|
}
|
|
520
|
-
function
|
|
521
|
-
|
|
547
|
+
function extractLinterRuleSetsRefDoc(libName, ruleSets) {
|
|
548
|
+
return Object.entries(ruleSets).map(([name, ruleSet]) => {
|
|
549
|
+
const fullName = `${libName}/${name}`;
|
|
522
550
|
return {
|
|
523
|
-
|
|
524
|
-
|
|
525
|
-
|
|
526
|
-
|
|
551
|
+
kind: "ruleset",
|
|
552
|
+
id: fullName,
|
|
553
|
+
name: fullName,
|
|
554
|
+
ruleSet
|
|
527
555
|
};
|
|
556
|
+
});
|
|
528
557
|
}
|
|
529
|
-
|
|
558
|
+
function extractLinterRuleRefDoc(libName, rule) {
|
|
559
|
+
const fullName = `${libName}/${rule.name}`;
|
|
560
|
+
return {
|
|
561
|
+
kind: "rule",
|
|
562
|
+
id: fullName,
|
|
563
|
+
name: fullName,
|
|
564
|
+
rule
|
|
565
|
+
};
|
|
566
|
+
}
|