Skip to content
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
120 changes: 120 additions & 0 deletions Cargo.lock

Some generated files are not rendered by default. Learn more about how customized files appear on GitHub.

1 change: 1 addition & 0 deletions Cargo.toml
Original file line number Diff line number Diff line change
Expand Up @@ -20,6 +20,7 @@ globset = { version = "0.4.18" }
ignore = { version = "0.4.25" }
jsonschema = { version = "0.46.5", default-features = false }
jsonc-parser = { version = "0.32.4", features = ["serde"] }
mermaid-rs-renderer = { version = "0.2.2", default-features = false }
napi = { version = "3.9.0", default-features = false, features = ["napi4"] }
napi-derive = { version = "3.5.6" }
oxc = { version = "0.132.0", features = ["ast_visit"] }
Expand Down
13 changes: 13 additions & 0 deletions MODULE.bazel.lock

Large diffs are not rendered by default.

6 changes: 4 additions & 2 deletions README.md
Original file line number Diff line number Diff line change
Expand Up @@ -142,15 +142,17 @@ codescythe query somepath src/main.ts src/module.ts
codescythe query somepaths src/main.ts src/features/
codescythe query allpaths src/main.ts src/runtime.ts:initRuntime --json
codescythe query allpaths src/main.ts src/runtime.ts:initRuntime --output mermaid
codescythe query allpaths src/main.ts src/runtime.ts:initRuntime --output svg > graph.svg
```

Selectors can point at files, directories, or exported symbols written as
`<file>:<symbol>`. `somepath` returns one shortest path, `somepaths` returns one
shortest path per reachable matched target, and `allpaths` returns the subgraph
of every node and edge that lies on a path from the source selector to the target
selector. JSON output includes stable file/export nodes and typed import or
re-export edges, and Mermaid output renders the same query graph as a
`flowchart LR` diagram.
re-export edges. Mermaid output renders the same query graph as a `flowchart LR`
diagram, and SVG output renders that Mermaid source with the pure-Rust
`mermaid-rs-renderer` crate.

## Contributing

Expand Down
1 change: 1 addition & 0 deletions crates/codescythe/BUILD.bazel
Original file line number Diff line number Diff line change
Expand Up @@ -8,6 +8,7 @@ COMMON_DEPS = [
"@crates//:ignore",
"@crates//:jsonschema",
"@crates//:jsonc-parser",
"@crates//:mermaid-rs-renderer",
"@crates//:oxc",
"@crates//:oxc_allocator",
"@crates//:oxc_ast",
Expand Down
1 change: 1 addition & 0 deletions crates/codescythe/Cargo.toml
Original file line number Diff line number Diff line change
Expand Up @@ -20,6 +20,7 @@ globset.workspace = true
ignore.workspace = true
jsonschema.workspace = true
jsonc-parser.workspace = true
mermaid-rs-renderer.workspace = true
oxc.workspace = true
oxc_allocator.workspace = true
oxc_ast.workspace = true
Expand Down
2 changes: 1 addition & 1 deletion crates/codescythe/analyze.rs
Original file line number Diff line number Diff line change
Expand Up @@ -16,7 +16,7 @@ pub use explain::ignored_unresolved_patterns_for_file;
pub use query::{
QueryEdge, QueryEdgeKind, QueryGraph, QueryKind, QueryNode, QueryNodeKind, QueryPath,
QueryRequest, QueryResult, QuerySelector, QuerySelectorKind, QueryUnresolvedImport, query_path,
render_query_mermaid,
render_query_mermaid, render_query_svg,
};
pub use resolver::{
source_alias_fix_blocking_ignore_warnings_for_config, source_alias_ignore_warnings_for_config,
Expand Down
5 changes: 5 additions & 0 deletions crates/codescythe/analyze/query.rs
Original file line number Diff line number Diff line change
Expand Up @@ -308,6 +308,11 @@ pub fn render_query_mermaid(result: &QueryResult) -> String {
lines.join("\n")
}

pub fn render_query_svg(result: &QueryResult) -> Result<String> {
let mermaid = render_query_mermaid(result);
mermaid_rs_renderer::render(&mermaid).context("failed to render query Mermaid as SVG")
}

fn query_result_graph(result: &QueryResult) -> QueryGraph {
if let Some(graph) = &result.graph {
return graph.clone();
Expand Down
4 changes: 4 additions & 0 deletions crates/codescythe/analyze/tests.rs
Original file line number Diff line number Diff line change
Expand Up @@ -1512,6 +1512,10 @@ fn query_somepath_tracks_named_export_edges() {
assert!(mermaid.contains("src/main.ts"));
assert!(mermaid.contains("src/module.ts:used"));
assert!(mermaid.contains("named import ./module:used"));

let svg = render_query_svg(&result).unwrap();
assert!(svg.contains("<svg"), "{svg}");
assert!(svg.contains("src/module.ts:used"), "{svg}");
}

#[test]
Expand Down
2 changes: 1 addition & 1 deletion crates/codescythe/lib.rs
Original file line number Diff line number Diff line change
Expand Up @@ -10,7 +10,7 @@ pub use analyze::{
QueryGraph, QueryKind, QueryNode, QueryNodeKind, QueryPath, QueryRequest, QueryResult,
QuerySelector, QuerySelectorKind, QueryUnresolvedImport, SourceAliasIgnoreWarning, SymbolIssue,
UnresolvedImportCandidateFile, UnresolvedImportExplanation, UnresolvedImportMatchedAlias,
analyze_path, doctor_config, query_path, render_query_mermaid,
analyze_path, doctor_config, query_path, render_query_mermaid, render_query_svg,
source_alias_fix_blocking_ignore_warnings_for_config, source_alias_ignore_warnings_for_config,
};
pub use config::{
Expand Down
19 changes: 19 additions & 0 deletions crates/codescythe_cli/e2e.rs
Original file line number Diff line number Diff line change
Expand Up @@ -291,6 +291,25 @@ fn cli_queries_dependency_paths() {
assert!(mermaid.contains("flowchart LR"), "{mermaid}");
assert!(mermaid.contains("src/module.ts:used"), "{mermaid}");
assert!(mermaid.contains("named import ./module:used"), "{mermaid}");

let svg_output = Command::new(runfile("crates/codescythe_cli/codescythe"))
.args([
"query",
"somepath",
"-C",
path_arg(&runfile("tests/fixtures/test-file-usage")),
"--output",
"svg",
"src/main.ts",
"src/module.ts:used",
])
.output()
.expect("failed to run codescythe query with svg output");

assert!(svg_output.status.success(), "{}", output_text(&svg_output));
let svg = String::from_utf8_lossy(&svg_output.stdout);
assert!(svg.contains("<svg"), "{svg}");
assert!(svg.contains("src/module.ts:used"), "{svg}");
}

#[test]
Expand Down
4 changes: 4 additions & 0 deletions crates/codescythe_cli/main.rs
Original file line number Diff line number Diff line change
Expand Up @@ -95,6 +95,7 @@ enum QueryOutputFormat {
Text,
Json,
Mermaid,
Svg,
}

fn main() -> ExitCode {
Expand Down Expand Up @@ -241,6 +242,9 @@ fn run_query_command(args: QueryArgs) -> Result<bool> {
QueryOutputFormat::Mermaid => {
print!("{}", codescythe::render_query_mermaid(&result));
}
QueryOutputFormat::Svg => {
print!("{}", codescythe::render_query_svg(&result)?);
}
QueryOutputFormat::Text => {
print_query_report(&result);
}
Expand Down