Skip to content

Commit bcbd736

Browse files
committed
build: add _tools/lint/manifest-json-deps
Add a lint tool that validates manifest.json dependencies by cross-referencing C source file `#include` directives against declared dependencies. The tool maps include paths to package names (handling underscore-to-hyphen conversion and sub-header resolution), scans addon.c for non-WASM build configurations, and reports any missing dependencies. --- type: pre_commit_static_analysis_report description: Results of running static analysis checks when committing changes. report: - task: lint_filenames status: passed - task: lint_editorconfig status: passed - task: lint_markdown status: na - task: lint_package_json status: na - task: lint_repl_help status: na - task: lint_javascript_src status: na - task: lint_javascript_cli status: na - task: lint_javascript_examples status: na - task: lint_javascript_tests status: na - task: lint_javascript_benchmarks status: na - task: lint_python status: na - task: lint_r status: na - task: lint_c_src status: na - task: lint_c_examples status: na - task: lint_c_benchmarks status: na - task: lint_c_tests_fixtures status: na - task: lint_shell status: na - task: lint_typescript_declarations status: passed - task: lint_typescript_tests status: na - task: lint_license_headers status: passed ---
1 parent 8427c6a commit bcbd736

File tree

29 files changed

+2224
-0
lines changed

29 files changed

