Skip to content

Read the go.mod module directive through go_mod_edit and delete the crawler's unused parse_go_mod_module #781

Description

[agent] Filed by the scheduled architecture audit routine (ecosystems and formats). Register: discussion #560 register.

Kind: refactor. Source: review Part 5.4 ("Go") and Part 6.4 (manifest table), register E19 (Go half).

Problem

The go.mod module directive has two hand-written readers (rows 1 and 2 below), and neither uses the directive walker that go_mod_edit already shares with the hosted rewriter and VEX discovery. Verified on 045d7ec:

Reader Production callers Grammar
crawlers/go_crawler.rs parse_go_mod_module none. grep -rnw over the workspace, including socket-patch-node, finds it only in its own unit tests and tests/crawler_go_e2e.rs. Its last caller went away before 2463257. first whitespace token; no BOM handling; no path-safety check
vex/product.rs parse_go_mod VEX --product auto-detection (the PRODUCT_MANIFESTS probe at product.rs#L83) strips a BOM; rejects module foo bar; runs is_safe_multi_segment
go_mod_edit for_each_directive_body / directive_body,`` with normalize_for_read require and replace for hosted, vendored, agent apply and VEX single-line and keyword ( … ) block forms, quoted tokens, any whitespace

They have drifted, proven by execution. Go accepts the block form of the directive: with go.mod = module (⏎\texample.com/blk⏎)⏎⏎go 1.21, go 1.24.7 list -m prints example.com/blk. A unit probe on the same text, run twice on 045d7ec (not committed), got:

  • product::parse_go_mod → Some("pkg:golang/(")
  • go_crawler::parse_go_mod_module → Some("(")
  • control module example.com/m → both example.com/m

go_mod_edit's walker already handles the block form, because it is the same rule it uses for require ( … ).

Symptoms and impact

I found no open issue for this. A block-form module directive is rare, so the user-visible risk is low (a wrong --product purl on a valid project). The structural cost is a dead public function with two test files pinning it, and a third copy of go.mod lexing that will drift again whenever the shared walker changes.

Proposed change

  1. Add go_mod_edit::module_path(text: &str) -> Option<String> built on normalize_for_read + for_each_directive_body(text, "module", …): the first body's first token, unquoted, rejected when empty or when is_safe_multi_segment fails.
  2. Make vex/product.rs parse_go_mod call it and keep only the pkg:golang/<module> formatting.
  3. Delete crawlers::go_crawler::parse_go_mod_module and its tests. Move the cases worth keeping (quoted path, module "", trailing comment, modulepath = x, module foo bar) to go_mod_edit's unit tests, and drop the parse_go_mod_module import from tests/crawler_go_e2e.rs.

Size and scope

vendor/go_mod_edit.rs (+15), vex/product.rs (−15), crawlers/go_crawler.rs (−45 prod, −35 test), tests/crawler_go_e2e.rs (−~30). Roughly −45 production lines net. Out of scope: moving go_mod_edit into formats/ (E20; #631 does this for go_sum_edit), and the other manifest probes in product.rs (E38).

Acceptance criteria

  • parse_go_mod_module no longer exists. grep -rn 'strip_prefix("module")' crates finds nothing outside tests.
  • New unit tests for module_path: single-line, quoted, trailing // comment, BOM, block form module ( … ), empty module "", module foo bar (→ None), modulepath = x (→ None), unsafe segments (→ None).
  • A vex/product.rs test: a block-form go.mod yields pkg:golang/example.com/blk.
  • cargo test -p socket-patch-core (including crawler_go_e2e) and the vex product tests stay green.

Dependencies

None; it can start now. If #631 lands first and moves the go codecs into formats/golang/, put module_path next to the go.mod reader wherever it lives then.

Activity

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Metadata

Metadata

Assignees

No one assigned

    Labels

    agent:claimedagent:triagedarch-auditFiled by a scheduled architecture audit routine (see the architecture review discussion)pm:goGo modulespriority:p2refactorStructural change: duplicated code or logic, missing abstraction, layering, dead code

    Type

    No type

    Projects

    No projects

      Milestone

      No milestone

      Relationships

      None yet

      Development

      No branches or pull requests

      Issue actions