[RFC]: Extend stdlib's doctesting approach to C examples
I maintainer di solito rispondono entro 1 giorno
Nessuno ha ancora preso questa issue.
Valutazione
- Difficoltà
- 5/5
- Tempo stimato
- Più di una settimana
- Idoneità per principianti
- 28/100
- Tipo di issue
- Funzionalità
- Chiarezza
- Abbastanza chiara
- Stato di attività
- Tranquilla
- Stack tecnologico
- c, javascript, node.js
- Ambito
- build-system, testing-qa, tooling
Direzione di ricerca
Inizia leggendo i target doctest esistenti in tools/make/lib/doctest/c/doctest-c.mk e le issue correlate #G96 e #1378. Esamina i confini proposti per estrazione, strumentazione, compilazione, esecuzione e confronto, quindi risolvi prima dell’implementazione le questioni relative al percorso di inclusione, all’helper statico, alla denominazione e alle regole di skip; il lavoro è completato quando esiste un design concordato per la pipeline di doctesting in C.
Scritto dal modello di indicizzazione a partire dal testo della issue.
Descrizione
Description
This RFC proposes a suite of packages under @stdlib/_tools/doctest/c implementing an automated extract → instrument → compile → run → compare pipeline for testing C code examples embedded in src/*.c source files and README.md files.
Proposed Changes
Package layout
@stdlib/_tools/doctest/c/ ← orchestrator (bin/cli)
├── extract/
├── instrument/
├── compile/
├── run/
└── compare/
Make targets follow the existing doctest namespace in tools/make/lib/doctest/c/doctest-c.mk.
Sub-package API
@stdlib/_tools/doctest/c/extract
extract( filePath, mode ) → Array<block>
// filePath: string — absolute path to a .c source file or README.md
// mode: 'src' | 'markdown'
// returns an array of self-contained block objects, one per testable example
/* block = {
file: string,
blockIndex: number, ← 0-based, helps segregating example blocks from same file
includes: Array<{ text: string, line: number }>, ← #include lines hoisted for this block
staticHelpers: Array<{ text: string, line: number }>, ← array of hoisted internal static functions called by this block
fileScope: Array<{ text: string, line: number }>, ← pre-function declarations + function definitions for this block (to be hoisted outside main()) (ex, @stdlib/ndarray/base/function-object)
body: Array<{ text: string, line: number }>, ← procedural lines for main() for this block
annotations: Array<{ text: string, line: number }> ← extracted annotation values (e.g., "~1.571", "true") from // returns comments
}
*/
Parses @example Doxygen blocks (src mode) or ```c ``` fenced blocks (markdown mode). Each block is independent.
Note: Contiguous lines are grouped into a single text block. The line property indicates the starting line number of that contiguous block
@stdlib/_tools/doctest/c/instrument
instrument( block ) → { tmpFile, annotations }
// block: block object from extract()
// tmpFile: absolute path to the generated .c file written to os.tmpdir()
// annotations: Array<{ annotation, type, varName, file, line }>
Wraps the block into a compilable .c file: injects necessary stdlib and standard library headers, hoists static helpers and file-scope declarations, wraps procedural code in main(), and emits a type-aware printf per // returns annotation. Injects #line N "original/file.c" directives so all compiler errors reference the original file and line, not the generated tmp file.
For each annotation, type inference runs via a inferType helper that backward-scans the body lines accumulated up to that annotation to find the preceding variable declaration.
@stdlib/_tools/doctest/c/compile
compile( tmpFile ) → { ok, binary, stderr }
// tmpFile: path from instrument()
// binary: path to the compiled executable (in os.tmpdir())
// stderr: raw compiler output (already line-mapped to original file via #line)
Resolves include paths via manifest.json using @stdlib/utils/library-manifest. Handles supplemental headers referenced inside a snippet but absent from the package's core manifest dependencies.
@stdlib/_tools/doctest/c/run
run( binary, opts ) → { ok, stdout, stderr, timedOut }
// binary: path from compile()
// opts: { timeout: number } — default 15000 ms
Executes the compiled binary via spawnSync with a configurable timeout.
@stdlib/_tools/doctest/c/compare
compare( stdout, annotations ) → Array<{ pass, got, expected, file, line }>
// stdout: raw stdout string from run()
// annotations: annotation metadata array from instrument()
Normalizes tokens (inf/-inf → ±Infinity, nan → NaN, trailing f stripped) before comparison. Uses Object.is for -0 detection and delegates ~-prefixed approximate values to @stdlib/_tools/doctest/compare-values and direct comparison for ints and bools.
Block Skip Rules
In src/*.c files, a trailing comment on the function definition opts the @example blocks of that function out:
// Skips @example blocks of that function:
static double foo( double x ) { // stdlib-c-doctest disable
...
}
// Skip all remaining @example blocks in the file:
// stdlib-c-doctest disable-file
In README.md files, the existing <!-- run-disable --> comment before a fenced block opts it out. napi packages (paths containing /napi/) are excluded automatically by the orchestrator.
CLI
Invoked by make targets and pre-commit hooks, one file at a time:
node lib/node_modules/@stdlib/_tools/doctest/c/bin/cli.js \
--mode=src \
--file=lib/node_modules/@stdlib/math/base/special/sin/src/main.c \
[--verbose] [--timeout=<ms>]
| Flag | Description |
|---|---|
--mode |
src or markdown |
--file |
File to process |
--verbose |
Print compiler output and instrumentation trace |
--timeout |
Per-binary execution timeout in ms (default: 15000) |
Output Format
Compiler errors are surfaced directly from the compiler's own output, which are already mapped to the original file via #line directives. Annotation mismatches and pipeline errors (compare stage) are formatted by the orchestrator as file:line:col: error: message [rule].
Stretch Goals
- Mutated scalar annotation:
// out => 0.5 - Flat array annotation:
// x => <double>[ 1.0, 2.0, 3.0 ] - Complex number annotation:
// returns <complex128>[re, im]
Related Issues
Related issues #G96 , #1378.
Questions
-
Include path resolution: Should supplemental dep resolution remain in the doctest tool, or should a
docstask config be added tomanifest.jsonsolibrary-manifesthandles it fully? -
Static helper handling: Should internal
statichelpers be hoisted exactly into the tmp file, or promoted to namespaced internal symbols (e.g.,stdlib_internal_*) via a restricted header? -
Tool structuring/naming: Any feedback on the sub-package naming or placement under
@stdlib/_tools/doctest/c/? -
Skip rule scope for
@exampleblocks: When// stdlib-c-doctest disableis placed on a function definition, it skips all@exampleblocks for that function. However, since a function can have multiple example blocks, should there be a way to skip specific blocks (e.g., using an index-based approach)?
Other
No.
Checklist
- I have read and understood the Code of Conduct.
- Searched for existing issues and pull requests.
- The issue name begins with
RFC:.
- Lingua principale
- JavaScript
- Stelle
- 6k
- Fork
- 1.3k
- Merge medio
- 1g 3h
- PR unite (30g)
- 567
Preparare l'ambiente
Avvia il container di sviluppo del progetto nel browser, con il tuo account GitHub.
- Nessun Dockerfile né file Docker Compose
- Ha un modello di pull request
- Leggi la guida per i contributori
Come iniziare
- Leggi tutta la issue e poi la guida ai contributi del progetto.
- Commenta sulla issue per dire che te ne occupi tu — evita che due persone facciano lo stesso lavoro.
- Fai un fork del repository e lavora su un branch.
- Apri una pull request che faccia riferimento al numero della issue.
Altre issue di stdlib-js/stdlib
-
Difficoltà 2/5 1-3 ore Idoneità per principianti 75/100
I maintainer di solito rispondono entro 1 giorno
-
[Bug]: rayleigh/mgf returns wrong values due to misplaced parenthesisForse già presa @anandkaranubc l’ha presa 1 giorno fa. ApertaBug
Difficoltà 2/5 1-3 ore Idoneità per principianti 75/100
stdlib-js/stdlib#15456 · 6 commenti · 1 assegnatario ·
I maintainer di solito rispondono entro 1 giorno
-
Difficoltà 2/5 1-3 ore Idoneità per principianti 82/100
stdlib-js/stdlib#15193 · 2 commenti ·
I maintainer di solito rispondono entro 1 giorno
-
Fix JavaScript lint errorsApertaGood First Issue
Difficoltà 2/5 1-3 ore Idoneità per principianti 76/100
stdlib-js/stdlib#14759 · 3 commenti ·
I maintainer di solito rispondono entro 1 giorno
-
Fix C lint errorsAperta
Difficoltà 1/5 Meno di un'ora Idoneità per principianti 85/100
I maintainer di solito rispondono entro 1 giorno
Tutte le issue di stdlib-js/stdlib
Issue simili
-
curriculum documentation quality
Difficoltà 2/5 1-3 ore Idoneità per principianti 78/100
githubnext/gh-aw-workshop#3897 ·
I maintainer di solito rispondono entro 2 giorni
-
agent/quality hive/hosted-available-lke648397-260827-5n31 quality testing
Difficoltà 2/5 1-3 ore Idoneità per principianti 91/100
I maintainer di solito rispondono entro 1 giorno
-
Add: RSV Honduras FeedApertacheck:failed feeds:add
Difficoltà 2/5 1-3 ore Idoneità per principianti 70/100
iptv-org/database#36179 · 1 commento ·
I maintainer di solito rispondono entro 1 giorno
-
bug
Difficoltà 2/5 1-3 ore Idoneità per principianti 88/100
I maintainer di solito rispondono entro 1 giorno
-
Difficoltà 2/5 1-3 ore Idoneità per principianti 84/100
I maintainer di solito rispondono entro 1 giorno