blockwatch-cli 0.14.2__tar.gz → 0.16.0__tar.gz
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- {blockwatch_cli-0.14.2 → blockwatch_cli-0.16.0}/.pre-commit-config.yaml +8 -0
- {blockwatch_cli-0.14.2 → blockwatch_cli-0.16.0}/AGENTS.md +9 -8
- {blockwatch_cli-0.14.2 → blockwatch_cli-0.16.0}/CHANGELOG.md +52 -0
- {blockwatch_cli-0.14.2 → blockwatch_cli-0.16.0}/CLAUDE.md +9 -8
- {blockwatch_cli-0.14.2 → blockwatch_cli-0.16.0}/Cargo.lock +1 -12
- {blockwatch_cli-0.14.2 → blockwatch_cli-0.16.0}/Cargo.toml +1 -2
- {blockwatch_cli-0.14.2 → blockwatch_cli-0.16.0}/PKG-INFO +1 -1
- {blockwatch_cli-0.14.2 → blockwatch_cli-0.16.0}/README.md +1 -1
- blockwatch_cli-0.16.0/clippy.toml +11 -0
- {blockwatch_cli-0.14.2 → blockwatch_cli-0.16.0}/docs/ci.md +2 -2
- {blockwatch_cli-0.14.2 → blockwatch_cli-0.16.0}/docs/cli.md +13 -13
- {blockwatch_cli-0.14.2 → blockwatch_cli-0.16.0}/docs/validators/check-ai.md +3 -0
- {blockwatch_cli-0.14.2 → blockwatch_cli-0.16.0}/docs/validators/check-lua.md +3 -0
- {blockwatch_cli-0.14.2 → blockwatch_cli-0.16.0}/docs/validators/keep-sorted.md +3 -0
- {blockwatch_cli-0.14.2 → blockwatch_cli-0.16.0}/docs/validators/line-count.md +3 -0
- {blockwatch_cli-0.14.2 → blockwatch_cli-0.16.0}/docs/validators/same-as.md +46 -26
- {blockwatch_cli-0.14.2 → blockwatch_cli-0.16.0}/setup.py +1 -1
- {blockwatch_cli-0.14.2 → blockwatch_cli-0.16.0}/src/blocks.rs +37 -3
- {blockwatch_cli-0.14.2 → blockwatch_cli-0.16.0}/src/config.rs +6 -2
- {blockwatch_cli-0.14.2 → blockwatch_cli-0.16.0}/src/fs.rs +5 -1
- {blockwatch_cli-0.14.2 → blockwatch_cli-0.16.0}/src/language_parsers/markdown.rs +306 -154
- {blockwatch_cli-0.14.2 → blockwatch_cli-0.16.0}/src/language_parsers/mdx.rs +4 -13
- {blockwatch_cli-0.14.2 → blockwatch_cli-0.16.0}/src/path_arguments.rs +15 -3
- {blockwatch_cli-0.14.2 → blockwatch_cli-0.16.0}/src/paths_glob.rs +66 -1
- {blockwatch_cli-0.14.2 → blockwatch_cli-0.16.0}/src/settings.rs +17 -1
- {blockwatch_cli-0.14.2 → blockwatch_cli-0.16.0}/src/skill.md +27 -23
- {blockwatch_cli-0.14.2 → blockwatch_cli-0.16.0}/src/validators/check_ai.rs +27 -1
- {blockwatch_cli-0.14.2 → blockwatch_cli-0.16.0}/src/validators/check_lua.rs +33 -0
- {blockwatch_cli-0.14.2 → blockwatch_cli-0.16.0}/src/validators/keep_sorted.rs +37 -1
- {blockwatch_cli-0.14.2 → blockwatch_cli-0.16.0}/src/validators/line_count.rs +30 -1
- {blockwatch_cli-0.14.2 → blockwatch_cli-0.16.0}/src/validators/mod.rs +49 -0
- {blockwatch_cli-0.14.2 → blockwatch_cli-0.16.0}/src/validators/same_as.rs +313 -59
- {blockwatch_cli-0.14.2 → blockwatch_cli-0.16.0}/tests/explain.rs +13 -5
- {blockwatch_cli-0.14.2 → blockwatch_cli-0.16.0}/tests/same_as.rs +35 -0
- blockwatch_cli-0.14.2/clippy.toml +0 -5
- {blockwatch_cli-0.14.2 → blockwatch_cli-0.16.0}/.agents/.claude-plugin/plugin.json +0 -0
- {blockwatch_cli-0.14.2 → blockwatch_cli-0.16.0}/.agents/skills/blockwatch/SKILL.md +0 -0
- {blockwatch_cli-0.14.2 → blockwatch_cli-0.16.0}/.claude-plugin/marketplace.json +0 -0
- {blockwatch_cli-0.14.2 → blockwatch_cli-0.16.0}/.github/dependabot.yml +0 -0
- {blockwatch_cli-0.14.2 → blockwatch_cli-0.16.0}/.github/workflows/blockwatch.yml +0 -0
- {blockwatch_cli-0.14.2 → blockwatch_cli-0.16.0}/.github/workflows/codeql.yml +0 -0
- {blockwatch_cli-0.14.2 → blockwatch_cli-0.16.0}/.github/workflows/markdownlint.yml +0 -0
- {blockwatch_cli-0.14.2 → blockwatch_cli-0.16.0}/.github/workflows/pypi.yml +0 -0
- {blockwatch_cli-0.14.2 → blockwatch_cli-0.16.0}/.github/workflows/release.yml +0 -0
- {blockwatch_cli-0.14.2 → blockwatch_cli-0.16.0}/.github/workflows/rust.yml +0 -0
- {blockwatch_cli-0.14.2 → blockwatch_cli-0.16.0}/.github/workflows/trusted-checks.yml +0 -0
- {blockwatch_cli-0.14.2 → blockwatch_cli-0.16.0}/.gitignore +0 -0
- {blockwatch_cli-0.14.2 → blockwatch_cli-0.16.0}/.markdownlint-cli2.yaml +0 -0
- {blockwatch_cli-0.14.2 → blockwatch_cli-0.16.0}/.pre-commit-hooks.yaml +0 -0
- {blockwatch_cli-0.14.2 → blockwatch_cli-0.16.0}/LICENSE +0 -0
- {blockwatch_cli-0.14.2 → blockwatch_cli-0.16.0}/SECURITY.md +0 -0
- {blockwatch_cli-0.14.2 → blockwatch_cli-0.16.0}/blockwatch.toml +0 -0
- {blockwatch_cli-0.14.2 → blockwatch_cli-0.16.0}/codecov.yml +0 -0
- {blockwatch_cli-0.14.2 → blockwatch_cli-0.16.0}/demo.gif +0 -0
- {blockwatch_cli-0.14.2 → blockwatch_cli-0.16.0}/dist-workspace.toml +0 -0
- {blockwatch_cli-0.14.2 → blockwatch_cli-0.16.0}/docs/agents.md +0 -0
- {blockwatch_cli-0.14.2 → blockwatch_cli-0.16.0}/docs/symbols.md +0 -0
- {blockwatch_cli-0.14.2 → blockwatch_cli-0.16.0}/docs/validators/README.md +0 -0
- {blockwatch_cli-0.14.2 → blockwatch_cli-0.16.0}/docs/validators/affects.md +0 -0
- {blockwatch_cli-0.14.2 → blockwatch_cli-0.16.0}/docs/validators/keep-unique.md +0 -0
- {blockwatch_cli-0.14.2 → blockwatch_cli-0.16.0}/docs/validators/line-pattern.md +0 -0
- {blockwatch_cli-0.14.2 → blockwatch_cli-0.16.0}/pypi/pyproject.toml +0 -0
- {blockwatch_cli-0.14.2 → blockwatch_cli-0.16.0}/pyproject.toml +0 -0
- {blockwatch_cli-0.14.2 → blockwatch_cli-0.16.0}/release.toml +0 -0
- {blockwatch_cli-0.14.2 → blockwatch_cli-0.16.0}/scripts/check_language_count.lua +0 -0
- {blockwatch_cli-0.14.2 → blockwatch_cli-0.16.0}/scripts/check_latest_gpt_nano_model.lua +0 -0
- {blockwatch_cli-0.14.2 → blockwatch_cli-0.16.0}/src/block_parser.rs +0 -0
- {blockwatch_cli-0.14.2 → blockwatch_cli-0.16.0}/src/cli.rs +0 -0
- {blockwatch_cli-0.14.2 → blockwatch_cli-0.16.0}/src/diff_parser.rs +0 -0
- {blockwatch_cli-0.14.2 → blockwatch_cli-0.16.0}/src/explain.rs +0 -0
- {blockwatch_cli-0.14.2 → blockwatch_cli-0.16.0}/src/flags.rs +0 -0
- {blockwatch_cli-0.14.2 → blockwatch_cli-0.16.0}/src/language_parsers/bash.rs +0 -0
- {blockwatch_cli-0.14.2 → blockwatch_cli-0.16.0}/src/language_parsers/c.rs +0 -0
- {blockwatch_cli-0.14.2 → blockwatch_cli-0.16.0}/src/language_parsers/c_sharp.rs +0 -0
- {blockwatch_cli-0.14.2 → blockwatch_cli-0.16.0}/src/language_parsers/cmake.rs +0 -0
- {blockwatch_cli-0.14.2 → blockwatch_cli-0.16.0}/src/language_parsers/cpp.rs +0 -0
- {blockwatch_cli-0.14.2 → blockwatch_cli-0.16.0}/src/language_parsers/css.rs +0 -0
- {blockwatch_cli-0.14.2 → blockwatch_cli-0.16.0}/src/language_parsers/dart.rs +0 -0
- {blockwatch_cli-0.14.2 → blockwatch_cli-0.16.0}/src/language_parsers/dockerfile.rs +0 -0
- {blockwatch_cli-0.14.2 → blockwatch_cli-0.16.0}/src/language_parsers/elixir.rs +0 -0
- {blockwatch_cli-0.14.2 → blockwatch_cli-0.16.0}/src/language_parsers/go.rs +0 -0
- {blockwatch_cli-0.14.2 → blockwatch_cli-0.16.0}/src/language_parsers/graphql.rs +0 -0
- {blockwatch_cli-0.14.2 → blockwatch_cli-0.16.0}/src/language_parsers/groovy.rs +0 -0
- {blockwatch_cli-0.14.2 → blockwatch_cli-0.16.0}/src/language_parsers/hcl.rs +0 -0
- {blockwatch_cli-0.14.2 → blockwatch_cli-0.16.0}/src/language_parsers/html.rs +0 -0
- {blockwatch_cli-0.14.2 → blockwatch_cli-0.16.0}/src/language_parsers/java.rs +0 -0
- {blockwatch_cli-0.14.2 → blockwatch_cli-0.16.0}/src/language_parsers/javascript.rs +0 -0
- {blockwatch_cli-0.14.2 → blockwatch_cli-0.16.0}/src/language_parsers/json.rs +0 -0
- {blockwatch_cli-0.14.2 → blockwatch_cli-0.16.0}/src/language_parsers/json.scm +0 -0
- {blockwatch_cli-0.14.2 → blockwatch_cli-0.16.0}/src/language_parsers/kotlin.rs +0 -0
- {blockwatch_cli-0.14.2 → blockwatch_cli-0.16.0}/src/language_parsers/lean.rs +0 -0
- {blockwatch_cli-0.14.2 → blockwatch_cli-0.16.0}/src/language_parsers/lua.rs +0 -0
- {blockwatch_cli-0.14.2 → blockwatch_cli-0.16.0}/src/language_parsers/makefile.rs +0 -0
- {blockwatch_cli-0.14.2 → blockwatch_cli-0.16.0}/src/language_parsers/mod.rs +0 -0
- {blockwatch_cli-0.14.2 → blockwatch_cli-0.16.0}/src/language_parsers/nix.rs +0 -0
- {blockwatch_cli-0.14.2 → blockwatch_cli-0.16.0}/src/language_parsers/ocaml.rs +0 -0
- {blockwatch_cli-0.14.2 → blockwatch_cli-0.16.0}/src/language_parsers/php.rs +0 -0
- {blockwatch_cli-0.14.2 → blockwatch_cli-0.16.0}/src/language_parsers/proto.rs +0 -0
- {blockwatch_cli-0.14.2 → blockwatch_cli-0.16.0}/src/language_parsers/python.rs +0 -0
- {blockwatch_cli-0.14.2 → blockwatch_cli-0.16.0}/src/language_parsers/ruby.rs +0 -0
- {blockwatch_cli-0.14.2 → blockwatch_cli-0.16.0}/src/language_parsers/rust.rs +0 -0
- {blockwatch_cli-0.14.2 → blockwatch_cli-0.16.0}/src/language_parsers/scala.rs +0 -0
- {blockwatch_cli-0.14.2 → blockwatch_cli-0.16.0}/src/language_parsers/sql.rs +0 -0
- {blockwatch_cli-0.14.2 → blockwatch_cli-0.16.0}/src/language_parsers/starlark.rs +0 -0
- {blockwatch_cli-0.14.2 → blockwatch_cli-0.16.0}/src/language_parsers/swift.rs +0 -0
- {blockwatch_cli-0.14.2 → blockwatch_cli-0.16.0}/src/language_parsers/toml.rs +0 -0
- {blockwatch_cli-0.14.2 → blockwatch_cli-0.16.0}/src/language_parsers/tsx.rs +0 -0
- {blockwatch_cli-0.14.2 → blockwatch_cli-0.16.0}/src/language_parsers/typescript.rs +0 -0
- {blockwatch_cli-0.14.2 → blockwatch_cli-0.16.0}/src/language_parsers/xml.rs +0 -0
- {blockwatch_cli-0.14.2 → blockwatch_cli-0.16.0}/src/language_parsers/yaml.rs +0 -0
- {blockwatch_cli-0.14.2 → blockwatch_cli-0.16.0}/src/lib.rs +0 -0
- {blockwatch_cli-0.14.2 → blockwatch_cli-0.16.0}/src/main.rs +0 -0
- {blockwatch_cli-0.14.2 → blockwatch_cli-0.16.0}/src/repo_path.rs +0 -0
- {blockwatch_cli-0.14.2 → blockwatch_cli-0.16.0}/src/report.rs +0 -0
- {blockwatch_cli-0.14.2 → blockwatch_cli-0.16.0}/src/sarif.rs +0 -0
- {blockwatch_cli-0.14.2 → blockwatch_cli-0.16.0}/src/scan.rs +0 -0
- {blockwatch_cli-0.14.2 → blockwatch_cli-0.16.0}/src/symbol_path.rs +0 -0
- {blockwatch_cli-0.14.2 → blockwatch_cli-0.16.0}/src/symbols.rs +0 -0
- {blockwatch_cli-0.14.2 → blockwatch_cli-0.16.0}/src/tag_parser.rs +0 -0
- {blockwatch_cli-0.14.2 → blockwatch_cli-0.16.0}/src/target_reference.rs +0 -0
- {blockwatch_cli-0.14.2 → blockwatch_cli-0.16.0}/src/validators/affects.rs +0 -0
- {blockwatch_cli-0.14.2 → blockwatch_cli-0.16.0}/src/validators/keep_unique.rs +0 -0
- {blockwatch_cli-0.14.2 → blockwatch_cli-0.16.0}/src/validators/line_pattern.rs +0 -0
- {blockwatch_cli-0.14.2 → blockwatch_cli-0.16.0}/src/violation_address.rs +0 -0
- {blockwatch_cli-0.14.2 → blockwatch_cli-0.16.0}/src/virtual_blocks.rs +0 -0
- {blockwatch_cli-0.14.2 → blockwatch_cli-0.16.0}/tests/affects.rs +0 -0
- {blockwatch_cli-0.14.2 → blockwatch_cli-0.16.0}/tests/check_ai.rs +0 -0
- {blockwatch_cli-0.14.2 → blockwatch_cli-0.16.0}/tests/check_lua.rs +0 -0
- {blockwatch_cli-0.14.2 → blockwatch_cli-0.16.0}/tests/common/empty.toml +0 -0
- {blockwatch_cli-0.14.2 → blockwatch_cli-0.16.0}/tests/common/mod.rs +0 -0
- {blockwatch_cli-0.14.2 → blockwatch_cli-0.16.0}/tests/config.rs +0 -0
- {blockwatch_cli-0.14.2 → blockwatch_cli-0.16.0}/tests/encoding.rs +0 -0
- {blockwatch_cli-0.14.2 → blockwatch_cli-0.16.0}/tests/general.rs +0 -0
- {blockwatch_cli-0.14.2 → blockwatch_cli-0.16.0}/tests/keep_sorted.rs +0 -0
- {blockwatch_cli-0.14.2 → blockwatch_cli-0.16.0}/tests/keep_unique.rs +0 -0
- {blockwatch_cli-0.14.2 → blockwatch_cli-0.16.0}/tests/line_count.rs +0 -0
- {blockwatch_cli-0.14.2 → blockwatch_cli-0.16.0}/tests/line_pattern.rs +0 -0
- {blockwatch_cli-0.14.2 → blockwatch_cli-0.16.0}/tests/list.rs +0 -0
- {blockwatch_cli-0.14.2 → blockwatch_cli-0.16.0}/tests/path_arguments.rs +0 -0
- {blockwatch_cli-0.14.2 → blockwatch_cli-0.16.0}/tests/repository_root.rs +0 -0
- {blockwatch_cli-0.14.2 → blockwatch_cli-0.16.0}/tests/sarif.rs +0 -0
- {blockwatch_cli-0.14.2 → blockwatch_cli-0.16.0}/tests/skill.rs +0 -0
- {blockwatch_cli-0.14.2 → blockwatch_cli-0.16.0}/tests/suppressions.rs +0 -0
- {blockwatch_cli-0.14.2 → blockwatch_cli-0.16.0}/tests/symbol_references.rs +0 -0
- {blockwatch_cli-0.14.2 → blockwatch_cli-0.16.0}/tests/testdata/affects/cross_file_source.rs +0 -0
- {blockwatch_cli-0.14.2 → blockwatch_cli-0.16.0}/tests/testdata/affects/cross_file_target.md +0 -0
- {blockwatch_cli-0.14.2 → blockwatch_cli-0.16.0}/tests/testdata/affects/custom_ext_source.javascript +0 -0
- {blockwatch_cli-0.14.2 → blockwatch_cli-0.16.0}/tests/testdata/affects/custom_ext_target.javascript +0 -0
- {blockwatch_cli-0.14.2 → blockwatch_cli-0.16.0}/tests/testdata/affects/dangling.md +0 -0
- {blockwatch_cli-0.14.2 → blockwatch_cli-0.16.0}/tests/testdata/affects/missing_symbol.rs +0 -0
- {blockwatch_cli-0.14.2 → blockwatch_cli-0.16.0}/tests/testdata/affects/more_added_than_deleted.py +0 -0
- {blockwatch_cli-0.14.2 → blockwatch_cli-0.16.0}/tests/testdata/affects/multiline_tag_source.rs +0 -0
- {blockwatch_cli-0.14.2 → blockwatch_cli-0.16.0}/tests/testdata/affects/multiline_tag_target.rs +0 -0
- {blockwatch_cli-0.14.2 → blockwatch_cli-0.16.0}/tests/testdata/affects/nested_mapping_source.rs +0 -0
- {blockwatch_cli-0.14.2 → blockwatch_cli-0.16.0}/tests/testdata/affects/nested_mapping_target.yaml +0 -0
- {blockwatch_cli-0.14.2 → blockwatch_cli-0.16.0}/tests/testdata/affects/sibling.md +0 -0
- {blockwatch_cli-0.14.2 → blockwatch_cli-0.16.0}/tests/testdata/affects/symbol_source.rs +0 -0
- {blockwatch_cli-0.14.2 → blockwatch_cli-0.16.0}/tests/testdata/affects/symbol_target.json +0 -0
- {blockwatch_cli-0.14.2 → blockwatch_cli-0.16.0}/tests/testdata/affects/table_source.rs +0 -0
- {blockwatch_cli-0.14.2 → blockwatch_cli-0.16.0}/tests/testdata/affects/table_target.toml +0 -0
- {blockwatch_cli-0.14.2 → blockwatch_cli-0.16.0}/tests/testdata/affects/tag_and_content_source.ts +0 -0
- {blockwatch_cli-0.14.2 → blockwatch_cli-0.16.0}/tests/testdata/affects/tag_and_content_target.ts +0 -0
- {blockwatch_cli-0.14.2 → blockwatch_cli-0.16.0}/tests/testdata/affects/whole_file_source.rs +0 -0
- {blockwatch_cli-0.14.2 → blockwatch_cli-0.16.0}/tests/testdata/affects/whole_file_target.json +0 -0
- {blockwatch_cli-0.14.2 → blockwatch_cli-0.16.0}/tests/testdata/check_ai/two_blocks.py +0 -0
- {blockwatch_cli-0.14.2 → blockwatch_cli-0.16.0}/tests/testdata/check_lua/affects.lua +0 -0
- {blockwatch_cli-0.14.2 → blockwatch_cli-0.16.0}/tests/testdata/check_lua/affects.py +0 -0
- {blockwatch_cli-0.14.2 → blockwatch_cli-0.16.0}/tests/testdata/check_lua/affects_drift.py +0 -0
- {blockwatch_cli-0.14.2 → blockwatch_cli-0.16.0}/tests/testdata/check_lua/blocking_io.lua +0 -0
- {blockwatch_cli-0.14.2 → blockwatch_cli-0.16.0}/tests/testdata/check_lua/blocking_io.py +0 -0
- {blockwatch_cli-0.14.2 → blockwatch_cli-0.16.0}/tests/testdata/check_lua/echo.lua +0 -0
- {blockwatch_cli-0.14.2 → blockwatch_cli-0.16.0}/tests/testdata/check_lua/fail.lua +0 -0
- {blockwatch_cli-0.14.2 → blockwatch_cli-0.16.0}/tests/testdata/check_lua/mode.py +0 -0
- {blockwatch_cli-0.14.2 → blockwatch_cli-0.16.0}/tests/testdata/check_lua/os.lua +0 -0
- {blockwatch_cli-0.14.2 → blockwatch_cli-0.16.0}/tests/testdata/check_lua/pathfmt/report_path.lua +0 -0
- {blockwatch_cli-0.14.2 → blockwatch_cli-0.16.0}/tests/testdata/check_lua/pathfmt/source.py +0 -0
- {blockwatch_cli-0.14.2 → blockwatch_cli-0.16.0}/tests/testdata/check_lua/pattern.py +0 -0
- {blockwatch_cli-0.14.2 → blockwatch_cli-0.16.0}/tests/testdata/check_lua/pattern_many_matches.py +0 -0
- {blockwatch_cli-0.14.2 → blockwatch_cli-0.16.0}/tests/testdata/check_lua/pattern_no_match.py +0 -0
- {blockwatch_cli-0.14.2 → blockwatch_cli-0.16.0}/tests/testdata/check_lua/success.lua +0 -0
- {blockwatch_cli-0.14.2 → blockwatch_cli-0.16.0}/tests/testdata/check_lua/success_and_failure.py +0 -0
- {blockwatch_cli-0.14.2 → blockwatch_cli-0.16.0}/tests/testdata/config/glob_target/config.toml +0 -0
- {blockwatch_cli-0.14.2 → blockwatch_cli-0.16.0}/tests/testdata/config/glob_target/package.json +0 -0
- {blockwatch_cli-0.14.2 → blockwatch_cli-0.16.0}/tests/testdata/config/glob_target/plugins/blue/package.json +0 -0
- {blockwatch_cli-0.14.2 → blockwatch_cli-0.16.0}/tests/testdata/config/glob_target/plugins/green/package.json +0 -0
- {blockwatch_cli-0.14.2 → blockwatch_cli-0.16.0}/tests/testdata/config/glob_target/plugins/red/package.json +0 -0
- {blockwatch_cli-0.14.2 → blockwatch_cli-0.16.0}/tests/testdata/explain/a.py +0 -0
- {blockwatch_cli-0.14.2 → blockwatch_cli-0.16.0}/tests/testdata/explain/check.lua +0 -0
- {blockwatch_cli-0.14.2 → blockwatch_cli-0.16.0}/tests/testdata/general/block_selection.py +0 -0
- {blockwatch_cli-0.14.2 → blockwatch_cli-0.16.0}/tests/testdata/general/custom_file_extension.javascript +0 -0
- {blockwatch_cli-0.14.2 → blockwatch_cli-0.16.0}/tests/testdata/general/custom_file_extension.python +0 -0
- {blockwatch_cli-0.14.2 → blockwatch_cli-0.16.0}/tests/testdata/general/disable_enable.py +0 -0
- {blockwatch_cli-0.14.2 → blockwatch_cli-0.16.0}/tests/testdata/general/paths/invalid.py +0 -0
- {blockwatch_cli-0.14.2 → blockwatch_cli-0.16.0}/tests/testdata/general/paths/subdir/nested_invalid.py +0 -0
- {blockwatch_cli-0.14.2 → blockwatch_cli-0.16.0}/tests/testdata/general/paths/valid.py +0 -0
- {blockwatch_cli-0.14.2 → blockwatch_cli-0.16.0}/tests/testdata/general/severity.py +0 -0
- {blockwatch_cli-0.14.2 → blockwatch_cli-0.16.0}/tests/testdata/hidden/.github/workflows/ci.yml +0 -0
- {blockwatch_cli-0.14.2 → blockwatch_cli-0.16.0}/tests/testdata/keep_sorted/orderings.py +0 -0
- {blockwatch_cli-0.14.2 → blockwatch_cli-0.16.0}/tests/testdata/keep_unique/basic_and_pattern.py +0 -0
- {blockwatch_cli-0.14.2 → blockwatch_cli-0.16.0}/tests/testdata/line_count/equality_and_greater_than.py +0 -0
- {blockwatch_cli-0.14.2 → blockwatch_cli-0.16.0}/tests/testdata/line_pattern/forbidden_text.py +0 -0
- {blockwatch_cli-0.14.2 → blockwatch_cli-0.16.0}/tests/testdata/line_pattern/hex_and_word_patterns.py +0 -0
- {blockwatch_cli-0.14.2 → blockwatch_cli-0.16.0}/tests/testdata/list/.hg/.gitkeep +0 -0
- {blockwatch_cli-0.14.2 → blockwatch_cli-0.16.0}/tests/testdata/list/a.py +0 -0
- {blockwatch_cli-0.14.2 → blockwatch_cli-0.16.0}/tests/testdata/list/b.py +0 -0
- {blockwatch_cli-0.14.2 → blockwatch_cli-0.16.0}/tests/testdata/positions/unicode_columns.py +0 -0
- {blockwatch_cli-0.14.2 → blockwatch_cli-0.16.0}/tests/testdata/same_as/custom_ext_source.javascript +0 -0
- {blockwatch_cli-0.14.2 → blockwatch_cli-0.16.0}/tests/testdata/same_as/custom_ext_target.javascript +0 -0
- {blockwatch_cli-0.14.2 → blockwatch_cli-0.16.0}/tests/testdata/same_as/package.json +0 -0
- {blockwatch_cli-0.14.2 → blockwatch_cli-0.16.0}/tests/testdata/same_as/paths/alpha/item.txt +0 -0
- {blockwatch_cli-0.14.2 → blockwatch_cli-0.16.0}/tests/testdata/same_as/paths/beta/item.txt +0 -0
- {blockwatch_cli-0.14.2 → blockwatch_cli-0.16.0}/tests/testdata/same_as/paths_and_block_source.md +0 -0
- {blockwatch_cli-0.14.2 → blockwatch_cli-0.16.0}/tests/testdata/same_as/paths_source.md +0 -0
- {blockwatch_cli-0.14.2 → blockwatch_cli-0.16.0}/tests/testdata/same_as/sibling.rs +0 -0
- {blockwatch_cli-0.14.2 → blockwatch_cli-0.16.0}/tests/testdata/same_as/source.rs +0 -0
- {blockwatch_cli-0.14.2 → blockwatch_cli-0.16.0}/tests/testdata/same_as/split_table_source.rs +0 -0
- {blockwatch_cli-0.14.2 → blockwatch_cli-0.16.0}/tests/testdata/same_as/split_table_target.toml +0 -0
- {blockwatch_cli-0.14.2 → blockwatch_cli-0.16.0}/tests/testdata/same_as/symbol_mismatch_source.rs +0 -0
- {blockwatch_cli-0.14.2 → blockwatch_cli-0.16.0}/tests/testdata/same_as/symbol_source.rs +0 -0
- {blockwatch_cli-0.14.2 → blockwatch_cli-0.16.0}/tests/testdata/same_as/target.md +0 -0
- {blockwatch_cli-0.14.2 → blockwatch_cli-0.16.0}/tests/testdata/same_as/whole_file_mismatch_source.rs +0 -0
- {blockwatch_cli-0.14.2 → blockwatch_cli-0.16.0}/tests/testdata/same_as/whole_file_source.rs +0 -0
- {blockwatch_cli-0.14.2 → blockwatch_cli-0.16.0}/tests/testdata/same_as/whole_file_target.json +0 -0
- {blockwatch_cli-0.14.2 → blockwatch_cli-0.16.0}/tests/testdata/sarif/advisory.py +0 -0
- {blockwatch_cli-0.14.2 → blockwatch_cli-0.16.0}/tests/testdata/sarif/clean.py +0 -0
- {blockwatch_cli-0.14.2 → blockwatch_cli-0.16.0}/tests/testdata/sarif/sorted.py +0 -0
- {blockwatch_cli-0.14.2 → blockwatch_cli-0.16.0}/tests/testdata/sarif/unnamed.py +0 -0
- {blockwatch_cli-0.14.2 → blockwatch_cli-0.16.0}/tests/testdata/suppressions/commit_msg.txt +0 -0
- {blockwatch_cli-0.14.2 → blockwatch_cli-0.16.0}/tests/testdata/suppressions/commit_msg_gone_a.txt +0 -0
- {blockwatch_cli-0.14.2 → blockwatch_cli-0.16.0}/tests/testdata/suppressions/commit_msg_gone_b.txt +0 -0
- {blockwatch_cli-0.14.2 → blockwatch_cli-0.16.0}/tests/testdata/suppressions/commit_msg_lowercase_trailer.txt +0 -0
- {blockwatch_cli-0.14.2 → blockwatch_cli-0.16.0}/tests/testdata/suppressions/commit_msg_malformed.txt +0 -0
- {blockwatch_cli-0.14.2 → blockwatch_cli-0.16.0}/tests/testdata/suppressions/commit_msg_with_noise.txt +0 -0
- {blockwatch_cli-0.14.2 → blockwatch_cli-0.16.0}/tests/testdata/suppressions/dangling.py +0 -0
- {blockwatch_cli-0.14.2 → blockwatch_cli-0.16.0}/tests/testdata/suppressions/sorted.py +0 -0
- {blockwatch_cli-0.14.2 → blockwatch_cli-0.16.0}/tests/testdata/suppressions/symbol.py +0 -0
- {blockwatch_cli-0.14.2 → blockwatch_cli-0.16.0}/tests/testdata/suppressions/symbol_target.json +0 -0
- {blockwatch_cli-0.14.2 → blockwatch_cli-0.16.0}/tests/testdata/suppressions/two_rules.py +0 -0
- {blockwatch_cli-0.14.2 → blockwatch_cli-0.16.0}/tests/testdata/suppressions/unnamed.py +0 -0
- {blockwatch_cli-0.14.2 → blockwatch_cli-0.16.0}/tests/testdata/symbol_references/escapes_source.rs +0 -0
- {blockwatch_cli-0.14.2 → blockwatch_cli-0.16.0}/tests/testdata/symbol_references/escapes_target.json +0 -0
- {blockwatch_cli-0.14.2 → blockwatch_cli-0.16.0}/tests/testdata/symbol_references/filter_source.rs +0 -0
- {blockwatch_cli-0.14.2 → blockwatch_cli-0.16.0}/tests/testdata/symbol_references/filter_target.yaml +0 -0
- {blockwatch_cli-0.14.2 → blockwatch_cli-0.16.0}/tests/testdata/symbol_references/json_source.rs +0 -0
- {blockwatch_cli-0.14.2 → blockwatch_cli-0.16.0}/tests/testdata/symbol_references/json_target.json +0 -0
- {blockwatch_cli-0.14.2 → blockwatch_cli-0.16.0}/tests/testdata/symbol_references/jsonc_source.rs +0 -0
- {blockwatch_cli-0.14.2 → blockwatch_cli-0.16.0}/tests/testdata/symbol_references/jsonc_target.jsonc +0 -0
- {blockwatch_cli-0.14.2 → blockwatch_cli-0.16.0}/tests/testdata/symbol_references/markdown_source.rs +0 -0
- {blockwatch_cli-0.14.2 → blockwatch_cli-0.16.0}/tests/testdata/symbol_references/markdown_target.markdown +0 -0
- {blockwatch_cli-0.14.2 → blockwatch_cli-0.16.0}/tests/testdata/symbol_references/md_source.rs +0 -0
- {blockwatch_cli-0.14.2 → blockwatch_cli-0.16.0}/tests/testdata/symbol_references/md_target.md +0 -0
- {blockwatch_cli-0.14.2 → blockwatch_cli-0.16.0}/tests/testdata/symbol_references/mdx_source.rs +0 -0
- {blockwatch_cli-0.14.2 → blockwatch_cli-0.16.0}/tests/testdata/symbol_references/mdx_target.mdx +0 -0
- {blockwatch_cli-0.14.2 → blockwatch_cli-0.16.0}/tests/testdata/symbol_references/mixed_list_source.rs +0 -0
- {blockwatch_cli-0.14.2 → blockwatch_cli-0.16.0}/tests/testdata/symbol_references/mixed_list_target.json +0 -0
- {blockwatch_cli-0.14.2 → blockwatch_cli-0.16.0}/tests/testdata/symbol_references/toml_source.rs +0 -0
- {blockwatch_cli-0.14.2 → blockwatch_cli-0.16.0}/tests/testdata/symbol_references/toml_target.toml +0 -0
- {blockwatch_cli-0.14.2 → blockwatch_cli-0.16.0}/tests/testdata/symbol_references/yaml_source.rs +0 -0
- {blockwatch_cli-0.14.2 → blockwatch_cli-0.16.0}/tests/testdata/symbol_references/yaml_target.yaml +0 -0
- {blockwatch_cli-0.14.2 → blockwatch_cli-0.16.0}/tests/testdata/symbol_references/yml_source.rs +0 -0
- {blockwatch_cli-0.14.2 → blockwatch_cli-0.16.0}/tests/testdata/symbol_references/yml_target.yml +0 -0
- {blockwatch_cli-0.14.2 → blockwatch_cli-0.16.0}/tests/testdata/verbosity/affects/pair.py +0 -0
- {blockwatch_cli-0.14.2 → blockwatch_cli-0.16.0}/tests/testdata/verbosity/clean/counted.py +0 -0
- {blockwatch_cli-0.14.2 → blockwatch_cli-0.16.0}/tests/testdata/verbosity/clean/noop.py +0 -0
- {blockwatch_cli-0.14.2 → blockwatch_cli-0.16.0}/tests/testdata/verbosity/clean/notes.txt +0 -0
- {blockwatch_cli-0.14.2 → blockwatch_cli-0.16.0}/tests/testdata/verbosity/clean/sorted.py +0 -0
- {blockwatch_cli-0.14.2 → blockwatch_cli-0.16.0}/tests/testdata/verbosity/diff/two_blocks.py +0 -0
- {blockwatch_cli-0.14.2 → blockwatch_cli-0.16.0}/tests/testdata/verbosity/failing/unsorted.py +0 -0
- {blockwatch_cli-0.14.2 → blockwatch_cli-0.16.0}/tests/testdata/verbosity/mixed/both_kinds.py +0 -0
- {blockwatch_cli-0.14.2 → blockwatch_cli-0.16.0}/tests/verbosity.rs +0 -0
|
@@ -43,6 +43,14 @@ repos:
|
|
|
43
43
|
types: [ rust ]
|
|
44
44
|
stages: [ pre-commit ]
|
|
45
45
|
pass_filenames: false
|
|
46
|
+
- id: cargo-test
|
|
47
|
+
name: cargo test
|
|
48
|
+
description: Run the unit, integration and doc tests.
|
|
49
|
+
entry: cargo test --quiet
|
|
50
|
+
language: system
|
|
51
|
+
types: [ rust ]
|
|
52
|
+
stages: [ pre-commit ]
|
|
53
|
+
pass_filenames: false
|
|
46
54
|
|
|
47
55
|
# Rules and the set of files linted live in `.markdownlint-cli2.yaml`, which the tool picks up
|
|
48
56
|
# from the repository root. The hook passes only the staged Markdown files, so a commit is judged
|
|
@@ -65,9 +65,9 @@ For example:
|
|
|
65
65
|
- *Always* handle the variants of an enum with an exhaustive `match`. A `let ... else`, or an `if` that handles one
|
|
66
66
|
variant and sends the rest to a single branch, quietly gives any new variant whatever that branch does. With a
|
|
67
67
|
`match`, the compiler makes you decide what to do with each new variant. One exception: a `match` on another
|
|
68
|
-
crate's enum can end with `_` when it only
|
|
69
|
-
|
|
70
|
-
Say why in a comment next to the `_`.
|
|
68
|
+
crate's enum can end with `_` when it only picks out one or a few variants, and no new variant could be one of
|
|
69
|
+
them. For example, every Markdown heading is `mdast::Node::Heading`, so the other node types can go to
|
|
70
|
+
`_ => None`. Say why in a comment next to the `_`.
|
|
71
71
|
- *Always* give an item the narrowest visibility that compiles: private, then `pub(super)`, then `pub(crate)`.
|
|
72
72
|
blockwatch is a program, not a library. Only `run` and `count_rust_blocks` in `lib.rs` are `pub`, for `main.rs` and
|
|
73
73
|
the fuzz target. The `unreachable_pub` lint makes `cargo clippy -- -D warnings` fail on any other `pub`.
|
|
@@ -173,8 +173,9 @@ The whole pipeline is in `src/cli.rs`. `src/main.rs` only calls `blockwatch::run
|
|
|
173
173
|
from the command line select, and that don't match the settings' ignore globs. `PathArguments::resolve` turns an
|
|
174
174
|
existing file or directory into a glob first, so `src` selects `src/**`. Pick each file's language by its
|
|
175
175
|
extension, using the settings' extension mappings too.
|
|
176
|
-
6. For each file, the matching `language_parsers::<lang>` (a tree-sitter grammar) finds the comments.
|
|
177
|
-
`block_parser` turn the comment text into `Block` values, with their attributes and their byte and
|
|
176
|
+
6. For each file, the matching `language_parsers::<lang>` (usually a tree-sitter grammar) finds the comments.
|
|
177
|
+
`tag_parser` and `block_parser` turn the comment text into `Block` values, with their attributes and their byte and
|
|
178
|
+
line ranges.
|
|
178
179
|
`VirtualBlock::resolve` finds each virtual block in the file, by its `Locator`, and adds it as a `Block` too. A file
|
|
179
180
|
without a grammar is read as plain text: it has no tags, only its virtual blocks. A target that does not resolve
|
|
180
181
|
stops the run. `--only-changed` also parses the file of a virtual block whose entry the diff
|
|
@@ -224,7 +225,8 @@ The main modules:
|
|
|
224
225
|
- `src/repo_path.rs` — `RepoPath`, the one way to write a path relative to the repository root. A diff header
|
|
225
226
|
(`b/src/main.rs`), a path found in the walk and a `file:name` attribute all become a `RepoPath`. So the same file is
|
|
226
227
|
always the same map key.
|
|
227
|
-
- `src/language_parsers/` — one
|
|
228
|
+
- `src/language_parsers/` — one parser for each language, most of them a tree-sitter grammar. Markdown and MDX use
|
|
229
|
+
the `markdown` crate, and Lean has its own scanner. Each language has a `parser()` that returns a
|
|
228
230
|
`LanguageParser`, which knows which syntax nodes are comments. `src/block_parser.rs` turns those comments into
|
|
229
231
|
blocks. `language_parsers()` in `language_parsers/mod.rs` returns `LanguageParsers`: the parser of each extension.
|
|
230
232
|
Its `parser_for` picks the parser of a file, using the settings' extension mappings too. **To add a language, add a
|
|
@@ -238,8 +240,7 @@ The main modules:
|
|
|
238
240
|
syntax tree is nested.
|
|
239
241
|
- YAML walks its syntax tree itself. An alias has a position in a sequence but can't be addressed, and a query can't
|
|
240
242
|
express that.
|
|
241
|
-
- Markdown finds its sections with the `markdown` crate
|
|
242
|
-
heading underlined with `---`.
|
|
243
|
+
- Markdown finds its sections with the `markdown` crate, the same parser that finds its comments.
|
|
243
244
|
|
|
244
245
|
Each language's tests list every symbol it finds. When you give a language symbols, also document its paths in
|
|
245
246
|
`docs/symbols.md` and in the "Symbols" section of the skill, `src/skill.md`. A test in `language_parsers/mod.rs` and the
|
|
@@ -12,6 +12,58 @@ Releases up to and including v0.3.11 predate this file. Their notes live on the
|
|
|
12
12
|
|
|
13
13
|
## [Unreleased] - ReleaseDate
|
|
14
14
|
|
|
15
|
+
## [0.16.0] - 2026-10-24
|
|
16
|
+
|
|
17
|
+
### Changed
|
|
18
|
+
|
|
19
|
+
- Without `same-as-pattern`, `same-as` compares each line that isn't blank as one value. Before, the whole block was
|
|
20
|
+
one value, so `same-as-mode` and `same-as-format` didn't work on a block of several lines. For example,
|
|
21
|
+
`same-as-mode="single"` passed with two lines, `subset` failed on a line that the target had, and `numeric` reported
|
|
22
|
+
that `1` and `2` together are not a number ([#179](https://github.com/mennanov/blockwatch/issues/179)).
|
|
23
|
+
- Without `same-as-mode`, a block without `same-as-pattern` compares in `sequence` mode. So it still fails when its
|
|
24
|
+
lines differ from the target's or come in another order. A block with a pattern still compares in `set` mode.
|
|
25
|
+
- A block without `same-as-pattern` now fails when its target's pattern finds a value more than once, or in another
|
|
26
|
+
order: `["1.2.3"] != ["1.2.3", "1.2.3"]`. Before, the default `set` mode ignored this. To keep the old result, add
|
|
27
|
+
`same-as-mode="set"`, or `same-as-mode="subset"` when the target may hold other values too.
|
|
28
|
+
- `same-as` now fails on two empty blocks, as it does on a pattern that matches nothing. The message for both is
|
|
29
|
+
`this block or its target has no values to compare`.
|
|
30
|
+
- `same-as-paths` no longer needs `same-as-pattern`. Without one, each line of the block must be a path, in sorted
|
|
31
|
+
order.
|
|
32
|
+
- An attribute that changes how a validator works now stops the run on a block without the validator's main
|
|
33
|
+
attribute. Before, it did nothing there. For example, `same-as-mode="sequence"` on a target let values in another
|
|
34
|
+
order pass. The attributes are:
|
|
35
|
+
- `same-as-mode` and `same-as-format`, without `same-as` or `same-as-paths`;
|
|
36
|
+
- `same-as-pattern`, without `same-as`, `same-as-paths` or `name`, because only a block with a name can be a target;
|
|
37
|
+
- `keep-sorted-pattern` and `keep-sorted-format`, without `keep-sorted`;
|
|
38
|
+
- `line-count-pattern`, without `line-count`;
|
|
39
|
+
- `check-ai-pattern`, without `check-ai`;
|
|
40
|
+
- `check-lua-pattern` and `check-lua-timeout`, without `check-lua`.
|
|
41
|
+
|
|
42
|
+
### Fixed
|
|
43
|
+
|
|
44
|
+
- An empty alternative in braces now matches, so `{,sub/}a.yml` matches both `a.yml` and `sub/a.yml`. Before, it
|
|
45
|
+
matched only `sub/a.yml`, with no error. This was true of every glob: a `[[block]]` target, `same-as-paths`, the
|
|
46
|
+
`ignore` setting and `--ignore`, and a path argument ([#177](https://github.com/mennanov/blockwatch/issues/177)).
|
|
47
|
+
|
|
48
|
+
## [0.15.0] - 2026-10-21
|
|
49
|
+
|
|
50
|
+
### Changed
|
|
51
|
+
|
|
52
|
+
- In Markdown, a `<!--` is a comment only where HTML is kept as it is: in an HTML block or in raw HTML in a line of
|
|
53
|
+
text. These were read as comments before and are not now:
|
|
54
|
+
- the alt text of an image: ``;
|
|
55
|
+
- the title of a link: `[Docs](docs.md "<!-- x -->")`;
|
|
56
|
+
- an escaped `<`: `\<!-- x -->`.
|
|
57
|
+
|
|
58
|
+
In a line of text, `<!-->` is now a whole comment, so a tag after it on that line is not read.
|
|
59
|
+
|
|
60
|
+
### Fixed
|
|
61
|
+
|
|
62
|
+
- In Markdown, blockwatch skipped every tag after a fenced code block that holds a line like `` ``` `` indented by 4
|
|
63
|
+
spaces or a tab, or `` echo x``` ``. Such a line closed the code block too early, so the rest of the file became
|
|
64
|
+
code. The run gave no error. Now such a line stays in the code block, as CommonMark says
|
|
65
|
+
([#176](https://github.com/mennanov/blockwatch/issues/176)).
|
|
66
|
+
|
|
15
67
|
## [0.14.2] - 2026-10-21
|
|
16
68
|
|
|
17
69
|
### Added
|
|
@@ -65,9 +65,9 @@ For example:
|
|
|
65
65
|
- *Always* handle the variants of an enum with an exhaustive `match`. A `let ... else`, or an `if` that handles one
|
|
66
66
|
variant and sends the rest to a single branch, quietly gives any new variant whatever that branch does. With a
|
|
67
67
|
`match`, the compiler makes you decide what to do with each new variant. One exception: a `match` on another
|
|
68
|
-
crate's enum can end with `_` when it only
|
|
69
|
-
|
|
70
|
-
Say why in a comment next to the `_`.
|
|
68
|
+
crate's enum can end with `_` when it only picks out one or a few variants, and no new variant could be one of
|
|
69
|
+
them. For example, every Markdown heading is `mdast::Node::Heading`, so the other node types can go to
|
|
70
|
+
`_ => None`. Say why in a comment next to the `_`.
|
|
71
71
|
- *Always* give an item the narrowest visibility that compiles: private, then `pub(super)`, then `pub(crate)`.
|
|
72
72
|
blockwatch is a program, not a library. Only `run` and `count_rust_blocks` in `lib.rs` are `pub`, for `main.rs` and
|
|
73
73
|
the fuzz target. The `unreachable_pub` lint makes `cargo clippy -- -D warnings` fail on any other `pub`.
|
|
@@ -173,8 +173,9 @@ The whole pipeline is in `src/cli.rs`. `src/main.rs` only calls `blockwatch::run
|
|
|
173
173
|
from the command line select, and that don't match the settings' ignore globs. `PathArguments::resolve` turns an
|
|
174
174
|
existing file or directory into a glob first, so `src` selects `src/**`. Pick each file's language by its
|
|
175
175
|
extension, using the settings' extension mappings too.
|
|
176
|
-
6. For each file, the matching `language_parsers::<lang>` (a tree-sitter grammar) finds the comments.
|
|
177
|
-
`block_parser` turn the comment text into `Block` values, with their attributes and their byte and
|
|
176
|
+
6. For each file, the matching `language_parsers::<lang>` (usually a tree-sitter grammar) finds the comments.
|
|
177
|
+
`tag_parser` and `block_parser` turn the comment text into `Block` values, with their attributes and their byte and
|
|
178
|
+
line ranges.
|
|
178
179
|
`VirtualBlock::resolve` finds each virtual block in the file, by its `Locator`, and adds it as a `Block` too. A file
|
|
179
180
|
without a grammar is read as plain text: it has no tags, only its virtual blocks. A target that does not resolve
|
|
180
181
|
stops the run. `--only-changed` also parses the file of a virtual block whose entry the diff
|
|
@@ -224,7 +225,8 @@ The main modules:
|
|
|
224
225
|
- `src/repo_path.rs` — `RepoPath`, the one way to write a path relative to the repository root. A diff header
|
|
225
226
|
(`b/src/main.rs`), a path found in the walk and a `file:name` attribute all become a `RepoPath`. So the same file is
|
|
226
227
|
always the same map key.
|
|
227
|
-
- `src/language_parsers/` — one
|
|
228
|
+
- `src/language_parsers/` — one parser for each language, most of them a tree-sitter grammar. Markdown and MDX use
|
|
229
|
+
the `markdown` crate, and Lean has its own scanner. Each language has a `parser()` that returns a
|
|
228
230
|
`LanguageParser`, which knows which syntax nodes are comments. `src/block_parser.rs` turns those comments into
|
|
229
231
|
blocks. `language_parsers()` in `language_parsers/mod.rs` returns `LanguageParsers`: the parser of each extension.
|
|
230
232
|
Its `parser_for` picks the parser of a file, using the settings' extension mappings too. **To add a language, add a
|
|
@@ -238,8 +240,7 @@ The main modules:
|
|
|
238
240
|
syntax tree is nested.
|
|
239
241
|
- YAML walks its syntax tree itself. An alias has a position in a sequence but can't be addressed, and a query can't
|
|
240
242
|
express that.
|
|
241
|
-
- Markdown finds its sections with the `markdown` crate
|
|
242
|
-
heading underlined with `---`.
|
|
243
|
+
- Markdown finds its sections with the `markdown` crate, the same parser that finds its comments.
|
|
243
244
|
|
|
244
245
|
Each language's tests list every symbol it finds. When you give a language symbols, also document its paths in
|
|
245
246
|
`docs/symbols.md` and in the "Symbols" section of the skill, `src/skill.md`. A test in `language_parsers/mod.rs` and the
|
|
@@ -274,7 +274,7 @@ checksum = "3ded4057c258ba199e2d26386d3af3780957ecaee6c4ef4041c6b4b8b97c0b06"
|
|
|
274
274
|
|
|
275
275
|
[[package]]
|
|
276
276
|
name = "blockwatch"
|
|
277
|
-
version = "0.
|
|
277
|
+
version = "0.16.0"
|
|
278
278
|
dependencies = [
|
|
279
279
|
"anyhow",
|
|
280
280
|
"assert-json-diff",
|
|
@@ -327,7 +327,6 @@ dependencies = [
|
|
|
327
327
|
"tree-sitter-kotlin-ng",
|
|
328
328
|
"tree-sitter-lua",
|
|
329
329
|
"tree-sitter-make",
|
|
330
|
-
"tree-sitter-md",
|
|
331
330
|
"tree-sitter-nix",
|
|
332
331
|
"tree-sitter-ocaml",
|
|
333
332
|
"tree-sitter-php",
|
|
@@ -2637,16 +2636,6 @@ dependencies = [
|
|
|
2637
2636
|
"tree-sitter-language",
|
|
2638
2637
|
]
|
|
2639
2638
|
|
|
2640
|
-
[[package]]
|
|
2641
|
-
name = "tree-sitter-md"
|
|
2642
|
-
version = "0.5.3"
|
|
2643
|
-
source = "registry+https://github.com/rust-lang/crates.io-index"
|
|
2644
|
-
checksum = "2efd398be546456c814598ee56c0f51769a77241511b4a58077815d120afa882"
|
|
2645
|
-
dependencies = [
|
|
2646
|
-
"cc",
|
|
2647
|
-
"tree-sitter-language",
|
|
2648
|
-
]
|
|
2649
|
-
|
|
2650
2639
|
[[package]]
|
|
2651
2640
|
name = "tree-sitter-nix"
|
|
2652
2641
|
version = "0.3.0"
|
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
[package]
|
|
2
2
|
name = "blockwatch"
|
|
3
|
-
version = "0.
|
|
3
|
+
version = "0.16.0"
|
|
4
4
|
edition = "2024"
|
|
5
5
|
repository = "https://github.com/mennanov/blockwatch"
|
|
6
6
|
description = "Language agnostic linter that keeps your code and documentation in sync and valid"
|
|
@@ -62,7 +62,6 @@ tree-sitter-json = "0.24.8"
|
|
|
62
62
|
tree-sitter-kotlin-ng = "1.1"
|
|
63
63
|
tree-sitter-lua = "0.5"
|
|
64
64
|
tree-sitter-make = "1.1"
|
|
65
|
-
tree-sitter-md = "0.5"
|
|
66
65
|
tree-sitter-nix = "0.3.0"
|
|
67
66
|
tree-sitter-ocaml = "0.26"
|
|
68
67
|
tree-sitter-php = "0.25"
|
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
Metadata-Version: 2.4
|
|
2
2
|
Name: blockwatch-cli
|
|
3
|
-
Version: 0.
|
|
3
|
+
Version: 0.16.0
|
|
4
4
|
Summary: Language agnostic linter that keeps your code and documentation in sync and valid
|
|
5
5
|
Keywords: linter,sync,drift,comments,agents
|
|
6
6
|
Home-Page: https://github.com/mennanov/blockwatch
|
|
@@ -0,0 +1,11 @@
|
|
|
1
|
+
# The integration tests run inside this repository, so a run would read its blockwatch.toml, which
|
|
2
|
+
# skips tests/testdata.
|
|
3
|
+
disallowed-macros = [
|
|
4
|
+
{ path = "assert_cmd::cargo_bin_cmd", reason = "use common::cargo_bin_cmd!, which passes an empty config" },
|
|
5
|
+
]
|
|
6
|
+
# globset drops an empty alternative in braces by default, so `{,sub/}a.yml` would not match
|
|
7
|
+
# `a.yml`.
|
|
8
|
+
disallowed-methods = [
|
|
9
|
+
{ path = "globset::Glob::new", reason = "use paths_glob::glob_builder, which keeps an empty alternative" },
|
|
10
|
+
{ path = "globset::GlobBuilder::new", reason = "use paths_glob::glob_builder, which keeps an empty alternative" },
|
|
11
|
+
]
|
|
@@ -19,7 +19,7 @@ To use [pre-commit](https://pre-commit.com), add the hook to `.pre-commit-config
|
|
|
19
19
|
|
|
20
20
|
```yaml
|
|
21
21
|
- repo: https://github.com/mennanov/blockwatch
|
|
22
|
-
rev: v0.
|
|
22
|
+
rev: v0.16.0 # Use latest release
|
|
23
23
|
hooks:
|
|
24
24
|
- id: blockwatch
|
|
25
25
|
```
|
|
@@ -59,7 +59,7 @@ The `blockwatch` hook runs before the commit message exists, so it cannot see a
|
|
|
59
59
|
|
|
60
60
|
```yaml
|
|
61
61
|
- repo: https://github.com/mennanov/blockwatch
|
|
62
|
-
rev: v0.
|
|
62
|
+
rev: v0.16.0 # Use latest release
|
|
63
63
|
hooks:
|
|
64
64
|
- id: blockwatch-commit-msg
|
|
65
65
|
```
|
|
@@ -557,15 +557,15 @@ Nothing else about the run changes: the same violations are found, and the exit
|
|
|
557
557
|
"tool": {
|
|
558
558
|
"driver": {
|
|
559
559
|
"name": "blockwatch",
|
|
560
|
-
"version": "0.
|
|
561
|
-
"semanticVersion": "0.
|
|
560
|
+
"version": "0.16.0",
|
|
561
|
+
"semanticVersion": "0.16.0",
|
|
562
562
|
"informationUri": "https://github.com/mennanov/blockwatch",
|
|
563
563
|
"rules": [
|
|
564
564
|
{
|
|
565
565
|
"id": "keep-sorted",
|
|
566
566
|
"name": "keep-sorted",
|
|
567
567
|
"shortDescription": { "text": "Requires the lines of a block to stay in order." },
|
|
568
|
-
"helpUri": "https://github.com/mennanov/blockwatch/blob/v0.
|
|
568
|
+
"helpUri": "https://github.com/mennanov/blockwatch/blob/v0.16.0/docs/validators/keep-sorted.md"
|
|
569
569
|
}
|
|
570
570
|
]
|
|
571
571
|
}
|
|
@@ -790,16 +790,16 @@ A trace stops where its validator stops, such as at the first line out of order.
|
|
|
790
790
|
file, and `text` is that line trimmed, as the validator compares it. A key that holds what a violation reports has the
|
|
791
791
|
name the violation's `data` gives it, such as `reason`.
|
|
792
792
|
|
|
793
|
-
| Validator | What it shows
|
|
794
|
-
|
|
795
|
-
| `same-as` | `records`: each match of `same-as-pattern` in the block, with its `line`, the text the regex matched (`match`), and each named group after `same-as-format` (`groups`). `targets`: the `records` of each target, and the `reason` of its violation, or `null` when the two agree. `paths`: with `same-as-paths`, the `glob`, the paths it `matched`, their `records` and the `reason`. |
|
|
796
|
-
| `keep-sorted` | `lines`: each line read, with the `value` it compares, or `null` when `keep-sorted-pattern` skips the line. `format` and `order`.
|
|
797
|
-
| `keep-unique` | `lines`, as for `keep-sorted`. A repeated value has `duplicate_of`: the line where it first appeared.
|
|
798
|
-
| `line-pattern` | `lines`: each line read, with the text `line-pattern` matched (`match`). A line that fails has `fails`: the check it fails. `forbidden_match` is the text `line-pattern-forbidden` found.
|
|
799
|
-
| `line-count` | `lines`, as for `keep-sorted`. A line counts when its `value` isn't `null`. The number of lines counted (`actual`), and the rule (`op` and `expected`).
|
|
800
|
-
| `affects` | Whether the diff changed the block (`block_changed`). For each target: whether the diff `changed` it, or the `reason` it doesn't resolve.
|
|
801
|
-
| `check-lua` | The `content` and the `affects` the script got, and the message it returned (`lua_error`), or `null` when it passed. `affects` is `ctx.affects` without the content of each target.
|
|
802
|
-
| `check-ai` | The `model`, the `prompt` sent and the `response`. Both are `null` when `check-ai-pattern` matched nothing, so no request was sent.
|
|
793
|
+
| Validator | What it shows |
|
|
794
|
+
|----------------|---------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------|
|
|
795
|
+
| `same-as` | `records`: each match of `same-as-pattern` in the block, or each line without a pattern, with its `line`, the text the regex matched (`match`), and each named group after `same-as-format` (`groups`). `mode`: the `same-as-mode` it compared with. `targets`: the `records` of each target, and the `reason` of its violation, or `null` when the two agree. `paths`: with `same-as-paths`, the `glob`, the paths it `matched`, their `records` and the `reason`. |
|
|
796
|
+
| `keep-sorted` | `lines`: each line read, with the `value` it compares, or `null` when `keep-sorted-pattern` skips the line. `format` and `order`. |
|
|
797
|
+
| `keep-unique` | `lines`, as for `keep-sorted`. A repeated value has `duplicate_of`: the line where it first appeared. |
|
|
798
|
+
| `line-pattern` | `lines`: each line read, with the text `line-pattern` matched (`match`). A line that fails has `fails`: the check it fails. `forbidden_match` is the text `line-pattern-forbidden` found. |
|
|
799
|
+
| `line-count` | `lines`, as for `keep-sorted`. A line counts when its `value` isn't `null`. The number of lines counted (`actual`), and the rule (`op` and `expected`). |
|
|
800
|
+
| `affects` | Whether the diff changed the block (`block_changed`). For each target: whether the diff `changed` it, or the `reason` it doesn't resolve. |
|
|
801
|
+
| `check-lua` | The `content` and the `affects` the script got, and the message it returned (`lua_error`), or `null` when it passed. `affects` is `ctx.affects` without the content of each target. |
|
|
802
|
+
| `check-ai` | The `model`, the `prompt` sent and the `response`. Both are `null` when `check-ai-pattern` matched nothing, so no request was sent. |
|
|
803
803
|
|
|
804
804
|
## Run Reports
|
|
805
805
|
|
|
@@ -10,6 +10,9 @@ mention the company name", "no TODOs left", "the tone matches the rest of the pa
|
|
|
10
10
|
| `check-ai` | the condition, in natural language | — |
|
|
11
11
|
| `check-ai-pattern` | regex; every match's `(?P<value>…)` group, or whole match | whole block |
|
|
12
12
|
|
|
13
|
+
`check-ai-pattern` works only next to `check-ai`. On a block without it, it stops the run, because it would do nothing
|
|
14
|
+
there.
|
|
15
|
+
|
|
13
16
|
## Example
|
|
14
17
|
|
|
15
18
|
```html
|
|
@@ -19,6 +19,9 @@ string when it fails.
|
|
|
19
19
|
|
|
20
20
|
<!-- </block> -->
|
|
21
21
|
|
|
22
|
+
`check-lua-pattern` and `check-lua-timeout` work only next to `check-lua`. On a block without it, they stop the run,
|
|
23
|
+
because they would do nothing there.
|
|
24
|
+
|
|
22
25
|
The script path must point to a file inside the repository. Paths that escape it — absolute paths outside the project,
|
|
23
26
|
`../` traversal, or symlinks pointing outward — are rejected.
|
|
24
27
|
|
|
@@ -10,6 +10,9 @@ Keeps a list ordered. Eliminates "please sort this" review nits.
|
|
|
10
10
|
| `keep-sorted-pattern` | regex; the `(?P<value>…)` group, or the whole match | whole line |
|
|
11
11
|
| `keep-sorted-format` | `numeric` | text |
|
|
12
12
|
|
|
13
|
+
`keep-sorted-pattern` and `keep-sorted-format` work only next to `keep-sorted`. On a block without it, they stop the
|
|
14
|
+
run, because they would do nothing there.
|
|
15
|
+
|
|
13
16
|
## Example
|
|
14
17
|
|
|
15
18
|
```python
|
|
@@ -10,6 +10,9 @@ size of the enum it maps.
|
|
|
10
10
|
| `line-count` | `<N`, `<=N`, `==N`, `>=N`, `>N` | — |
|
|
11
11
|
| `line-count-pattern` | regex; a line counts when it gives a value | every line that has text |
|
|
12
12
|
|
|
13
|
+
`line-count-pattern` works only next to `line-count`. On a block without it, it stops the run, because it would do
|
|
14
|
+
nothing there.
|
|
15
|
+
|
|
13
16
|
## Example
|
|
14
17
|
|
|
15
18
|
```python
|
|
@@ -8,13 +8,17 @@ It runs on every scan, with or without a diff.
|
|
|
8
8
|
|
|
9
9
|
## Syntax
|
|
10
10
|
|
|
11
|
-
| Attribute | Value | Default
|
|
12
|
-
|
|
13
|
-
| `same-as` | One or more [targets](#targets), comma-separated | —
|
|
14
|
-
| `same-as-paths` | A [glob](#paths-as-targets) of paths to compare | —
|
|
15
|
-
| `same-as-pattern` | A regex that picks the values to compare |
|
|
16
|
-
| `same-as-mode` | `set`, `sequence`, `single` or `subset` | `set`
|
|
17
|
-
| `same-as-format` | `numeric`, `identifier` or `flat`, or [one for each group](#a-format-for-each-group) | text
|
|
11
|
+
| Attribute | Value | Default |
|
|
12
|
+
|-------------------|--------------------------------------------------------------------------------------|------------------------------------------|
|
|
13
|
+
| `same-as` | One or more [targets](#targets), comma-separated | — |
|
|
14
|
+
| `same-as-paths` | A [glob](#paths-as-targets) of paths to compare | — |
|
|
15
|
+
| `same-as-pattern` | A regex that picks the values to compare | each line |
|
|
16
|
+
| `same-as-mode` | `set`, `sequence`, `single` or `subset` | [`sequence` or `set`](#comparison-modes) |
|
|
17
|
+
| `same-as-format` | `numeric`, `identifier` or `flat`, or [one for each group](#a-format-for-each-group) | text |
|
|
18
|
+
|
|
19
|
+
`same-as-mode` and `same-as-format` work only next to `same-as` or `same-as-paths`. `same-as-pattern` also works next
|
|
20
|
+
to `name`, because a block with a name can be a target. On any other block, they stop the run, because they would do
|
|
21
|
+
nothing there.
|
|
18
22
|
|
|
19
23
|
## Targets
|
|
20
24
|
|
|
@@ -28,7 +32,8 @@ It runs on every scan, with or without a diff.
|
|
|
28
32
|
|
|
29
33
|
## Example
|
|
30
34
|
|
|
31
|
-
With no other attributes, both blocks must hold **identical** text
|
|
35
|
+
With no other attributes, both blocks must hold **identical** text: the same lines in the same order. Blank lines and
|
|
36
|
+
indentation don't count. This suits
|
|
32
37
|
text you can't share any other way, such as a command shown in two docs:
|
|
33
38
|
|
|
34
39
|
**README.md**:
|
|
@@ -145,7 +150,8 @@ pub const NODE_VERSION: &str = "20.11.1";
|
|
|
145
150
|
```
|
|
146
151
|
|
|
147
152
|
The file has no block of its own, so the referencing block's pattern reads both sides. For anything longer than one
|
|
148
|
-
line, you will want a pattern: without one, the block must equal the entire file.
|
|
153
|
+
line, you will want a pattern: without one, the block must equal the entire file. Or add `same-as-mode="subset"`: then
|
|
154
|
+
each line of the block must be a line of the file.
|
|
149
155
|
|
|
150
156
|
## Symbols as targets
|
|
151
157
|
|
|
@@ -187,10 +193,10 @@ show every entry of a directory, such as the services in a README:
|
|
|
187
193
|
The glob lists `services/auth/`, `services/billing/` and `services/search/`. The pattern picks `auth`, `billing` and
|
|
188
194
|
`search` from them, and `billing` and `search` from the block. So the run reports that `auth` is missing.
|
|
189
195
|
|
|
190
|
-
-
|
|
191
|
-
`
|
|
192
|
-
- **The paths are sorted, and each one is listed once.**
|
|
193
|
-
|
|
196
|
+
- **The block's `same-as-pattern` reads both the block and the paths.** Without a pattern, each line of the block must
|
|
197
|
+
be a path, such as `services/billing/`.
|
|
198
|
+
- **The paths are sorted, and each one is listed once.** Without a pattern, or with `same-as-mode="sequence"`, the
|
|
199
|
+
block must list them in that order. To allow any order, add `same-as-mode="set"`.
|
|
194
200
|
- **A trailing `/` lists directories.** A directory is listed when it holds a file, and `services/billing/` is listed
|
|
195
201
|
once however many files it holds. Without the `/`, the glob lists files: `crates/*/AGENTS.md`.
|
|
196
202
|
- **`*` stops at `/`.** `services/*/` lists `services/billing/`, but not `services/billing/src/`. `**` matches any
|
|
@@ -205,12 +211,22 @@ A block can have both `same-as` and `same-as-paths`. Each target is compared wit
|
|
|
205
211
|
|
|
206
212
|
## Comparison modes
|
|
207
213
|
|
|
208
|
-
| `same-as-mode`
|
|
209
|
-
|
|
210
|
-
| `set`
|
|
211
|
-
| `sequence`
|
|
212
|
-
| `single`
|
|
213
|
-
| `subset`
|
|
214
|
+
| `same-as-mode` | Passes when |
|
|
215
|
+
|----------------|-----------------------------------------------------------------|
|
|
216
|
+
| `set` | both sides hold the same values, in any order, ignoring repeats |
|
|
217
|
+
| `sequence` | both sides hold the same values in the same order |
|
|
218
|
+
| `single` | each side holds exactly one value, and the two are equal |
|
|
219
|
+
| `subset` | every value in this block also appears in the target |
|
|
220
|
+
|
|
221
|
+
Without `same-as-mode`, the mode depends on the block's own `same-as-pattern`. A target's pattern doesn't change it.
|
|
222
|
+
|
|
223
|
+
- **The block has no pattern:** `sequence`. Each line that isn't blank is a value, so the two sides must hold the same
|
|
224
|
+
lines in the same order, as in the [example](#example).
|
|
225
|
+
- **The block has a pattern:** `set`.
|
|
226
|
+
|
|
227
|
+
So adding a pattern stops order from mattering. To keep the order, add `same-as-mode="sequence"` too. And a block
|
|
228
|
+
without a pattern fails when its target's pattern finds a value twice: `["1.2.3"] != ["1.2.3", "1.2.3"]`. To allow
|
|
229
|
+
repeats, add `same-as-mode="set"` or `same-as-mode="subset"`.
|
|
214
230
|
|
|
215
231
|
`subset` checks one direction only. Use it when one side should hold part of the other, like a test that uses only
|
|
216
232
|
some of the environment variables:
|
|
@@ -356,14 +372,18 @@ const TIMEOUT_SECS: f64 = 2.0;
|
|
|
356
372
|
## Notes
|
|
357
373
|
|
|
358
374
|
- **Which block's attributes count.** The referencing block's `same-as-mode` and `same-as-format` decide how to compare.
|
|
359
|
-
|
|
360
|
-
|
|
375
|
+
On a target, or any block without `same-as` or `same-as-paths`, they stop the run, because they would do nothing
|
|
376
|
+
there. Each block's `same-as-pattern` reads only that block. A whole file, a symbol or a list of paths has no block,
|
|
377
|
+
so the referencing block's pattern reads it too. Only a block with a name can be a target, so `same-as-pattern` on a
|
|
378
|
+
block without `same-as`, `same-as-paths` or `name` stops the run.
|
|
361
379
|
- **Violations:** a missing block, a missing or repeated key, a value that is not a number under `numeric`, a `single`
|
|
362
|
-
side without exactly one value, a
|
|
363
|
-
and a `same-as-paths` glob that matches no path. Two empty sides do not count as
|
|
364
|
-
|
|
365
|
-
|
|
366
|
-
|
|
380
|
+
side without exactly one value, a side with no values (such as an empty block, or a pattern that matches nothing),
|
|
381
|
+
two patterns with different groups, and a `same-as-paths` glob that matches no path. Two empty sides do not count as
|
|
382
|
+
equal.
|
|
383
|
+
- **Errors that stop the run:** an unknown `same-as-mode` or `same-as-format`, either of them on a block without
|
|
384
|
+
`same-as` or `same-as-paths`, `same-as-pattern` on a block without `same-as`, `same-as-paths` or `name`, a
|
|
385
|
+
`same-as-format` entry for a group that the pattern doesn't have, an invalid regex or glob, a missing target file,
|
|
386
|
+
and a symbol in a file with a syntax error, without symbols, or with several YAML documents.
|
|
367
387
|
- **Run it on the whole tree now and then.** `same-as` needs no diff, so a plain `blockwatch` run catches drift that
|
|
368
388
|
`--only-changed` misses. See [CI integration](../ci.md).
|
|
369
389
|
- **A rename alone goes unnoticed in a diff.** Renaming a target file without changing it (a plain `git mv`) gives
|
|
@@ -6,7 +6,7 @@ setup(
|
|
|
6
6
|
name='blockwatch-pre-commit-placeholder',
|
|
7
7
|
version='0.0.0',
|
|
8
8
|
# <block name="blockwatch-cli-version" same-as-pattern="blockwatch-cli==(?P<value>\d+\.\d+\.\d+)">
|
|
9
|
-
install_requires=['blockwatch-cli==0.
|
|
9
|
+
install_requires=['blockwatch-cli==0.16.0'],
|
|
10
10
|
# </block>
|
|
11
11
|
# Without it, setuptools takes the directories under src/ for Python packages.
|
|
12
12
|
packages=[],
|
|
@@ -13,6 +13,7 @@ use std::collections::{BTreeMap, BTreeSet, HashMap};
|
|
|
13
13
|
use std::fmt;
|
|
14
14
|
use std::ops::Range;
|
|
15
15
|
use std::str::FromStr;
|
|
16
|
+
use strum::IntoEnumIterator;
|
|
16
17
|
use strum_macros::EnumString;
|
|
17
18
|
|
|
18
19
|
const UNNAMED_BLOCK_LABEL: &str = "(unnamed)";
|
|
@@ -496,11 +497,12 @@ const RECOGNIZED_ATTRIBUTES: &[&str] = &[
|
|
|
496
497
|
// </block>
|
|
497
498
|
];
|
|
498
499
|
|
|
499
|
-
/// Checks that each attribute of a block is recognized
|
|
500
|
+
/// Checks that each attribute of a block is recognized, and that each validator accepts the
|
|
501
|
+
/// attributes it reads (see [`Validator::check_attributes`]). It does not check the values: see
|
|
500
502
|
/// [`BlockSeverity::from_attributes`] for `severity`.
|
|
501
503
|
///
|
|
502
504
|
/// # Errors
|
|
503
|
-
/// Returns an error that quotes the attribute
|
|
505
|
+
/// Returns an error that quotes the first attribute found to be wrong, such as
|
|
504
506
|
/// ``unrecognized attribute `keep-sortd` ``.
|
|
505
507
|
pub(crate) fn validate_attributes(attributes: &HashMap<String, String>) -> anyhow::Result<()> {
|
|
506
508
|
if let Some(name) = attributes
|
|
@@ -509,7 +511,39 @@ pub(crate) fn validate_attributes(attributes: &HashMap<String, String>) -> anyho
|
|
|
509
511
|
{
|
|
510
512
|
bail!("unrecognized attribute `{name}`");
|
|
511
513
|
}
|
|
512
|
-
|
|
514
|
+
// A block can be in a file that the run reads only to find a target, and no validator runs on
|
|
515
|
+
// such a block. Every parsed block passes here.
|
|
516
|
+
Validator::iter().try_for_each(|validator| validator.check_attributes(attributes))
|
|
517
|
+
}
|
|
518
|
+
|
|
519
|
+
#[cfg(test)]
|
|
520
|
+
mod validate_attributes_tests {
|
|
521
|
+
use crate::blocks::{RECOGNIZED_ATTRIBUTES, validate_attributes};
|
|
522
|
+
use crate::validators::Validator;
|
|
523
|
+
use std::collections::HashMap;
|
|
524
|
+
use strum::IntoEnumIterator;
|
|
525
|
+
|
|
526
|
+
#[test]
|
|
527
|
+
fn single_attribute_returns_an_error_only_when_it_needs_another() {
|
|
528
|
+
// A new attribute must either work alone or stop the run alone. Otherwise a block with
|
|
529
|
+
// only that attribute would pass without being checked.
|
|
530
|
+
let needs_no_other: Vec<&str> = Validator::iter()
|
|
531
|
+
.map(Validator::as_str)
|
|
532
|
+
.chain([
|
|
533
|
+
"line-pattern-forbidden",
|
|
534
|
+
"name",
|
|
535
|
+
"same-as-paths",
|
|
536
|
+
"severity",
|
|
537
|
+
])
|
|
538
|
+
.collect();
|
|
539
|
+
for name in RECOGNIZED_ATTRIBUTES {
|
|
540
|
+
let attributes = HashMap::from([(name.to_string(), String::new())]);
|
|
541
|
+
|
|
542
|
+
let result = validate_attributes(&attributes);
|
|
543
|
+
|
|
544
|
+
assert_eq!(result.is_ok(), needs_no_other.contains(name), "{name}");
|
|
545
|
+
}
|
|
546
|
+
}
|
|
513
547
|
}
|
|
514
548
|
|
|
515
549
|
#[cfg(test)]
|
|
@@ -272,7 +272,9 @@ fn is_entry_modified(
|
|
|
272
272
|
/// - the target's file is a glob that is not valid or that matches no file;
|
|
273
273
|
/// - `target-pattern` comes with a symbol, or is not a valid regex;
|
|
274
274
|
/// - an attribute is not one a tag can have, or has a value that is not a string, `true` or an
|
|
275
|
-
/// integer
|
|
275
|
+
/// integer;
|
|
276
|
+
/// - an attribute comes without the attribute its validator needs, such as `check-lua-timeout`
|
|
277
|
+
/// without `check-lua`.
|
|
276
278
|
fn entry_blocks(
|
|
277
279
|
block_entry: BlockEntry,
|
|
278
280
|
entry: ConfigEntry,
|
|
@@ -433,6 +435,7 @@ mod tests {
|
|
|
433
435
|
target = 'package.json#/version'
|
|
434
436
|
name = 'version'
|
|
435
437
|
keep-unique = true
|
|
438
|
+
check-lua = 'check.lua'
|
|
436
439
|
check-lua-timeout = 30
|
|
437
440
|
|
|
438
441
|
[[block]]
|
|
@@ -450,6 +453,7 @@ target = 'a.yaml#/b'
|
|
|
450
453
|
attributes: HashMap::from([
|
|
451
454
|
("name".to_string(), "version".to_string()),
|
|
452
455
|
("keep-unique".to_string(), String::new()),
|
|
456
|
+
("check-lua".to_string(), "check.lua".to_string()),
|
|
453
457
|
("check-lua-timeout".to_string(), "30".to_string()),
|
|
454
458
|
]),
|
|
455
459
|
entry: ConfigEntry {
|
|
@@ -465,7 +469,7 @@ target = 'a.yaml#/b'
|
|
|
465
469
|
attributes: HashMap::new(),
|
|
466
470
|
entry: ConfigEntry {
|
|
467
471
|
file: PathBuf::from(DEFAULT_FILE),
|
|
468
|
-
line:
|
|
472
|
+
line: 10,
|
|
469
473
|
},
|
|
470
474
|
is_entry_modified: false,
|
|
471
475
|
severity: BlockSeverity::Error,
|
|
@@ -263,7 +263,11 @@ impl PathFilter {
|
|
|
263
263
|
fn glob_set(globs: impl IntoIterator<Item = impl AsRef<str>>) -> GlobSet {
|
|
264
264
|
let mut builder = GlobSet::builder();
|
|
265
265
|
for glob in globs {
|
|
266
|
-
builder.add(
|
|
266
|
+
builder.add(
|
|
267
|
+
crate::paths_glob::glob_builder(glob.as_ref())
|
|
268
|
+
.build()
|
|
269
|
+
.expect("malformed test glob"),
|
|
270
|
+
);
|
|
267
271
|
}
|
|
268
272
|
builder.build().expect("failed to build test glob set")
|
|
269
273
|
}
|