blockwatch-cli 0.16.3__tar.gz → 0.16.4__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.
Files changed (302) hide show
  1. {blockwatch_cli-0.16.3 → blockwatch_cli-0.16.4}/CHANGELOG.md +20 -0
  2. {blockwatch_cli-0.16.3 → blockwatch_cli-0.16.4}/Cargo.lock +1 -1
  3. {blockwatch_cli-0.16.3 → blockwatch_cli-0.16.4}/Cargo.toml +1 -1
  4. {blockwatch_cli-0.16.3 → blockwatch_cli-0.16.4}/PKG-INFO +1 -1
  5. {blockwatch_cli-0.16.3 → blockwatch_cli-0.16.4}/README.md +2 -2
  6. {blockwatch_cli-0.16.3 → blockwatch_cli-0.16.4}/docs/ci.md +2 -2
  7. {blockwatch_cli-0.16.3 → blockwatch_cli-0.16.4}/docs/cli.md +3 -3
  8. {blockwatch_cli-0.16.3 → blockwatch_cli-0.16.4}/docs/symbols.md +132 -3
  9. {blockwatch_cli-0.16.3 → blockwatch_cli-0.16.4}/setup.py +1 -1
  10. {blockwatch_cli-0.16.3 → blockwatch_cli-0.16.4}/src/language_parsers/c.rs +7 -1
  11. {blockwatch_cli-0.16.3 → blockwatch_cli-0.16.4}/src/language_parsers/c_sharp.rs +3 -21
  12. {blockwatch_cli-0.16.3 → blockwatch_cli-0.16.4}/src/language_parsers/java.rs +47 -24
  13. blockwatch_cli-0.16.4/src/language_parsers/kotlin.rs +802 -0
  14. {blockwatch_cli-0.16.3 → blockwatch_cli-0.16.4}/src/language_parsers/mod.rs +3 -0
  15. {blockwatch_cli-0.16.3 → blockwatch_cli-0.16.4}/src/language_parsers/rust.rs +9 -0
  16. blockwatch_cli-0.16.4/src/language_parsers/swift.rs +1195 -0
  17. {blockwatch_cli-0.16.3 → blockwatch_cli-0.16.4}/src/skill.md +38 -3
  18. {blockwatch_cli-0.16.3 → blockwatch_cli-0.16.4}/src/symbols/code.rs +114 -17
  19. {blockwatch_cli-0.16.3 → blockwatch_cli-0.16.4}/tests/symbol_references.rs +21 -0
  20. blockwatch_cli-0.16.4/tests/testdata/symbol_references/kt_source.rs +3 -0
  21. blockwatch_cli-0.16.4/tests/testdata/symbol_references/kt_target.kt +5 -0
  22. blockwatch_cli-0.16.4/tests/testdata/symbol_references/kts_source.rs +3 -0
  23. blockwatch_cli-0.16.4/tests/testdata/symbol_references/kts_target.kts +5 -0
  24. blockwatch_cli-0.16.4/tests/testdata/symbol_references/swift_source.rs +3 -0
  25. blockwatch_cli-0.16.4/tests/testdata/symbol_references/swift_target.swift +5 -0
  26. blockwatch_cli-0.16.3/src/language_parsers/kotlin.rs +0 -86
  27. blockwatch_cli-0.16.3/src/language_parsers/swift.rs +0 -91
  28. {blockwatch_cli-0.16.3 → blockwatch_cli-0.16.4}/.agents/.claude-plugin/plugin.json +0 -0
  29. {blockwatch_cli-0.16.3 → blockwatch_cli-0.16.4}/.agents/skills/blockwatch/SKILL.md +0 -0
  30. {blockwatch_cli-0.16.3 → blockwatch_cli-0.16.4}/.claude-plugin/marketplace.json +0 -0
  31. {blockwatch_cli-0.16.3 → blockwatch_cli-0.16.4}/.github/dependabot.yml +0 -0
  32. {blockwatch_cli-0.16.3 → blockwatch_cli-0.16.4}/.github/workflows/blockwatch.yml +0 -0
  33. {blockwatch_cli-0.16.3 → blockwatch_cli-0.16.4}/.github/workflows/codeql.yml +0 -0
  34. {blockwatch_cli-0.16.3 → blockwatch_cli-0.16.4}/.github/workflows/markdownlint.yml +0 -0
  35. {blockwatch_cli-0.16.3 → blockwatch_cli-0.16.4}/.github/workflows/pypi.yml +0 -0
  36. {blockwatch_cli-0.16.3 → blockwatch_cli-0.16.4}/.github/workflows/release.yml +0 -0
  37. {blockwatch_cli-0.16.3 → blockwatch_cli-0.16.4}/.github/workflows/rust.yml +0 -0
  38. {blockwatch_cli-0.16.3 → blockwatch_cli-0.16.4}/.github/workflows/trusted-checks.yml +0 -0
  39. {blockwatch_cli-0.16.3 → blockwatch_cli-0.16.4}/.gitignore +0 -0
  40. {blockwatch_cli-0.16.3 → blockwatch_cli-0.16.4}/.markdownlint-cli2.yaml +0 -0
  41. {blockwatch_cli-0.16.3 → blockwatch_cli-0.16.4}/.pre-commit-config.yaml +0 -0
  42. {blockwatch_cli-0.16.3 → blockwatch_cli-0.16.4}/.pre-commit-hooks.yaml +0 -0
  43. {blockwatch_cli-0.16.3 → blockwatch_cli-0.16.4}/AGENTS.md +0 -0
  44. {blockwatch_cli-0.16.3 → blockwatch_cli-0.16.4}/CLAUDE.md +0 -0
  45. {blockwatch_cli-0.16.3 → blockwatch_cli-0.16.4}/LICENSE +0 -0
  46. {blockwatch_cli-0.16.3 → blockwatch_cli-0.16.4}/SECURITY.md +0 -0
  47. {blockwatch_cli-0.16.3 → blockwatch_cli-0.16.4}/blockwatch.toml +0 -0
  48. {blockwatch_cli-0.16.3 → blockwatch_cli-0.16.4}/clippy.toml +0 -0
  49. {blockwatch_cli-0.16.3 → blockwatch_cli-0.16.4}/codecov.yml +0 -0
  50. {blockwatch_cli-0.16.3 → blockwatch_cli-0.16.4}/demo.gif +0 -0
  51. {blockwatch_cli-0.16.3 → blockwatch_cli-0.16.4}/dist-workspace.toml +0 -0
  52. {blockwatch_cli-0.16.3 → blockwatch_cli-0.16.4}/docs/agents.md +0 -0
  53. {blockwatch_cli-0.16.3 → blockwatch_cli-0.16.4}/docs/validators/README.md +0 -0
  54. {blockwatch_cli-0.16.3 → blockwatch_cli-0.16.4}/docs/validators/affects.md +0 -0
  55. {blockwatch_cli-0.16.3 → blockwatch_cli-0.16.4}/docs/validators/check-ai.md +0 -0
  56. {blockwatch_cli-0.16.3 → blockwatch_cli-0.16.4}/docs/validators/check-lua.md +0 -0
  57. {blockwatch_cli-0.16.3 → blockwatch_cli-0.16.4}/docs/validators/keep-sorted.md +0 -0
  58. {blockwatch_cli-0.16.3 → blockwatch_cli-0.16.4}/docs/validators/keep-unique.md +0 -0
  59. {blockwatch_cli-0.16.3 → blockwatch_cli-0.16.4}/docs/validators/line-count.md +0 -0
  60. {blockwatch_cli-0.16.3 → blockwatch_cli-0.16.4}/docs/validators/line-pattern.md +0 -0
  61. {blockwatch_cli-0.16.3 → blockwatch_cli-0.16.4}/docs/validators/same-as.md +0 -0
  62. {blockwatch_cli-0.16.3 → blockwatch_cli-0.16.4}/pypi/pyproject.toml +0 -0
  63. {blockwatch_cli-0.16.3 → blockwatch_cli-0.16.4}/pyproject.toml +0 -0
  64. {blockwatch_cli-0.16.3 → blockwatch_cli-0.16.4}/release.toml +0 -0
  65. {blockwatch_cli-0.16.3 → blockwatch_cli-0.16.4}/scripts/check_language_count.lua +0 -0
  66. {blockwatch_cli-0.16.3 → blockwatch_cli-0.16.4}/scripts/check_latest_gpt_nano_model.lua +0 -0
  67. {blockwatch_cli-0.16.3 → blockwatch_cli-0.16.4}/src/block_parser.rs +0 -0
  68. {blockwatch_cli-0.16.3 → blockwatch_cli-0.16.4}/src/blocks.rs +0 -0
  69. {blockwatch_cli-0.16.3 → blockwatch_cli-0.16.4}/src/cli.rs +0 -0
  70. {blockwatch_cli-0.16.3 → blockwatch_cli-0.16.4}/src/config.rs +0 -0
  71. {blockwatch_cli-0.16.3 → blockwatch_cli-0.16.4}/src/diff_parser.rs +0 -0
  72. {blockwatch_cli-0.16.3 → blockwatch_cli-0.16.4}/src/explain.rs +0 -0
  73. {blockwatch_cli-0.16.3 → blockwatch_cli-0.16.4}/src/flags.rs +0 -0
  74. {blockwatch_cli-0.16.3 → blockwatch_cli-0.16.4}/src/fs.rs +0 -0
  75. {blockwatch_cli-0.16.3 → blockwatch_cli-0.16.4}/src/language_parsers/bash.rs +0 -0
  76. {blockwatch_cli-0.16.3 → blockwatch_cli-0.16.4}/src/language_parsers/cmake.rs +0 -0
  77. {blockwatch_cli-0.16.3 → blockwatch_cli-0.16.4}/src/language_parsers/cpp.rs +0 -0
  78. {blockwatch_cli-0.16.3 → blockwatch_cli-0.16.4}/src/language_parsers/css.rs +0 -0
  79. {blockwatch_cli-0.16.3 → blockwatch_cli-0.16.4}/src/language_parsers/dart.rs +0 -0
  80. {blockwatch_cli-0.16.3 → blockwatch_cli-0.16.4}/src/language_parsers/dockerfile.rs +0 -0
  81. {blockwatch_cli-0.16.3 → blockwatch_cli-0.16.4}/src/language_parsers/elixir.rs +0 -0
  82. {blockwatch_cli-0.16.3 → blockwatch_cli-0.16.4}/src/language_parsers/go.rs +0 -0
  83. {blockwatch_cli-0.16.3 → blockwatch_cli-0.16.4}/src/language_parsers/graphql.rs +0 -0
  84. {blockwatch_cli-0.16.3 → blockwatch_cli-0.16.4}/src/language_parsers/groovy.rs +0 -0
  85. {blockwatch_cli-0.16.3 → blockwatch_cli-0.16.4}/src/language_parsers/hcl.rs +0 -0
  86. {blockwatch_cli-0.16.3 → blockwatch_cli-0.16.4}/src/language_parsers/html.rs +0 -0
  87. {blockwatch_cli-0.16.3 → blockwatch_cli-0.16.4}/src/language_parsers/javascript.rs +0 -0
  88. {blockwatch_cli-0.16.3 → blockwatch_cli-0.16.4}/src/language_parsers/json.rs +0 -0
  89. {blockwatch_cli-0.16.3 → blockwatch_cli-0.16.4}/src/language_parsers/json.scm +0 -0
  90. {blockwatch_cli-0.16.3 → blockwatch_cli-0.16.4}/src/language_parsers/lean.rs +0 -0
  91. {blockwatch_cli-0.16.3 → blockwatch_cli-0.16.4}/src/language_parsers/lua.rs +0 -0
  92. {blockwatch_cli-0.16.3 → blockwatch_cli-0.16.4}/src/language_parsers/makefile.rs +0 -0
  93. {blockwatch_cli-0.16.3 → blockwatch_cli-0.16.4}/src/language_parsers/markdown.rs +0 -0
  94. {blockwatch_cli-0.16.3 → blockwatch_cli-0.16.4}/src/language_parsers/mdx.rs +0 -0
  95. {blockwatch_cli-0.16.3 → blockwatch_cli-0.16.4}/src/language_parsers/nix.rs +0 -0
  96. {blockwatch_cli-0.16.3 → blockwatch_cli-0.16.4}/src/language_parsers/ocaml.rs +0 -0
  97. {blockwatch_cli-0.16.3 → blockwatch_cli-0.16.4}/src/language_parsers/php.rs +0 -0
  98. {blockwatch_cli-0.16.3 → blockwatch_cli-0.16.4}/src/language_parsers/proto.rs +0 -0
  99. {blockwatch_cli-0.16.3 → blockwatch_cli-0.16.4}/src/language_parsers/python.rs +0 -0
  100. {blockwatch_cli-0.16.3 → blockwatch_cli-0.16.4}/src/language_parsers/ruby.rs +0 -0
  101. {blockwatch_cli-0.16.3 → blockwatch_cli-0.16.4}/src/language_parsers/scala.rs +0 -0
  102. {blockwatch_cli-0.16.3 → blockwatch_cli-0.16.4}/src/language_parsers/sql.rs +0 -0
  103. {blockwatch_cli-0.16.3 → blockwatch_cli-0.16.4}/src/language_parsers/starlark.rs +0 -0
  104. {blockwatch_cli-0.16.3 → blockwatch_cli-0.16.4}/src/language_parsers/toml.rs +0 -0
  105. {blockwatch_cli-0.16.3 → blockwatch_cli-0.16.4}/src/language_parsers/tsx.rs +0 -0
  106. {blockwatch_cli-0.16.3 → blockwatch_cli-0.16.4}/src/language_parsers/typescript.rs +0 -0
  107. {blockwatch_cli-0.16.3 → blockwatch_cli-0.16.4}/src/language_parsers/xml.rs +0 -0
  108. {blockwatch_cli-0.16.3 → blockwatch_cli-0.16.4}/src/language_parsers/yaml.rs +0 -0
  109. {blockwatch_cli-0.16.3 → blockwatch_cli-0.16.4}/src/lib.rs +0 -0
  110. {blockwatch_cli-0.16.3 → blockwatch_cli-0.16.4}/src/main.rs +0 -0
  111. {blockwatch_cli-0.16.3 → blockwatch_cli-0.16.4}/src/path_arguments.rs +0 -0
  112. {blockwatch_cli-0.16.3 → blockwatch_cli-0.16.4}/src/paths_glob.rs +0 -0
  113. {blockwatch_cli-0.16.3 → blockwatch_cli-0.16.4}/src/repo_path.rs +0 -0
  114. {blockwatch_cli-0.16.3 → blockwatch_cli-0.16.4}/src/report.rs +0 -0
  115. {blockwatch_cli-0.16.3 → blockwatch_cli-0.16.4}/src/sarif.rs +0 -0
  116. {blockwatch_cli-0.16.3 → blockwatch_cli-0.16.4}/src/scan.rs +0 -0
  117. {blockwatch_cli-0.16.3 → blockwatch_cli-0.16.4}/src/settings.rs +0 -0
  118. {blockwatch_cli-0.16.3 → blockwatch_cli-0.16.4}/src/symbol_path.rs +0 -0
  119. {blockwatch_cli-0.16.3 → blockwatch_cli-0.16.4}/src/symbols/mod.rs +0 -0
  120. {blockwatch_cli-0.16.3 → blockwatch_cli-0.16.4}/src/tag_parser.rs +0 -0
  121. {blockwatch_cli-0.16.3 → blockwatch_cli-0.16.4}/src/target_reference.rs +0 -0
  122. {blockwatch_cli-0.16.3 → blockwatch_cli-0.16.4}/src/validators/affects.rs +0 -0
  123. {blockwatch_cli-0.16.3 → blockwatch_cli-0.16.4}/src/validators/check_ai.rs +0 -0
  124. {blockwatch_cli-0.16.3 → blockwatch_cli-0.16.4}/src/validators/check_lua.rs +0 -0
  125. {blockwatch_cli-0.16.3 → blockwatch_cli-0.16.4}/src/validators/keep_sorted.rs +0 -0
  126. {blockwatch_cli-0.16.3 → blockwatch_cli-0.16.4}/src/validators/keep_unique.rs +0 -0
  127. {blockwatch_cli-0.16.3 → blockwatch_cli-0.16.4}/src/validators/line_count.rs +0 -0
  128. {blockwatch_cli-0.16.3 → blockwatch_cli-0.16.4}/src/validators/line_pattern.rs +0 -0
  129. {blockwatch_cli-0.16.3 → blockwatch_cli-0.16.4}/src/validators/mod.rs +0 -0
  130. {blockwatch_cli-0.16.3 → blockwatch_cli-0.16.4}/src/validators/same_as.rs +0 -0
  131. {blockwatch_cli-0.16.3 → blockwatch_cli-0.16.4}/src/violation_address.rs +0 -0
  132. {blockwatch_cli-0.16.3 → blockwatch_cli-0.16.4}/src/virtual_blocks.rs +0 -0
  133. {blockwatch_cli-0.16.3 → blockwatch_cli-0.16.4}/tests/affects.rs +0 -0
  134. {blockwatch_cli-0.16.3 → blockwatch_cli-0.16.4}/tests/check_ai.rs +0 -0
  135. {blockwatch_cli-0.16.3 → blockwatch_cli-0.16.4}/tests/check_lua.rs +0 -0
  136. {blockwatch_cli-0.16.3 → blockwatch_cli-0.16.4}/tests/common/empty.toml +0 -0
  137. {blockwatch_cli-0.16.3 → blockwatch_cli-0.16.4}/tests/common/mod.rs +0 -0
  138. {blockwatch_cli-0.16.3 → blockwatch_cli-0.16.4}/tests/config.rs +0 -0
  139. {blockwatch_cli-0.16.3 → blockwatch_cli-0.16.4}/tests/encoding.rs +0 -0
  140. {blockwatch_cli-0.16.3 → blockwatch_cli-0.16.4}/tests/explain.rs +0 -0
  141. {blockwatch_cli-0.16.3 → blockwatch_cli-0.16.4}/tests/general.rs +0 -0
  142. {blockwatch_cli-0.16.3 → blockwatch_cli-0.16.4}/tests/keep_sorted.rs +0 -0
  143. {blockwatch_cli-0.16.3 → blockwatch_cli-0.16.4}/tests/keep_unique.rs +0 -0
  144. {blockwatch_cli-0.16.3 → blockwatch_cli-0.16.4}/tests/line_count.rs +0 -0
  145. {blockwatch_cli-0.16.3 → blockwatch_cli-0.16.4}/tests/line_pattern.rs +0 -0
  146. {blockwatch_cli-0.16.3 → blockwatch_cli-0.16.4}/tests/list.rs +0 -0
  147. {blockwatch_cli-0.16.3 → blockwatch_cli-0.16.4}/tests/path_arguments.rs +0 -0
  148. {blockwatch_cli-0.16.3 → blockwatch_cli-0.16.4}/tests/repository_root.rs +0 -0
  149. {blockwatch_cli-0.16.3 → blockwatch_cli-0.16.4}/tests/same_as.rs +0 -0
  150. {blockwatch_cli-0.16.3 → blockwatch_cli-0.16.4}/tests/sarif.rs +0 -0
  151. {blockwatch_cli-0.16.3 → blockwatch_cli-0.16.4}/tests/skill.rs +0 -0
  152. {blockwatch_cli-0.16.3 → blockwatch_cli-0.16.4}/tests/suppressions.rs +0 -0
  153. {blockwatch_cli-0.16.3 → blockwatch_cli-0.16.4}/tests/testdata/affects/cross_file_source.rs +0 -0
  154. {blockwatch_cli-0.16.3 → blockwatch_cli-0.16.4}/tests/testdata/affects/cross_file_target.md +0 -0
  155. {blockwatch_cli-0.16.3 → blockwatch_cli-0.16.4}/tests/testdata/affects/custom_ext_source.javascript +0 -0
  156. {blockwatch_cli-0.16.3 → blockwatch_cli-0.16.4}/tests/testdata/affects/custom_ext_target.javascript +0 -0
  157. {blockwatch_cli-0.16.3 → blockwatch_cli-0.16.4}/tests/testdata/affects/dangling.md +0 -0
  158. {blockwatch_cli-0.16.3 → blockwatch_cli-0.16.4}/tests/testdata/affects/missing_symbol.rs +0 -0
  159. {blockwatch_cli-0.16.3 → blockwatch_cli-0.16.4}/tests/testdata/affects/more_added_than_deleted.py +0 -0
  160. {blockwatch_cli-0.16.3 → blockwatch_cli-0.16.4}/tests/testdata/affects/multiline_tag_source.rs +0 -0
  161. {blockwatch_cli-0.16.3 → blockwatch_cli-0.16.4}/tests/testdata/affects/multiline_tag_target.rs +0 -0
  162. {blockwatch_cli-0.16.3 → blockwatch_cli-0.16.4}/tests/testdata/affects/nested_mapping_source.rs +0 -0
  163. {blockwatch_cli-0.16.3 → blockwatch_cli-0.16.4}/tests/testdata/affects/nested_mapping_target.yaml +0 -0
  164. {blockwatch_cli-0.16.3 → blockwatch_cli-0.16.4}/tests/testdata/affects/sibling.md +0 -0
  165. {blockwatch_cli-0.16.3 → blockwatch_cli-0.16.4}/tests/testdata/affects/symbol_source.rs +0 -0
  166. {blockwatch_cli-0.16.3 → blockwatch_cli-0.16.4}/tests/testdata/affects/symbol_target.json +0 -0
  167. {blockwatch_cli-0.16.3 → blockwatch_cli-0.16.4}/tests/testdata/affects/table_source.rs +0 -0
  168. {blockwatch_cli-0.16.3 → blockwatch_cli-0.16.4}/tests/testdata/affects/table_target.toml +0 -0
  169. {blockwatch_cli-0.16.3 → blockwatch_cli-0.16.4}/tests/testdata/affects/tag_and_content_source.ts +0 -0
  170. {blockwatch_cli-0.16.3 → blockwatch_cli-0.16.4}/tests/testdata/affects/tag_and_content_target.ts +0 -0
  171. {blockwatch_cli-0.16.3 → blockwatch_cli-0.16.4}/tests/testdata/affects/whole_file_source.rs +0 -0
  172. {blockwatch_cli-0.16.3 → blockwatch_cli-0.16.4}/tests/testdata/affects/whole_file_target.json +0 -0
  173. {blockwatch_cli-0.16.3 → blockwatch_cli-0.16.4}/tests/testdata/check_ai/two_blocks.py +0 -0
  174. {blockwatch_cli-0.16.3 → blockwatch_cli-0.16.4}/tests/testdata/check_lua/affects.lua +0 -0
  175. {blockwatch_cli-0.16.3 → blockwatch_cli-0.16.4}/tests/testdata/check_lua/affects.py +0 -0
  176. {blockwatch_cli-0.16.3 → blockwatch_cli-0.16.4}/tests/testdata/check_lua/affects_drift.py +0 -0
  177. {blockwatch_cli-0.16.3 → blockwatch_cli-0.16.4}/tests/testdata/check_lua/blocking_io.lua +0 -0
  178. {blockwatch_cli-0.16.3 → blockwatch_cli-0.16.4}/tests/testdata/check_lua/blocking_io.py +0 -0
  179. {blockwatch_cli-0.16.3 → blockwatch_cli-0.16.4}/tests/testdata/check_lua/echo.lua +0 -0
  180. {blockwatch_cli-0.16.3 → blockwatch_cli-0.16.4}/tests/testdata/check_lua/fail.lua +0 -0
  181. {blockwatch_cli-0.16.3 → blockwatch_cli-0.16.4}/tests/testdata/check_lua/mode.py +0 -0
  182. {blockwatch_cli-0.16.3 → blockwatch_cli-0.16.4}/tests/testdata/check_lua/os.lua +0 -0
  183. {blockwatch_cli-0.16.3 → blockwatch_cli-0.16.4}/tests/testdata/check_lua/pathfmt/report_path.lua +0 -0
  184. {blockwatch_cli-0.16.3 → blockwatch_cli-0.16.4}/tests/testdata/check_lua/pathfmt/source.py +0 -0
  185. {blockwatch_cli-0.16.3 → blockwatch_cli-0.16.4}/tests/testdata/check_lua/pattern.py +0 -0
  186. {blockwatch_cli-0.16.3 → blockwatch_cli-0.16.4}/tests/testdata/check_lua/pattern_many_matches.py +0 -0
  187. {blockwatch_cli-0.16.3 → blockwatch_cli-0.16.4}/tests/testdata/check_lua/pattern_no_match.py +0 -0
  188. {blockwatch_cli-0.16.3 → blockwatch_cli-0.16.4}/tests/testdata/check_lua/success.lua +0 -0
  189. {blockwatch_cli-0.16.3 → blockwatch_cli-0.16.4}/tests/testdata/check_lua/success_and_failure.py +0 -0
  190. {blockwatch_cli-0.16.3 → blockwatch_cli-0.16.4}/tests/testdata/config/glob_target/config.toml +0 -0
  191. {blockwatch_cli-0.16.3 → blockwatch_cli-0.16.4}/tests/testdata/config/glob_target/package.json +0 -0
  192. {blockwatch_cli-0.16.3 → blockwatch_cli-0.16.4}/tests/testdata/config/glob_target/plugins/blue/package.json +0 -0
  193. {blockwatch_cli-0.16.3 → blockwatch_cli-0.16.4}/tests/testdata/config/glob_target/plugins/green/package.json +0 -0
  194. {blockwatch_cli-0.16.3 → blockwatch_cli-0.16.4}/tests/testdata/config/glob_target/plugins/red/package.json +0 -0
  195. {blockwatch_cli-0.16.3 → blockwatch_cli-0.16.4}/tests/testdata/explain/a.py +0 -0
  196. {blockwatch_cli-0.16.3 → blockwatch_cli-0.16.4}/tests/testdata/explain/check.lua +0 -0
  197. {blockwatch_cli-0.16.3 → blockwatch_cli-0.16.4}/tests/testdata/general/block_selection.py +0 -0
  198. {blockwatch_cli-0.16.3 → blockwatch_cli-0.16.4}/tests/testdata/general/custom_file_extension.javascript +0 -0
  199. {blockwatch_cli-0.16.3 → blockwatch_cli-0.16.4}/tests/testdata/general/custom_file_extension.python +0 -0
  200. {blockwatch_cli-0.16.3 → blockwatch_cli-0.16.4}/tests/testdata/general/disable_enable.py +0 -0
  201. {blockwatch_cli-0.16.3 → blockwatch_cli-0.16.4}/tests/testdata/general/paths/invalid.py +0 -0
  202. {blockwatch_cli-0.16.3 → blockwatch_cli-0.16.4}/tests/testdata/general/paths/subdir/nested_invalid.py +0 -0
  203. {blockwatch_cli-0.16.3 → blockwatch_cli-0.16.4}/tests/testdata/general/paths/valid.py +0 -0
  204. {blockwatch_cli-0.16.3 → blockwatch_cli-0.16.4}/tests/testdata/general/severity.py +0 -0
  205. {blockwatch_cli-0.16.3 → blockwatch_cli-0.16.4}/tests/testdata/hidden/.github/workflows/ci.yml +0 -0
  206. {blockwatch_cli-0.16.3 → blockwatch_cli-0.16.4}/tests/testdata/keep_sorted/orderings.py +0 -0
  207. {blockwatch_cli-0.16.3 → blockwatch_cli-0.16.4}/tests/testdata/keep_unique/basic_and_pattern.py +0 -0
  208. {blockwatch_cli-0.16.3 → blockwatch_cli-0.16.4}/tests/testdata/line_count/equality_and_greater_than.py +0 -0
  209. {blockwatch_cli-0.16.3 → blockwatch_cli-0.16.4}/tests/testdata/line_pattern/forbidden_text.py +0 -0
  210. {blockwatch_cli-0.16.3 → blockwatch_cli-0.16.4}/tests/testdata/line_pattern/hex_and_word_patterns.py +0 -0
  211. {blockwatch_cli-0.16.3 → blockwatch_cli-0.16.4}/tests/testdata/list/.hg/.gitkeep +0 -0
  212. {blockwatch_cli-0.16.3 → blockwatch_cli-0.16.4}/tests/testdata/list/a.py +0 -0
  213. {blockwatch_cli-0.16.3 → blockwatch_cli-0.16.4}/tests/testdata/list/b.py +0 -0
  214. {blockwatch_cli-0.16.3 → blockwatch_cli-0.16.4}/tests/testdata/positions/unicode_columns.py +0 -0
  215. {blockwatch_cli-0.16.3 → blockwatch_cli-0.16.4}/tests/testdata/same_as/custom_ext_source.javascript +0 -0
  216. {blockwatch_cli-0.16.3 → blockwatch_cli-0.16.4}/tests/testdata/same_as/custom_ext_target.javascript +0 -0
  217. {blockwatch_cli-0.16.3 → blockwatch_cli-0.16.4}/tests/testdata/same_as/package.json +0 -0
  218. {blockwatch_cli-0.16.3 → blockwatch_cli-0.16.4}/tests/testdata/same_as/paths/alpha/item.txt +0 -0
  219. {blockwatch_cli-0.16.3 → blockwatch_cli-0.16.4}/tests/testdata/same_as/paths/beta/item.txt +0 -0
  220. {blockwatch_cli-0.16.3 → blockwatch_cli-0.16.4}/tests/testdata/same_as/paths_and_block_source.md +0 -0
  221. {blockwatch_cli-0.16.3 → blockwatch_cli-0.16.4}/tests/testdata/same_as/paths_source.md +0 -0
  222. {blockwatch_cli-0.16.3 → blockwatch_cli-0.16.4}/tests/testdata/same_as/sibling.rs +0 -0
  223. {blockwatch_cli-0.16.3 → blockwatch_cli-0.16.4}/tests/testdata/same_as/source.rs +0 -0
  224. {blockwatch_cli-0.16.3 → blockwatch_cli-0.16.4}/tests/testdata/same_as/split_table_source.rs +0 -0
  225. {blockwatch_cli-0.16.3 → blockwatch_cli-0.16.4}/tests/testdata/same_as/split_table_target.toml +0 -0
  226. {blockwatch_cli-0.16.3 → blockwatch_cli-0.16.4}/tests/testdata/same_as/symbol_mismatch_source.rs +0 -0
  227. {blockwatch_cli-0.16.3 → blockwatch_cli-0.16.4}/tests/testdata/same_as/symbol_source.rs +0 -0
  228. {blockwatch_cli-0.16.3 → blockwatch_cli-0.16.4}/tests/testdata/same_as/target.md +0 -0
  229. {blockwatch_cli-0.16.3 → blockwatch_cli-0.16.4}/tests/testdata/same_as/whole_file_mismatch_source.rs +0 -0
  230. {blockwatch_cli-0.16.3 → blockwatch_cli-0.16.4}/tests/testdata/same_as/whole_file_source.rs +0 -0
  231. {blockwatch_cli-0.16.3 → blockwatch_cli-0.16.4}/tests/testdata/same_as/whole_file_target.json +0 -0
  232. {blockwatch_cli-0.16.3 → blockwatch_cli-0.16.4}/tests/testdata/sarif/advisory.py +0 -0
  233. {blockwatch_cli-0.16.3 → blockwatch_cli-0.16.4}/tests/testdata/sarif/clean.py +0 -0
  234. {blockwatch_cli-0.16.3 → blockwatch_cli-0.16.4}/tests/testdata/sarif/sorted.py +0 -0
  235. {blockwatch_cli-0.16.3 → blockwatch_cli-0.16.4}/tests/testdata/sarif/unnamed.py +0 -0
  236. {blockwatch_cli-0.16.3 → blockwatch_cli-0.16.4}/tests/testdata/suppressions/commit_msg.txt +0 -0
  237. {blockwatch_cli-0.16.3 → blockwatch_cli-0.16.4}/tests/testdata/suppressions/commit_msg_gone_a.txt +0 -0
  238. {blockwatch_cli-0.16.3 → blockwatch_cli-0.16.4}/tests/testdata/suppressions/commit_msg_gone_b.txt +0 -0
  239. {blockwatch_cli-0.16.3 → blockwatch_cli-0.16.4}/tests/testdata/suppressions/commit_msg_lowercase_trailer.txt +0 -0
  240. {blockwatch_cli-0.16.3 → blockwatch_cli-0.16.4}/tests/testdata/suppressions/commit_msg_malformed.txt +0 -0
  241. {blockwatch_cli-0.16.3 → blockwatch_cli-0.16.4}/tests/testdata/suppressions/commit_msg_with_noise.txt +0 -0
  242. {blockwatch_cli-0.16.3 → blockwatch_cli-0.16.4}/tests/testdata/suppressions/dangling.py +0 -0
  243. {blockwatch_cli-0.16.3 → blockwatch_cli-0.16.4}/tests/testdata/suppressions/sorted.py +0 -0
  244. {blockwatch_cli-0.16.3 → blockwatch_cli-0.16.4}/tests/testdata/suppressions/symbol.py +0 -0
  245. {blockwatch_cli-0.16.3 → blockwatch_cli-0.16.4}/tests/testdata/suppressions/symbol_target.json +0 -0
  246. {blockwatch_cli-0.16.3 → blockwatch_cli-0.16.4}/tests/testdata/suppressions/two_rules.py +0 -0
  247. {blockwatch_cli-0.16.3 → blockwatch_cli-0.16.4}/tests/testdata/suppressions/unnamed.py +0 -0
  248. {blockwatch_cli-0.16.3 → blockwatch_cli-0.16.4}/tests/testdata/symbol_references/bzl_source.rs +0 -0
  249. {blockwatch_cli-0.16.3 → blockwatch_cli-0.16.4}/tests/testdata/symbol_references/bzl_target.bzl +0 -0
  250. {blockwatch_cli-0.16.3 → blockwatch_cli-0.16.4}/tests/testdata/symbol_references/c_source.rs +0 -0
  251. {blockwatch_cli-0.16.3 → blockwatch_cli-0.16.4}/tests/testdata/symbol_references/c_target.c +0 -0
  252. {blockwatch_cli-0.16.3 → blockwatch_cli-0.16.4}/tests/testdata/symbol_references/cpp_source.rs +0 -0
  253. {blockwatch_cli-0.16.3 → blockwatch_cli-0.16.4}/tests/testdata/symbol_references/cpp_target.cpp +0 -0
  254. {blockwatch_cli-0.16.3 → blockwatch_cli-0.16.4}/tests/testdata/symbol_references/cs_source.rs +0 -0
  255. {blockwatch_cli-0.16.3 → blockwatch_cli-0.16.4}/tests/testdata/symbol_references/cs_target.cs +0 -0
  256. {blockwatch_cli-0.16.3 → blockwatch_cli-0.16.4}/tests/testdata/symbol_references/escapes_source.rs +0 -0
  257. {blockwatch_cli-0.16.3 → blockwatch_cli-0.16.4}/tests/testdata/symbol_references/escapes_target.json +0 -0
  258. {blockwatch_cli-0.16.3 → blockwatch_cli-0.16.4}/tests/testdata/symbol_references/filter_source.rs +0 -0
  259. {blockwatch_cli-0.16.3 → blockwatch_cli-0.16.4}/tests/testdata/symbol_references/filter_target.yaml +0 -0
  260. {blockwatch_cli-0.16.3 → blockwatch_cli-0.16.4}/tests/testdata/symbol_references/go_source.rs +0 -0
  261. {blockwatch_cli-0.16.3 → blockwatch_cli-0.16.4}/tests/testdata/symbol_references/go_target.go +0 -0
  262. {blockwatch_cli-0.16.3 → blockwatch_cli-0.16.4}/tests/testdata/symbol_references/h_source.rs +0 -0
  263. {blockwatch_cli-0.16.3 → blockwatch_cli-0.16.4}/tests/testdata/symbol_references/h_target.h +0 -0
  264. {blockwatch_cli-0.16.3 → blockwatch_cli-0.16.4}/tests/testdata/symbol_references/java_source.rs +0 -0
  265. {blockwatch_cli-0.16.3 → blockwatch_cli-0.16.4}/tests/testdata/symbol_references/java_target.java +0 -0
  266. {blockwatch_cli-0.16.3 → blockwatch_cli-0.16.4}/tests/testdata/symbol_references/js_source.rs +0 -0
  267. {blockwatch_cli-0.16.3 → blockwatch_cli-0.16.4}/tests/testdata/symbol_references/js_target.js +0 -0
  268. {blockwatch_cli-0.16.3 → blockwatch_cli-0.16.4}/tests/testdata/symbol_references/json_source.rs +0 -0
  269. {blockwatch_cli-0.16.3 → blockwatch_cli-0.16.4}/tests/testdata/symbol_references/json_target.json +0 -0
  270. {blockwatch_cli-0.16.3 → blockwatch_cli-0.16.4}/tests/testdata/symbol_references/jsonc_source.rs +0 -0
  271. {blockwatch_cli-0.16.3 → blockwatch_cli-0.16.4}/tests/testdata/symbol_references/jsonc_target.jsonc +0 -0
  272. {blockwatch_cli-0.16.3 → blockwatch_cli-0.16.4}/tests/testdata/symbol_references/markdown_source.rs +0 -0
  273. {blockwatch_cli-0.16.3 → blockwatch_cli-0.16.4}/tests/testdata/symbol_references/markdown_target.markdown +0 -0
  274. {blockwatch_cli-0.16.3 → blockwatch_cli-0.16.4}/tests/testdata/symbol_references/md_source.rs +0 -0
  275. {blockwatch_cli-0.16.3 → blockwatch_cli-0.16.4}/tests/testdata/symbol_references/md_target.md +0 -0
  276. {blockwatch_cli-0.16.3 → blockwatch_cli-0.16.4}/tests/testdata/symbol_references/mdx_source.rs +0 -0
  277. {blockwatch_cli-0.16.3 → blockwatch_cli-0.16.4}/tests/testdata/symbol_references/mdx_target.mdx +0 -0
  278. {blockwatch_cli-0.16.3 → blockwatch_cli-0.16.4}/tests/testdata/symbol_references/mixed_list_source.rs +0 -0
  279. {blockwatch_cli-0.16.3 → blockwatch_cli-0.16.4}/tests/testdata/symbol_references/mixed_list_target.json +0 -0
  280. {blockwatch_cli-0.16.3 → blockwatch_cli-0.16.4}/tests/testdata/symbol_references/py_source.rs +0 -0
  281. {blockwatch_cli-0.16.3 → blockwatch_cli-0.16.4}/tests/testdata/symbol_references/py_target.py +0 -0
  282. {blockwatch_cli-0.16.3 → blockwatch_cli-0.16.4}/tests/testdata/symbol_references/rs_source.rs +0 -0
  283. {blockwatch_cli-0.16.3 → blockwatch_cli-0.16.4}/tests/testdata/symbol_references/rs_target.rs +0 -0
  284. {blockwatch_cli-0.16.3 → blockwatch_cli-0.16.4}/tests/testdata/symbol_references/toml_source.rs +0 -0
  285. {blockwatch_cli-0.16.3 → blockwatch_cli-0.16.4}/tests/testdata/symbol_references/toml_target.toml +0 -0
  286. {blockwatch_cli-0.16.3 → blockwatch_cli-0.16.4}/tests/testdata/symbol_references/ts_source.rs +0 -0
  287. {blockwatch_cli-0.16.3 → blockwatch_cli-0.16.4}/tests/testdata/symbol_references/ts_target.ts +0 -0
  288. {blockwatch_cli-0.16.3 → blockwatch_cli-0.16.4}/tests/testdata/symbol_references/tsx_source.rs +0 -0
  289. {blockwatch_cli-0.16.3 → blockwatch_cli-0.16.4}/tests/testdata/symbol_references/tsx_target.tsx +0 -0
  290. {blockwatch_cli-0.16.3 → blockwatch_cli-0.16.4}/tests/testdata/symbol_references/yaml_source.rs +0 -0
  291. {blockwatch_cli-0.16.3 → blockwatch_cli-0.16.4}/tests/testdata/symbol_references/yaml_target.yaml +0 -0
  292. {blockwatch_cli-0.16.3 → blockwatch_cli-0.16.4}/tests/testdata/symbol_references/yml_source.rs +0 -0
  293. {blockwatch_cli-0.16.3 → blockwatch_cli-0.16.4}/tests/testdata/symbol_references/yml_target.yml +0 -0
  294. {blockwatch_cli-0.16.3 → blockwatch_cli-0.16.4}/tests/testdata/verbosity/affects/pair.py +0 -0
  295. {blockwatch_cli-0.16.3 → blockwatch_cli-0.16.4}/tests/testdata/verbosity/clean/counted.py +0 -0
  296. {blockwatch_cli-0.16.3 → blockwatch_cli-0.16.4}/tests/testdata/verbosity/clean/noop.py +0 -0
  297. {blockwatch_cli-0.16.3 → blockwatch_cli-0.16.4}/tests/testdata/verbosity/clean/notes.txt +0 -0
  298. {blockwatch_cli-0.16.3 → blockwatch_cli-0.16.4}/tests/testdata/verbosity/clean/sorted.py +0 -0
  299. {blockwatch_cli-0.16.3 → blockwatch_cli-0.16.4}/tests/testdata/verbosity/diff/two_blocks.py +0 -0
  300. {blockwatch_cli-0.16.3 → blockwatch_cli-0.16.4}/tests/testdata/verbosity/failing/unsorted.py +0 -0
  301. {blockwatch_cli-0.16.3 → blockwatch_cli-0.16.4}/tests/testdata/verbosity/mixed/both_kinds.py +0 -0
  302. {blockwatch_cli-0.16.3 → blockwatch_cli-0.16.4}/tests/verbosity.rs +0 -0
