@typespec/compiler
Version:
TypeSpec Compiler Preview
103 lines • 3.55 kB
JavaScript
import { getSymNode } from "../core/binder.js";
import { compilerAssert } from "../core/diagnostics.js";
import { getDocData } from "../core/intrinsic-type-state.js";
import { isType } from "../core/type-utils.js";
import { SyntaxKind } from "../core/types.js";
import { getSymbolSignature } from "./type-signature.js";
/**
* Get the detailed documentation for a symbol.
* @param program The program
* @internal
*/
export function getSymbolDetails(program, symbol, options = {
includeSignature: true,
includeParameterTags: true,
includeExpandedDefinition: false,
}) {
const lines = [];
if (options.includeSignature) {
lines.push(getSymbolSignature(program, symbol));
}
const doc = getSymbolDocumentation(program, symbol);
if (doc) {
lines.push(doc);
}
for (const node of symbol.declarations) {
for (const doc of node?.docs ?? []) {
for (const tag of doc.tags) {
if (!options.includeParameterTags &&
(tag.kind === SyntaxKind.DocParamTag || tag.kind === SyntaxKind.DocTemplateTag)) {
continue;
}
lines.push(
//prettier-ignore
`_@${tag.tagName.sv}_${"paramName" in tag ? ` \`${tag.paramName.sv}\`` : ""} —\n${getDocContent(tag.content)}`);
}
}
}
if (options.includeExpandedDefinition) {
lines.push(`*Full Definition:*`);
lines.push(getSymbolSignature(program, symbol, {
includeBody: true,
}));
}
return lines.join("\n\n");
}
function getSymbolDocumentation(program, symbol) {
const docs = [];
for (const node of [...symbol.declarations, ...(symbol.node ? [symbol.node] : [])]) {
// Add /** ... */ developer docs
for (const d of node.docs ?? []) {
docs.push(getDocContent(d.content));
}
}
// Add @doc(...) API docs
let type = symbol.type;
if (!type) {
const entity = program.checker.getTypeOrValueForNode(getSymNode(symbol));
if (entity && isType(entity)) {
type = entity;
}
}
if (type) {
const apiDocs = getDocData(program, type);
// The doc comment is already included above we don't want to duplicate. Only include if it was specificed via `@doc`
if (apiDocs && apiDocs.source === "decorator") {
docs.push(apiDocs.value);
}
}
return docs.join("\n\n");
}
/** @internal */
export function getParameterDocumentation(program, type) {
const map = new Map();
for (const d of type?.node?.docs ?? []) {
for (const tag of d.tags) {
if (tag.kind === SyntaxKind.DocParamTag) {
map.set(tag.paramName.sv, getDocContent(tag.content));
}
}
}
return map;
}
/** @internal */
export function getTemplateParameterDocumentation(node) {
const map = new Map();
for (const d of node?.docs ?? []) {
for (const tag of d.tags) {
if (tag.kind === SyntaxKind.DocTemplateTag) {
map.set(tag.paramName.sv, getDocContent(tag.content));
}
}
}
return map;
}
function getDocContent(content) {
const docs = [];
for (const node of content) {
compilerAssert(node.kind === SyntaxKind.DocText, "No other doc content node kinds exist yet. Update this code appropriately when more are added.");
docs.push(node.text);
}
return docs.join("");
}
//# sourceMappingURL=type-details.js.map