Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Add more sphinxJsConfig hooks #139

Merged
merged 1 commit into from
May 3, 2024
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
10 changes: 8 additions & 2 deletions sphinx_js/js/call_typedoc.ts
Original file line number Diff line number Diff line change
Expand Up @@ -55,9 +55,13 @@ async function main() {
console.log(app.toString());
return ExitCodes.Ok;
}
app.extraData = {};
app.options.getValue("modifierTags").push("@hidetype");
const config = await loadConfig(app.options.getValue("sphinxJsConfig"));
const userConfigPath = app.options.getValue("sphinxJsConfig");
const config = await loadConfig(userConfigPath);
app.logger.info(`Loaded user config from ${userConfigPath}`);
const symbolToType = redirectPrivateTypes(app);
await config.preConvert?.(app);

const project = await app.convert();
if (!project) {
Expand All @@ -82,7 +86,9 @@ async function main() {
const converter = new Converter(project, basePath, config, symbolToType);
converter.computePaths();
const space = app.options.getValue("pretty") ? "\t" : "";
const res = JSON.stringify(converter.convertAll(), null, space);
const result = converter.convertAll();
await config.postConvert?.(app, project, converter.typedocToIRMap);
const res = JSON.stringify([result, app.extraData], null, space);
const json = app.options.getValue("json");
await writeFile(json, res);
app.logger.info(`JSON written to ${json}`);
Expand Down
6 changes: 4 additions & 2 deletions sphinx_js/js/convertTopLevel.ts
Original file line number Diff line number Diff line change
Expand Up @@ -29,8 +29,6 @@ import {
TopLevel,
Type,
TypeParam,
TypeXRefInternal,
TypeXRefExternal,
} from "./ir.ts";
import { sep, relative } from "path";
import { SphinxJsConfig } from "./sphinxJsConfig.ts";
Expand Down Expand Up @@ -341,6 +339,7 @@ export class Converter {
Pathname
>;
readonly documentationRoots: Set<DeclarationReflection | SignatureReflection>;
readonly typedocToIRMap: Map<DeclarationReflection, TopLevel>;

constructor(
project: ProjectReflection,
Expand All @@ -352,9 +351,11 @@ export class Converter {
this.basePath = basePath;
this.config = config;
this.symbolToType = symbolToType;

this.pathMap = new Map();
this.filePathMap = new Map();
this.documentationRoots = new Set();
this.typedocToIRMap = new Map();
}

renderType(type: SomeType, context: TypeContext = TypeContext.none): Type {
Expand Down Expand Up @@ -397,6 +398,7 @@ export class Converter {
const node = todo.pop()!;
const [converted, rest] = this.toIr(node);
if (converted) {
this.typedocToIRMap.set(node, converted);
result.push(converted);
}
todo.push(...(rest || []));
Expand Down
8 changes: 6 additions & 2 deletions sphinx_js/js/redirectPrivateAliases.ts
Original file line number Diff line number Diff line change
Expand Up @@ -101,13 +101,17 @@ export function redirectPrivateTypes(app: Application): ReadonlySymbolToType {
}

const origCreateSymbolReference = ReferenceType.createSymbolReference;
ReferenceType.createSymbolReference = function (symbol, context, name) {
ReferenceType.createSymbolReference = function (
symbol: ts.Symbol,
context: Context,
name: string,
) {
const owningModule = getOwningModule(context);
getReferencedSymbols(owningModule).add(symbol);
return origCreateSymbolReference.call(this, symbol, context, name);
};

function onResolveBegin(context: Context) {
function onResolveBegin(context: Context): void {
const modules: (DeclarationReflection | ProjectReflection)[] =
context.project.getChildrenByKind(ReflectionKind.Module);
if (modules.length === 0) {
Expand Down
16 changes: 14 additions & 2 deletions sphinx_js/js/sphinxJsConfig.ts
Original file line number Diff line number Diff line change
@@ -1,5 +1,17 @@
import { ParameterReflection } from "typedoc";
import {
Application,
DeclarationReflection,
ParameterReflection,
ProjectReflection,
} from "typedoc";
import { TopLevel } from "./ir.ts";

export type SphinxJsConfig = {
shouldDestructureArg?: (p: ParameterReflection) => boolean;
shouldDestructureArg?: (param: ParameterReflection) => boolean;
preConvert?: (app: Application) => Promise<void>;
postConvert?: (
app: Application,
project: ProjectReflection,
typedocToIRMap: ReadonlyMap<DeclarationReflection, TopLevel>,
) => Promise<void>;
};
6 changes: 5 additions & 1 deletion sphinx_js/js/typedocPatches.ts
Original file line number Diff line number Diff line change
@@ -1,7 +1,11 @@
/** Declare some extra stuff we monkeypatch on to typedoc */

declare module "typedoc" {
export interface TypeDocOptionMap {
sphinxJsConfig: string;
}
export interface Application {
extraData: {
[key: string]: any;
};
}
}
2 changes: 1 addition & 1 deletion sphinx_js/js/typedocPlugin.ts
Original file line number Diff line number Diff line change
Expand Up @@ -5,7 +5,7 @@
// TODO: we don't seem to resolve imports correctly in this file, but it works
// to do a dynamic import. Figure out why.

export async function load(app: any) {
export async function load(app: any): Promise<void> {
// @ts-ignore
const typedoc = await import("typedoc");
app.options.addDeclaration({
Expand Down
17 changes: 11 additions & 6 deletions sphinx_js/typedoc.py
Original file line number Diff line number Diff line change
Expand Up @@ -11,7 +11,7 @@
from operator import attrgetter
from pathlib import Path
from tempfile import NamedTemporaryFile
from typing import Literal
from typing import Any, Literal

from sphinx.application import Sphinx
from sphinx.errors import SphinxError
Expand Down Expand Up @@ -54,7 +54,7 @@ def typedoc_output(
typedoc_config_path: str | None,
tsconfig_path: str | None,
ts_sphinx_js_config: str | None,
) -> list[ir.TopLevelUnion]:
) -> tuple[list[ir.TopLevelUnion], dict[str, Any]]:
"""Return the loaded JSON output of the TypeDoc command run over the given
paths."""
typedoc = search_node_modules("typedoc", "typedoc/bin/typedoc", sphinx_conf_dir)
Expand Down Expand Up @@ -100,14 +100,19 @@ def typedoc_output(
else:
raise
# typedoc emits a valid JSON file even if it finds no TS files in the dir:
return ir.json_to_ir(load(temp))
json_ir, extra_data = load(temp)
return ir.json_to_ir(json_ir), extra_data


class Analyzer:
_objects_by_path: SuffixTree[ir.TopLevel]
_modules_by_path: SuffixTree[ir.Module]
_extra_data: dict[str, Any]

def __init__(self, objects: Sequence[ir.TopLevel], base_dir: str) -> None:
def __init__(
self, objects: Sequence[ir.TopLevel], extra_data: dict[str, Any], base_dir: str
) -> None:
self._extra_data = extra_data
self._base_dir = base_dir
self._objects_by_path = SuffixTree()
self._objects_by_path.add_many((obj.path.segments, obj) for obj in objects)
Expand All @@ -130,15 +135,15 @@ def get_object(
def from_disk(
cls, abs_source_paths: Sequence[str], app: Sphinx, base_dir: str
) -> "Analyzer":
json = typedoc_output(
json, extra_data = typedoc_output(
abs_source_paths,
base_dir=base_dir,
sphinx_conf_dir=app.confdir,
typedoc_config_path=app.config.jsdoc_config_path,
tsconfig_path=app.config.jsdoc_tsconfig_path,
ts_sphinx_js_config=app.config.ts_sphinx_js_config,
)
return cls(json, base_dir)
return cls(json, extra_data, base_dir)

def _get_toplevel_objects(
self, ir_objects: Sequence[ir.TopLevel]
Expand Down
4 changes: 2 additions & 2 deletions tests/testing.py
Original file line number Diff line number Diff line change
Expand Up @@ -82,7 +82,7 @@ def setup_class(cls):

config_file = Path(__file__).parent / "sphinxJsConfig.ts"

cls.json = typedoc_output(
[cls.json, cls.extra_data] = typedoc_output(
abs_source_paths=[join(cls._source_dir, file) for file in cls.files],
base_dir=cls._source_dir,
ts_sphinx_js_config=str(config_file),
Expand All @@ -103,7 +103,7 @@ def setup_class(cls):
def should_destructure(sig, p):
return p.name == "destructureThisPlease"

cls.analyzer = TsAnalyzer(cls.json, cls._source_dir)
cls.analyzer = TsAnalyzer(cls.json, cls.extra_data, cls._source_dir)


NO_MATCH = object()
Expand Down
Loading