@@ -12,6 +12,26 @@ 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.4] - 2026-11-03
16
+
17
+ ### Added
18
+
19
+ - Symbols in Kotlin files (`.kt` and `.kts`). `Config.kt#/Config/MAX_RETRIES` points at a property of the class
20
+ `Config`, and `#/MAX_RETRIES` at one at the top of the file. Each type is a symbol, and so is each property,
21
+ constructor property, function, enum entry and nested type in it. A companion object's members sit under the class.
22
+ See [Kotlin](docs/symbols.md#kotlin).
23
+ - Symbols in Swift files. `Config.swift#/Config/maxRetries` points at a property of the type `Config`, and
24
+ `#/maxRetries` at one at the top of the file. Each type is a symbol, and so is each property, function, enum case and
25
+ nested type in it. An extension's members sit under the type it extends, and an enum case's value is its raw value.
26
+ See [Swift](docs/symbols.md#swift).
27
+
28
+ ### Fixed
29
+
30
+ - A Java text block with `\u` and a sign, such as `\u+041`, counted as the character, here `A`. Java rejects this
31
+ escape, so a path to the text block now stops the run.
32
+ - A Java string in `"` quotes with a line break in it counted as text. Java rejects it, so a path to it now stops the
33
+ run. Before, a string missing its closing quote took in the next line as its value.
34
+
15
35
  ## [0.16.3] - 2026-11-02
16
36
 
17
37
  ## [0.16.2] - 2026-10-30
@@ -274,7 +274,7 @@ checksum = "3ded4057c258ba199e2d26386d3af3780957ecaee6c4ef4041c6b4b8b97c0b06"
274
274
 
275
275
  [[package]]
276
276
  name = "blockwatch"
277
- version = "0.16.3"
277
+ version = "0.16.4"
278
278
  dependencies = [
279
279
  "anyhow",
280
280
  "assert-json-diff",
@@ -1,6 +1,6 @@
1
1
  [package]
2
2
  name = "blockwatch"
3
- version = "0.16.3"
3
+ version = "0.16.4"
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"
@@ -1,6 +1,6 @@
1
1
  Metadata-Version: 2.4
2
2
  Name: blockwatch-cli
3
- Version: 0.16.3
3
+ Version: 0.16.4
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
@@ -89,7 +89,7 @@ Two validators work across files:
89
89
  - `same-as` fails when a block and its target hold different values. It needs no diff.
90
90
 
91
91
  Both can point to a block, a whole file, a specific value in a file like `package.json#/version`, a section of a
92
- Markdown file, or a constant in a Go, C, C++, Python, Rust, TypeScript, JavaScript, Java or C# file (see
92
+ Markdown file, or a constant in a Go, C, C++, Python, Rust, TypeScript, JavaScript, Java, C#, Kotlin or Swift file (see
93
93
  [Symbols](docs/symbols.md)). The other validators check a single block on their own: the things you'd otherwise have to
94
94
  nitpick in code review.
95
95
 
@@ -219,7 +219,7 @@ exclusions, and custom extension mappings.
219
219
 
220
220
  ```yaml
221
221
  - repo: https://github.com/mennanov/blockwatch
222
- rev: v0.16.3 # Use latest release
222
+ rev: v0.16.4 # Use latest release
223
223
  hooks:
224
224
  - id: blockwatch
225
225
  ```
@@ -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.16.3 # Use latest release
22
+ rev: v0.16.4 # 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.16.3 # Use latest release
62
+ rev: v0.16.4 # 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.16.3",
561
- "semanticVersion": "0.16.3",
560
+ "version": "0.16.4",
561
+ "semanticVersion": "0.16.4",
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.16.3/docs/validators/keep-sorted.md"
568
+ "helpUri": "https://github.com/mennanov/blockwatch/blob/v0.16.4/docs/validators/keep-sorted.md"
569
569
  }
570
570
  ]
