Document workspace package graphs
This commit is contained in:
parent
0c612ad7fd
commit
0337974923
@ -20,12 +20,14 @@ ABI promise.
|
||||
- Diagnose missing `default_package` references during workspace loading.
|
||||
- Diagnose duplicate workspace members after path normalization before package
|
||||
loading.
|
||||
- Add workspace package and dependency summaries to `glagol doc`.
|
||||
- Keep dependency resolution local-path-only and deterministic.
|
||||
|
||||
## Acceptance Gates
|
||||
|
||||
- `cargo test --test project_mode workspace_default_package`
|
||||
- `cargo test --test project_mode workspace_package_boundaries`
|
||||
- `cargo test --test dx_v1_7 doc_generates_workspace_package_summary`
|
||||
- `cargo fmt --check`
|
||||
- `git diff --check`
|
||||
|
||||
|
||||
@ -156,8 +156,10 @@ After `1.0.0-beta.4`, `main` is tracking a package/workspace discipline slice.
|
||||
Local workspaces may declare `[workspace] default_package = "name"` to select
|
||||
the build/run entry package when multiple packages have entry modules.
|
||||
Duplicate normalized workspace members and missing default-package references
|
||||
are now dedicated diagnostics. Remote registries, lockfiles, semantic-version
|
||||
solving, package publishing, and stable package ABI/layout remain deferred.
|
||||
are now dedicated diagnostics. `glagol doc <workspace> -o <dir>` includes a
|
||||
workspace package/dependency summary. Remote registries, lockfiles,
|
||||
semantic-version solving, package publishing, and stable package ABI/layout
|
||||
remain deferred.
|
||||
|
||||
## Documentation
|
||||
|
||||
|
||||
@ -4,14 +4,14 @@ use crate::{
|
||||
ast::Program,
|
||||
diag::Diagnostic,
|
||||
lexer, lower,
|
||||
project::{self, SourceFile, ToolFailure},
|
||||
project::{self, ProjectArtifact, SourceFile, ToolFailure, WorkspaceArtifact},
|
||||
sexpr::{Atom, SExpr, SExprKind},
|
||||
};
|
||||
|
||||
pub fn generate(input: &str, output_dir: &str) -> Result<(), ToolFailure> {
|
||||
let docs = if project::is_project_input(input) {
|
||||
let loaded = project::load_project_sources_for_tools(input)?;
|
||||
render_project(&loaded.artifact.project_name, &loaded.sources)?
|
||||
render_project(&loaded.artifact, &loaded.sources)?
|
||||
} else {
|
||||
let source = fs::read_to_string(input).map_err(|err| ToolFailure {
|
||||
diagnostics: vec![Diagnostic::new(
|
||||
@ -52,11 +52,17 @@ pub fn generate(input: &str, output_dir: &str) -> Result<(), ToolFailure> {
|
||||
})
|
||||
}
|
||||
|
||||
fn render_project(title: &str, sources: &[SourceFile]) -> Result<String, ToolFailure> {
|
||||
fn render_project(
|
||||
artifact: &ProjectArtifact,
|
||||
sources: &[SourceFile],
|
||||
) -> Result<String, ToolFailure> {
|
||||
let mut out = String::new();
|
||||
out.push_str("# Project ");
|
||||
out.push_str(title);
|
||||
out.push_str(&artifact.project_name);
|
||||
out.push_str("\n\n");
|
||||
if let Some(workspace) = &artifact.workspace {
|
||||
render_workspace(&mut out, workspace);
|
||||
}
|
||||
for source in sources {
|
||||
let module = document_source(source)?;
|
||||
render_module(&mut out, &module);
|
||||
@ -64,6 +70,35 @@ fn render_project(title: &str, sources: &[SourceFile]) -> Result<String, ToolFai
|
||||
Ok(out)
|
||||
}
|
||||
|
||||
fn render_workspace(out: &mut String, workspace: &WorkspaceArtifact) {
|
||||
out.push_str("## Workspace\n\n");
|
||||
render_list(out, "Members", &workspace.members);
|
||||
|
||||
let packages = workspace
|
||||
.packages
|
||||
.iter()
|
||||
.map(|package| {
|
||||
format!(
|
||||
"{} {} (entry {})",
|
||||
package.name, package.version, package.entry
|
||||
)
|
||||
})
|
||||
.collect::<Vec<_>>();
|
||||
render_list(out, "Packages", &packages);
|
||||
|
||||
let dependencies = workspace
|
||||
.dependencies
|
||||
.iter()
|
||||
.map(|dependency| {
|
||||
format!(
|
||||
"{} -> {} ({}, {})",
|
||||
dependency.from, dependency.to, dependency.kind, dependency.path
|
||||
)
|
||||
})
|
||||
.collect::<Vec<_>>();
|
||||
render_list(out, "Package Dependencies", &dependencies);
|
||||
}
|
||||
|
||||
fn render_file(title: &str, sources: &[SourceFile]) -> Result<String, ToolFailure> {
|
||||
let mut out = String::new();
|
||||
out.push_str("# File ");
|
||||
|
||||
@ -351,6 +351,38 @@ fn doc_generates_markdown_for_file_and_project() {
|
||||
assert!(project_index.contains("- `math`"));
|
||||
}
|
||||
|
||||
#[test]
|
||||
fn doc_generates_workspace_package_summary() {
|
||||
let workspace = unique_path("doc-workspace");
|
||||
let new_output = run_glagol([
|
||||
"new".as_ref(),
|
||||
workspace.as_os_str(),
|
||||
"--template".as_ref(),
|
||||
"workspace".as_ref(),
|
||||
]);
|
||||
assert_success("doc workspace scaffold", &new_output);
|
||||
|
||||
let workspace_docs = unique_path("doc-workspace-out");
|
||||
let doc_output = run_glagol([
|
||||
"doc".as_ref(),
|
||||
workspace.as_os_str(),
|
||||
"-o".as_ref(),
|
||||
workspace_docs.as_os_str(),
|
||||
]);
|
||||
assert_success("doc workspace", &doc_output);
|
||||
|
||||
let index = fs::read_to_string(workspace_docs.join("index.md")).expect("read workspace docs");
|
||||
assert!(index.contains("## Workspace"));
|
||||
assert!(index.contains("### Members"));
|
||||
assert!(index.contains("- `packages/app`"));
|
||||
assert!(index.contains("- `packages/libutil`"));
|
||||
assert!(index.contains("### Packages"));
|
||||
assert!(index.contains("- `app 0.1.0 (entry main)`"));
|
||||
assert!(index.contains("- `libutil 0.1.0 (entry main)`"));
|
||||
assert!(index.contains("### Package Dependencies"));
|
||||
assert!(index.contains("- `app -> libutil (local-path, packages/libutil)`"));
|
||||
}
|
||||
|
||||
#[cfg(unix)]
|
||||
#[test]
|
||||
fn project_tooling_rejects_symlinked_module_escape() {
|
||||
|
||||
@ -134,7 +134,8 @@ Work:
|
||||
In progress after `1.0.0-beta.4`: local workspaces can declare
|
||||
`default_package` to select the build/run entry package when multiple packages
|
||||
have entry modules. Duplicate normalized member paths and missing default
|
||||
package references are dedicated diagnostics. Lockfiles, remote registries,
|
||||
package references are dedicated diagnostics. Workspace documentation now
|
||||
includes package and local dependency summaries. Lockfiles, remote registries,
|
||||
semver solving, publishing, optional/dev/target dependencies, and stable
|
||||
package ABI/layout remain out of scope.
|
||||
|
||||
|
||||
@ -18,6 +18,8 @@ integration/readiness release, not the first real beta.
|
||||
- Workspace loading now diagnoses a missing `default_package` reference with
|
||||
`WorkspaceDefaultPackageMissing`, and build/run diagnose a selected package
|
||||
that lacks its entry module with `WorkspaceDefaultPackageEntryMissing`.
|
||||
- `glagol doc <workspace> -o <dir>` now includes a deterministic workspace
|
||||
summary with members, packages, and local package dependency edges.
|
||||
|
||||
## 1.0.0-beta.4
|
||||
|
||||
|
||||
@ -33,8 +33,8 @@ diagnostics.
|
||||
Current unreleased work is the package/workspace discipline slice. It adds
|
||||
`[workspace] default_package = "name"` for deterministic build/run entry
|
||||
selection in multi-entry workspaces and tightens workspace-member/default
|
||||
package diagnostics while keeping registries, lockfiles, semver solving, and
|
||||
publishing deferred.
|
||||
package diagnostics. Workspace docs now include package/dependency summaries.
|
||||
Registries, lockfiles, semver solving, and publishing remain deferred.
|
||||
|
||||
The final experimental precursor scope is `exp-125`. Its unsigned direct-value
|
||||
flow, parse/format runtime lanes, and matching staged stdlib helper breadth
|
||||
|
||||
@ -26,6 +26,8 @@ diagnostics bundle.
|
||||
`WorkspaceDefaultPackageMissing` diagnostic. A selected default package that
|
||||
lacks its configured entry module is diagnosed as
|
||||
`WorkspaceDefaultPackageEntryMissing` during build/run.
|
||||
- Workspace documentation generated by `glagol doc` now includes a
|
||||
deterministic summary of members, packages, and local dependency edges.
|
||||
|
||||
## 1.0.0-beta.4
|
||||
|
||||
|
||||
@ -20,8 +20,8 @@ standard-library stabilization release, entry-specific project/workspace
|
||||
Current unreleased work is the package/workspace discipline slice. It adds
|
||||
`[workspace] default_package = "name"` for deterministic build/run entry
|
||||
selection in multi-entry workspaces and tightens duplicate-member/default
|
||||
package diagnostics while keeping registries, lockfiles, semver solving, and
|
||||
publishing deferred.
|
||||
package diagnostics. Workspace docs now include package/dependency summaries.
|
||||
Registries, lockfiles, semver solving, and publishing remain deferred.
|
||||
|
||||
The final experimental precursor scope is `exp-125`, defined in
|
||||
`.llm/EXP_125_UNSIGNED_U32_U64_NUMERIC_AND_STDLIB_BREADTH_ALPHA.md`. Its
|
||||
|
||||
@ -1032,6 +1032,11 @@ Workspace member paths are normalized under the workspace root before package
|
||||
loading. Duplicate normalized member paths are invalid, even if they were
|
||||
spelled differently in the manifest.
|
||||
|
||||
`glagol doc <workspace> -o <dir>` documents the workspace graph in addition to
|
||||
module structure. The generated `index.md` includes deterministic lists of
|
||||
workspace members, packages, and local package dependency edges before the
|
||||
module sections.
|
||||
|
||||
This slice does not add remote registries, lockfiles, semantic-version
|
||||
solving, package publishing, archive formats, optional/dev/target
|
||||
dependencies, feature flags, package build scripts, or stable package
|
||||
|
||||
Loading…
Reference in New Issue
Block a user