Conversation
`GO_PACKAGE_RE` is anchored at the start of the snippet, so a go block that opens with a comment — a file-name comment or a `//go:build` constraint — is treated as having no package clause. mdsf then prepends its temporary package and hands gofmt two package clauses, which fails with «expected declaration, found 'package'». The failure is quiet: mdsf prints `error running gofmt` and exits zero, so the block is not formatted and not reported as unformatted either. Anchor the pattern per line. Co-Authored-By: Claude Opus 5 (1M context) <noreply@anthropic.com>
| // TODO: check for multiline comments | ||
| pub static GO_PACKAGE_RE: std::sync::LazyLock<Regex> = | ||
| std::sync::LazyLock::new(|| Regex::new(r"^\s*package\s+\w").unwrap()); | ||
| std::sync::LazyLock::new(|| Regex::new(r"(?m)^\s*package\s+\w").unwrap()); |
There was a problem hiding this comment.
This enable multine matching, won't this break some use cases.
package is a reserved word in Go, so it sounds safe
But you may something odd like this snippet without a package
/*
I like my
package manager
*/
const foo = 1But I feel like there is no better solution without dealing with complicated regexp to remove comments
There was a problem hiding this comment.
Thanks, that example is a real hole and it pushed the fix to the right place.
Dropped the (?m) and matched Go's own rule instead: the package clause is the first token that is neither whitespace nor a comment. has_go_package skips leading // and /* */ and applies the existing anchored pattern to the remainder, so your snippet stays without a package clause and still gets the temporary one. No comment-removing regex needed, and the TODO: check for multiline comments above GO_PACKAGE_RE is gone with it.
Both directions are covered in a new test_has_go_package module, your snippet included.
A package clause is the first token of a Go file that is neither whitespace nor a comment. Match that rule directly instead of widening the anchored pattern to every line, so a block comment containing a line that starts with `package` is not mistaken for a package clause. Co-Authored-By: Claude Opus 5 (1M context) <noreply@anthropic.com>
There was a problem hiding this comment.
I feel like this file is out the scope of this PR
There was a problem hiding this comment.
You are right, and it was not mine to add: those language-table entries came from this repo's own codegen.yml auto-committing chore: updated generated code when I pushed the branch to my fork. Reverted the file to main, so the diff here is now just parser/mod.rs.
Heads up that it may reappear if that workflow fires on my fork again — I could not disable it on my side. Say the word if you would rather I keep the regenerated table in.
The language table entries came from the repo's own codegen workflow auto-committing on push, not from this fix; they belong to a codegen run on main, not to a PR about the Go package clause.
Problem
GO_PACKAGE_REis anchored at the start of the snippet, not per line. A go block that opens with a comment therefore looks like a snippet without a package clause, and mdsf prepends its temporary package:gofmt then sees two package clauses and fails with
expected declaration, found 'package'. Sinceerror running gofmtexits zero, the block is neither formatted nor reported as unformatted — it just silently drops out of the check. Both a file-name comment and a//go:buildconstraint hit this, and both are common in documentation.Change
A package clause is the first token of a Go file that is neither whitespace nor a comment, so
has_go_packageskips leading//and/* */comments and applies the existing anchored pattern to the remainder.GO_PACKAGE_REkeeps its original semantics, and theTODO: check for multiline commentsabove it is resolved: a block comment containing a line that starts withpackageis not mistaken for a package clause.Checks
cargo test -p mdsf --lib parserpasses, with a newtest_has_go_packagemodule covering both directions (leading file-name comment,//go:build, a block comment before a real package clause, and the same block comment without one).cargo clippy --all-targetsis clean. On a corpus of Go-heavy markdown, the block above goes fromerror running gofmtto being formatted normally.