571
571
  }
@@ -39,6 +39,8 @@ declares, instead of tags in a comment.
39
39
  | JavaScript | `.js`, `.mjs`, `.cjs`, `.jsx` | [TypeScript and JavaScript](#typescript-and-javascript) |
40
40
  | Java | `.java` | [Java](#java) |
41
41
  | C# | `.cs` | [C#](#c) |
42
+ | Kotlin | `.kt`, `.kts` | [Kotlin](#kotlin) |
43
+ | Swift | `.swift` | [Swift](#swift) |
42
44
 
43
45
  <!-- </block> -->
44
46
 
@@ -249,8 +251,8 @@ Clone the repository.
249
251
 
250
252
  In a code file, each top-level name is a symbol: a constant, a variable, a type, a function or a macro. Its path is
251
253
  `#/NAME`.
252
- With `const MaxPorts = 8` in `consts.go`, `consts.go#/MaxPorts` points at `8`. In Java and C#, the members of a type
253
- are symbols too, under the type's name: `Config.java#/Config/MAX_PORTS`.
254
+ With `const MaxPorts = 8` in `consts.go`, `consts.go#/MaxPorts` points at `8`. In Java, C#, Kotlin and Swift, the
255
+ members of a type are symbols too, under the type's name: `Config.java#/Config/MAX_PORTS`.
254
256
 
255
257
  - **A value is the initializer as written.** blockwatch never works it out: `20 * 1024 * 1024` stays as it is, and so
256
258
  does `0x10`. Use `same-as-pattern` to take the part you need.
@@ -264,7 +266,7 @@ are symbols too, under the type's name: `Config.java#/Config/MAX_PORTS`.
264
266
  with a name from the text that the parser had to skip. Other names in the file still resolve. The message shows
265
267
  where the error is.
266
268
  - **A path to a string that blockwatch can't decode stops the run.** Other paths in the file still resolve.
267
- - **Members are not symbols yet**, such as a method or a field, except in Java and C#.
269
+ - **Members are not symbols yet**, such as a method or a field, except in Java, C#, Kotlin and Swift.
268
270
 
269
271
  <!-- </block> -->
270
272
 
@@ -595,6 +597,133 @@ public class Config
595
597
 
596
598
  <!-- </block> -->
597
599
 
600
+ ## Kotlin
601
+
602
+ <!-- <block name="kotlin-paths"> -->
603
+
604
+ ```kotlin
605
+ const val MAX_RETRIES = 20 * 1024
606
+
607
+ data class Config(val timeout: Int = 30, val name: String) {
608
+ @JvmField
609
+ val url = "https://example.com"
610
+
611
+ fun run() {}
612
+ fun run(times: Int) {}
613
+
614
+ companion object {
615
+ const val ORIGIN = 0
616
+ }
617
+
618
+ enum class Mode { RED, GREEN }
619
+ }
620
+ ```
621
+
622
+ | Path | Points at |
623
+ |-----------------------|--------------------------------------------|
624
+ | `#/MAX_RETRIES` | `20 * 1024` |
625
+ | `#/Config` | the whole class |
626
+ | `#/Config/timeout` | `30` |
627
+ | `#/Config/name` | `val name: String`, as it has no default |
628
+ | `#/Config/url` | `https://example.com` |
629
+ | `#/Config/run` | a violation, as `run` is defined twice |
630
+ | `#/Config/ORIGIN` | `0` |
631
+ | `#/Config/Mode/GREEN` | `GREEN`, as it has no value |
632
+
633
+ - **Each top-level property, function, type and type alias is a symbol, and so is each member of a type**: a property,
634
+ a function, an enum entry, or a nested class, interface or object. A path goes from the top-level type down:
635
+ `#/Config/Mode/GREEN`.
636
+ - **A constructor parameter with `val` or `var` is a symbol.** Its value is its default. A parameter without `val` or
637
+ `var` is not a symbol.
638
+ - **A companion object's members sit under the class**, as code reads them: `#/Config/ORIGIN`. A companion with a
639
+ name works the same way: `companion object Builder` still gives `#/Config/ORIGIN`.
640
+ - **Overloads are defined twice.** So are a property and a function with one name, and two extension functions with
641
+ one name, such as `fun Foo.toDto()` and `fun Bar.toDto()`. Wrap the one you mean in a block instead.
642
+ - **A property's value is its initializer, or the `v` of `get() = v`.** A property with `by`, such as
643
+ `by lazy { 3 }`, has no value, and neither has one whose getter has a block body.
644
+ - **A name in backticks loses them.** `` fun `parses empty input`() `` in `Config` is
645
+ `#/Config/parses empty input`.
646
+ - **Annotations are part of a definition. KDoc is not.** One case is left out: at the top of a file, an annotation with
647
+ arguments on its own line, before a `fun` or `val` with no other modifier. The parser reads it as a separate
648
+ expression.
649
+ - **Constructors, `init` blocks, the companion object itself, local declarations, and the members in the body of an
650
+ enum entry are not symbols.** In a `.kts` script, the top-level properties, functions and types are symbols. Calls
651
+ such as `plugins { ... }` and everything inside them are not.
652
+ - **Strings follow Kotlin's escapes.** `"caf\u00e9"` is `café`. A raw string (`"""..."""`) has no escapes, and each line
653
+ end in it is a line feed. A string with a template, such as `"v$major"` or `"${a + b}"`, stays as written, and so
654
+ does a character such as `'a'`. A path to a string that Kotlin rejects stops the run, such as `"\q"`.
655
+ - **A syntax error stops the run for the member that holds it, and for each type around that member.** The other
656
+ members still resolve. The parser doesn't read some newer syntax, such as context parameters and `$$"..."` strings.
657
+ It also fails on a class body on one line with a property in it, such as `class A { val x = 1 }`.
658
+
659
+ <!-- </block> -->
660
+
661
+ ## Swift
662
+
663
+ <!-- <block name="swift-paths"> -->
664
+
665
+ ```swift
666
+ public let maxRetries = 20 * 1024
667
+
668
+ struct Config {
669
+ static let timeout = 30
670
+ var name: String
671
+ var ready: Bool { timeout > 0 }
672
+
673
+ func run() {}
674
+ func run(times: Int) {}
675
+
676
+ enum Mode: String {
677
+ case red = "r", green
678
+ }
679
+ }
680
+
681
+ extension Config {
682
+ static let url = "https://example.com"
683
+ }
684
+ ```
685
+
686
+ | Path | Points at |
687
+ |-----------------------|--------------------------------------------|
688
+ | `#/maxRetries` | `20 * 1024` |
689
+ | `#/Config` | the whole struct, without its extension |
690
+ | `#/Config/timeout` | `30` |
691
+ | `#/Config/name` | `var name: String`, as it has no value |
692
+ | `#/Config/ready` | `timeout > 0` |
693
+ | `#/Config/run` | a violation, as `run` is defined twice |
694
+ | `#/Config/Mode/red` | `r` |
695
+ | `#/Config/Mode/green` | `green`, as its raw value is implicit |
696
+ | `#/Config/url` | `https://example.com` |
697
+
698
+ - **Each top-level property, function, type, type alias and macro is a symbol, and so is each member of a type**: a
699
+ property, a function, an enum case, an associated type or a nested type. A protocol is a type, and its requirements
700
+ are members. A path goes from the top-level type down: `#/Config/Mode/red`.
701
+ - **An extension's members sit under the type it extends**, as code reads them: `#/Config/url`. The type can come from
702
+ another file too, so `String+Format.swift` can have `#/String/trimmed`. The path follows the type's name as written:
703
+ `extension Outer.Inner` gives `#/Outer/Inner/...`, and `extension Swift.String` gives `#/Swift/String/...`. An
704
+ extension of a type without a name, such as `extension [Int]`, has no symbols.
705
+ - **Overloads are defined twice.** So are a property and a function with one name, copies of a name in `#if` and
706
+ `#else`, and a protocol requirement and its default in an extension. Wrap the one you mean in a block instead.
707
+ - **A property's value is its initializer, or the `v` of `{ v }` or `{ return v }`.** A computed property with `get`
708
+ or `set`, with several statements, or with one statement that is not an expression, such as a `for` loop, has no
709
+ value. An enum case's value is its raw value, the `v` of `= v`. A case
710
+ without one has no value, even when Swift gives it one.
711
+ - **In `let a = 1, b = 2` and `case a = 1, b`, each name covers only its own part.** The first part also covers the
712
+ attributes, the modifiers and `let`, `var` or `case`: `#/a` is `let a = 1`, and `#/b` is `b = 2`.
713
+ - **A name in backticks loses them.** Attributes are part of a definition. Doc comments are not.
714
+ - **`init`, `deinit`, `subscript`, operators, precedence groups, extensions themselves, local declarations and
715
+ top-level statements are not symbols.**
716
+ - **Strings follow Swift's escapes.** `"caf\u{e9}"` is `café`. A raw string, such as `#"C:\new"#`, reads only the
717
+ escapes with as many `#` as its quotes, such as `\#n`. A multi-line string loses the white space before its closing
718
+ quotes on each line, and each line end in it is a line feed. A string with an interpolation, such as `"v\(major)"`,
719
+ stays as written, and so does a regex. A path to a string that Swift rejects stops the run, such as `"\u{D800}"`.
720
+ - **A syntax error stops the run for the member that holds it, and for each type around that member.** The other
721
+ members still resolve. An extension is not part of the type it extends, so an error in an extension's member leaves
722
+ the type readable. The parser fails on an empty tuple passed to a function, as in `f(())`, so a function with one in
723
+ its body stops the run too.
724
+
725
+ <!-- </block> -->
726
+
598
727
  ---
599
728
 
600
729
  [← Return to README](../README.md)
@@ -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.16.3'],
9
+ install_requires=['blockwatch-cli==0.16.4'],
10
10
  # </block>
11
11
  # Without it, setuptools takes the directories under src/ for Python packages.
12
12
  packages=[],
@@ -39,7 +39,13 @@ impl SymbolsParser for CSymbolsParser {
39
39
  .parse(fixed_directive_line_ends(source).as_ref(), None)
40
40
  .context("failed to parse syntax tree")?;
41
41
  let definitions = definitions(tree.root_node(), source, &mut self.parser)?;
42
- Ok(code::symbols(&tree, source, &definitions, &decode_string))
42
+ Ok(code::symbols(
43
+ &tree,
44
+ source,
45
+ &definitions,
46
+ &decode_string,
47
+ None,
48
+ ))
43
49
  }
44
50
  }
45
51
 
@@ -26,15 +26,7 @@ impl CodeLanguage for CSharp {
26
26
  /// document order. A type comes before its members. The names of the namespaces a type sits
27
27
  /// in are its first parents.
28
28
  fn definitions<'tree>(&self, root: Node<'tree>, _source: &str) -> Vec<Definition<'tree>> {
29
- let mut definitions = Vec::new();
30
- // The walk keeps its own stack, as deeply nested types could overflow the call stack.
31
- let mut bodies = vec![(root, Vec::new())];
32
- while let Some((body, parents)) = bodies.pop() {
33
- push_members(body, parents, &mut definitions, &mut bodies);
34
- }
35
- // The walk reads all of a body before the bodies in it.
36
- definitions.sort_by_key(|definition| definition.range.start);
37
- definitions
29
+ code::nested_definitions(root, push_members)
38
30
  }
39
31
 
40
32
  /// Decodes a C# string, or an interpolated string without a hole. Returns `None` for any other
@@ -293,7 +285,7 @@ fn property_value(property: Node) -> Option<Node> {
293
285
  let value = property.child_by_field_name("value")?;
294
286
  // Code reads a property as it reads a field, so `X => v` has the value `v`.
295
287
  if value.kind() == "arrow_expression_clause" {
296
- value_after(value, "=>")
288
+ code::value_after(value, "=>")
297
289
  } else {
298
290
  Some(value)
299
291
  }
@@ -333,21 +325,11 @@ fn push_fields<'tree>(
333
325
  parents.to_vec(),
334
326
  name,
335
327
  range,
336
- value_after(declarator, "="),
328
+ code::value_after(declarator, "="),
337
329
  ));
338
330
  }