+2224
-0
lines changed
Lines changed: 244 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,244 @@
1+
<!--
2+
3+
@license Apache-2.0
4+
5+
Copyright (c) 2026 The Stdlib Authors.
6+
7+
Licensed under the Apache License, Version 2.0 (the "License");
8+
you may not use this file except in compliance with the License.
9+
You may obtain a copy of the License at
10+
11+
http://www.apache.org/licenses/LICENSE-2.0
12+
13+
Unless required by applicable law or agreed to in writing, software
14+
distributed under the License is distributed on an "AS IS" BASIS,
15+
WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
16+
See the License for the specific language governing permissions and
17+
limitations under the License.
18+
19+
-->
20+
21+
# Lint
22+
23+
> Lint manifest.json dependencies to ensure all required packages are listed.
24+
25+
<section class="usage">
26+
27+
## Usage
28+
29+
```javascript
30+
var lint = require( '@stdlib/_tools/lint/manifest-json-deps' );
31+
```
32+
33+
#### lint( \[options,] clbk )
34+
35+
Asynchronously lints manifest.json dependencies by analyzing C source file `#include` directives and verifying that the corresponding `@stdlib` packages are listed in each configuration's `dependencies` array.
36+
37+
```javascript
38+
lint( onLint );
39+
40+
function onLint( error, errs ) {
41+
if ( error ) {
42+
throw error;
43+
}
44+
if ( errs && errs.length ) {
45+
console.error( JSON.stringify( errs ) );
46+
} else {
47+
console.log( 'No detected errors.' );
48+
}
49+
}
50+
```
51+
52+
The function accepts the following `options`:
53+
54+
- **dir**: root directory from which to search for manifest.json files. May be either an absolute file path or a path relative to the current working directory. Default: current working directory.
55+
- **pattern**: glob pattern for finding manifest.json files. Default: `**/@stdlib/**/manifest.json`.
56+
- **ignore**: glob pattern(s) to exclude.
57+
58+
Each lint error is represented by an `object` having the following fields:
59+
60+
- **file**: manifest.json file path.
61+
- **errors**: array of error objects, each with `message`, `conf`, and `dependency` fields.
62+
63+
To lint starting from a descendant directory, set the `dir` option.
64+
65+
```javascript
66+
var opts = {
67+
'dir': '/foo/bar/baz'
68+
};
69+
70+
lint( opts, onLint );
71+
72+
function onLint( error, errs ) {
73+
if ( error ) {
74+
throw error;
75+
}
76+
if ( errs && errs.length ) {
77+
console.error( JSON.stringify( errs ) );
78+
} else {
79+
console.log( 'No detected errors.' );
80+
}
81+
}
82+
```
83+
84+
#### lint.sync( \[options] )
85+
86+
Synchronously lints manifest.json dependencies.
87+
88+
```javascript
89+
var errs = lint.sync();
90+
if ( errs && errs.length ) {
91+
console.error( JSON.stringify( errs ) );
92+
} else {
93+
console.log( 'No detected errors.' );
94+
}
95+
```
96+
97+
The function accepts the same `options` as `lint()` above.
98+
99+
</section>
100+
101+
<!-- /.usage -->
102+
103+
<section class="notes">
104+
105+
## Notes
106+
107+
- The linter analyzes C source files (`.c`) for `#include "stdlib/..."` directives and maps each include path to an `@stdlib` package name.
108+
- The mapping converts underscores in header paths to hyphens in package names (e.g., `stdlib/napi/argv_double.h` maps to `@stdlib/napi/argv-double`).
109+
- For `build` configurations (non-WASM), the linter also scans `src/addon.c` if present, as it is compiled during builds but not listed in the manifest's `src` array.
110+
- Self-references (a package including its own headers) are automatically excluded.
111+
- Fortran files (`.f`) are skipped as they do not contain `#include` directives.
112+
113+
</section>
114+
115+
<!-- /.notes -->
116+
117+
<section class="examples">
118+
119+
## Examples
120+
121+
<!-- eslint no-undef: "error" -->
122+
123+
```javascript
124+
var lint = require( '@stdlib/_tools/lint/manifest-json-deps' );
125+
126+
var opts = {
127+
'dir': './',
128+
'pattern': '**/@stdlib/math/**/manifest.json'
129+
};
130+
131+
lint( opts, onLint );
132+
133+
function onLint( error, errors ) {
134+
if ( error ) {
135+
throw error;
136+
}
137+
if ( errors && errors.length ) {
138+
console.error( JSON.stringify( errors ) );
139+
} else {
140+
console.log( 'No detected errors.' );
141+
}
142+
}
143+
```
144+
145+
</section>
146+
147+
<!-- /.examples -->
148+
149+
* * *
150+
151+
<section class="cli">
152+
153+
## CLI
154+
155+
<section class="usage">
156+
157+
### Usage
158+
159+
```text
160+
Usage: lint-manifest-json-deps [options] [<dir>]
161+
162+
Options:
163+
164+
-h, --help Print this message.
165+
-V, --version Print the package version.
166+
--pattern pattern Inclusion glob pattern.
167+
--ignore pattern Exclusion glob pattern.
168+
--format fmt Output format: 'pretty' or 'ndjson'. Default: 'pretty'.
169+
--split sep Separator used to split stdin data. Default: /\\r?\\n/.
170+
```
171+
172+
</section>
173+
174+
<!-- /.usage -->
175+
176+
<section class="notes">
177+
178+
### Notes
179+
180+
- If part of a [standard stream][standard-stream] pipeline, results are written to `stdout` as newline-delimited JSON ([NDJSON][ndjson]). Otherwise, results are pretty printed by default.
181+
182+
- If not provided a `dir` argument, the current working directory is the search directory.
183+
184+
- To provide multiple exclusion glob patterns, set multiple `--ignore` option arguments.
185+
186+
```bash
187+
$ lint-manifest-json-deps --ignore=node_modules/** --ignore=build/** --ignore=reports/**
188+
```
189+
190+
</section>
191+
192+
<!-- /.notes -->
193+
194+
<section class="examples">
195+
196+
### Examples
197+
198+
```bash
199+
$ lint-manifest-json-deps
200+
201+
/path/to/lib/node_modules/@stdlib/math/base/special/abs/manifest.json
202+
203+
message: Missing dependency "@stdlib/napi/argv-double" in conf [task:build, wasm:false].
204+
conf: task:build, wasm:false
205+
dependency: @stdlib/napi/argv-double
206+
207+
1 errors
208+
```
209+
210+
To output results as newline-delimited JSON ([NDJSON][ndjson]),
211+
212+
```bash
213+
$ lint-manifest-json-deps --format ndjson
214+
{"file":"/path/to/manifest.json","message":"Missing dependency...","conf":"task:build","dependency":"@stdlib/napi/argv-double"}
215+
...
216+
```
217+
218+
</section>
219+
220+
<!-- /.examples -->
221+
222+
</section>
223+
224+
<!-- /.cli -->
225+
226+
<!-- Section for related `stdlib` packages. Do not manually edit this section, as it is automatically populated. -->
227+
228+
<section class="related">
229+
230+
</section>
231+
232+
<!-- /.related -->
233+
234+
<!-- Section for all links. Make sure to keep an empty line after the `section` element and another before the `/section` close. -->
235+
236+
<section class="links">
237+
238+
[ndjson]: http://ndjson.org/
239+
240+
[standard-stream]: https://en.wikipedia.org/wiki/Pipeline_%28Unix%29
241+
242+
</section>
243+
244+
<!-- /.links -->

0 commit comments

Comments
 (0)