339
331
  }
340
332
 
341
- /// The value that follows the `token` in `node`, such as the `5` after the `=` in `x = 5`.
342
- /// Returns `None` when `node` has no `token`.
343
- fn value_after<'tree>(node: Node<'tree>, token: &str) -> Option<Node<'tree>> {
344
- // The grammar gives the value no field name. A comment after the token is not the value.
345
- let mut cursor = node.walk();
346
- node.children(&mut cursor)
347
- .skip_while(|child| child.kind() != token)
348
- .find(|child| child.is_named() && !child.is_extra())
349
- }
350
-
351
333
  /// The definition of `member`, a declaration with one name, in the namespace or type at
352
334
  /// `parents`. It covers the whole declaration and has the initializer `value`, if any. Returns
353
335
  /// `None` if the parser found no name.
@@ -25,23 +25,16 @@ impl CodeLanguage for Java {
25
25
  /// The types under `root`, the root of a Java file's syntax tree, and their members, in
26
26
  /// document order. A type comes before its members.
27
27
  fn definitions<'tree>(&self, root: Node<'tree>, _source: &str) -> Vec<Definition<'tree>> {
28
- let mut definitions = Vec::new();
29
- // The walk keeps its own stack, as deeply nested types could overflow the call stack.
30
28
  // A compact source file holds methods and fields at its top level, as a class body does.
31
- let mut bodies = vec![(root, Vec::new())];
32
- while let Some((body, parents)) = bodies.pop() {
33
- push_members(body, &parents, &mut definitions, &mut bodies);
34
- }
35
- // The walk reads all of a body before the bodies of the types in it.
36
- definitions.sort_by_key(|definition| definition.range.start);
37
- definitions
29
+ code::nested_definitions(root, push_members)
38
30
  }
39
31
 
40
32
  /// Decodes a Java string or text block. Returns `None` for any other node.
41
33
  ///
42
34
  /// # Errors
43
- /// Returns an error if an escape is not one of Java's, if the string holds `\u005c`, or if the
44
- /// string holds half of a character.
35
+ /// Returns an error if an escape is not one of Java's, if the string holds `\u005c`, if a
36
+ /// string that is not a text block holds a line break, or if the string holds half of a
37
+ /// character.
45
38
  fn decode_string(&self, node: &Node, source: &str) -> anyhow::Result<Option<String>> {
46
39
  if node.kind() != "string_literal" {
47
40
  return Ok(None);
@@ -51,11 +44,18 @@ impl CodeLanguage for Java {
51
44
  Some(block) => {
52
45
  text_block_content(block.strip_suffix(TEXT_BLOCK_QUOTES).unwrap_or(block))
53
46
  }
54
- None => literal
55
- .strip_prefix('"')
56
- .and_then(|content| content.strip_suffix('"'))
57
- .unwrap_or(literal)
58
- .to_string(),
47
+ None => {
48
+ let content = literal
49
+ .strip_prefix('"')
50
+ .and_then(|content| content.strip_suffix('"'))
51
+ .unwrap_or(literal);
52
+ // The grammar lets a string run on to the next line, so a string missing its
53
+ // closing quote takes in the next line too.
54
+ if content.contains(['\r', '\n']) {
55
+ bail!("Java allows a line break only in a text block");
56
+ }
57
+ content.to_string()
58
+ }
59
59
  };
60
60
  code::decode_utf16(&content, push_escape).map(Some)
61
61
  }
@@ -147,12 +147,11 @@ fn octal_digits(first: char, characters: &mut Peekable<Chars>) -> String {
147
147
  /// `u`. For `\u00e9`, it is the unit of `é`.
148
148
  ///
149
149
  /// # Errors
150
- /// Returns an error if the next 4 characters don't read as a hex number, or if the escape is
151
- /// `\u005c`.
150
+ /// Returns an error if the next 4 characters are not hex digits, or if the escape is `\u005c`.
152
151
  fn unicode_unit(characters: &mut Peekable<Chars>) -> anyhow::Result<u16> {
153
152
  let digits: String = characters.by_ref().take(4).collect();
154
- let unit = u16::from_str_radix(&digits, 16)
155
- .map_err(|_| anyhow!("`\\u{digits}` is not an escape in a Java string"))?;
153
+ let unit = code::utf16_unit(&digits)
154
+ .ok_or_else(|| anyhow!("`\\u{digits}` is not an escape in a Java string"))?;
156
155
  // Java turns `\u005c` into a backslash before it reads the other escapes, so `\u005cn` is
157
156
  // a line feed, which one pass over the escapes can't give.
158
157
  if unit == u16::from(b'\\') {
@@ -166,7 +165,7 @@ fn unicode_unit(characters: &mut Peekable<Chars>) -> anyhow::Result<u16> {
166
165
  /// each type in `body` to `bodies`, with its own parents.
167
166
  fn push_members<'tree>(
168
167
  body: Node<'tree>,
169
- parents: &[Node<'tree>],
168
+ parents: Vec<Node<'tree>>,
170
169
  definitions: &mut Vec<Definition<'tree>>,
171
170
  bodies: &mut Vec<(Node<'tree>, Vec<Node<'tree>>)>,
172
171
  ) {
@@ -177,10 +176,10 @@ fn push_members<'tree>(
177
176
  // A compact source file declares its fields as local variables, and an interface its
178
177
  // constants as constants.
179
178
  "field_declaration" | "local_variable_declaration" | "constant_declaration" => {
180
- push_fields(member, parents, definitions);
179
+ push_fields(member, &parents, definitions);
181
180
  }
182
181
  // The members of an enum that come after its constants.
183
- "enum_body_declarations" => bodies.push((member, parents.to_vec())),
182
+ "enum_body_declarations" => bodies.push((member, parents.clone())),
184
183
  "class_declaration"
185
184
  | "interface_declaration"
186
185
  | "enum_declaration"
@@ -196,7 +195,7 @@ fn push_members<'tree>(
196
195
  None,
197
196
  ));
198
197
  if let Some(body) = member.child_by_field_name("body") {
199
- bodies.push((body, [parents, &[name]].concat()));
198
+ bodies.push((body, [&parents[..], &[name]].concat()));
200
199
  }
201
200
  }
202
201
  // The body of an enum constant is a class without a name, so its members are not
@@ -622,6 +621,8 @@ class Helper {}
622
621
  static final String HEX = "\x41";
623
622
  static final String HALF = "\uD800";
624
623
  static final String BACKSLASH = "\u005cn";
624
+ static final String SIGN = """
625
+ \u+041""";
625
626
  static final String FINE = "ok";
626
627
  }
627
628
  "#;
@@ -650,6 +651,28 @@ class Helper {}
650
651
  r"Java turns `\u005c` into a backslash before it reads the other escapes"
651
652
  )
652
653
  );
654
+ // The grammar rejects this escape in a string, but not in a text block.
655
+ assert_eq!(
656
+ unresolved(&java(source)?, source, "/Broken/SIGN")?,
657
+ decode_error(5, 32, r"`\u+041` is not an escape in a Java string")
658
+ );
659
+ Ok(())
660
+ }
661
+
662
+ #[test]
663
+ fn line_break_in_a_string_parse_symbols_makes_the_name_unreadable() -> anyhow::Result<()> {
664
+ // Java reads a carriage return alone as a line end too.
665
+ let source = "class A {\n static final String LF = \"a\nb\";\n static final String CR = \"a\rb\";\n}\n";
666
+
667
+ assert_eq!(values(&java(source)?, source).len(), 1, "only the class");
668
+ assert_eq!(
669
+ unresolved(&java(source)?, source, "/A/LF")?,
670
+ decode_error(2, 30, "Java allows a line break only in a text block")
671
+ );
672
+ assert_eq!(
673
+ unresolved(&java(source)?, source, "/A/CR")?,
674
+ decode_error(4, 30, "Java allows a line break only in a text block")
675
+ );
653
676
  Ok(())
654
677
  }
655
678