Conversation
There was a problem hiding this comment.
Pull request overview
This PR is a significant parser/AST refactor and documentation expansion for attribs, adding richer source-span error reporting, new tag options (required/disabled/positional), and an “ignore unknown attributes” mode across the public API and debug tooling.
Changes:
- Refactors
parser.Parseto return a top-level AST node withSourceSpan-based errors and adds typed value helpers (AsBool/AsInt/...), token helpers, and matcher/item utilities. - Extends struct tag parsing to support
required,disabled, and positional arguments (pos=N), and threadsignoreUnknownthroughDefinition.ParseandDebug. - Rewrites/expands README and adds extensive new unit tests across parser, lexer, and tag parsing.
Reviewed changes
Copilot reviewed 21 out of 22 changed files in this pull request and generated 6 comments.
Show a summary per file
| File | Description |
|---|---|
attr.go |
Updates reflection-based setter to consume new AST shape and adds positional argument assignment. |
debug.go |
Threads ignoreUnknown through debug parsing. |
definition.go |
Changes public Parse signature to include ignoreUnknown and adapts to new parser return type. |
definition_test.go |
Updates tests for new Parse signature. |
example/example.go |
Updates example to pass ignoreUnknown and adds an extra tag attribute. |
go.mod |
Updates Go version directive and test dependencies. |
go.sum |
Records updated dependency checksums. |
README.md |
Major documentation rewrite with expanded examples and API details. |
tag.go |
Refactors struct-tag parsing; adds required/positional support and validation. |
tag_test.go |
Adds unit tests for new tag parsing behavior. |
parser/attribute.go |
Changes AST representation (Object/Array as *Attributes) and updates Build/PrepareAny. |
parser/errors.go |
Moves parse errors to span-based reporting and adds matcher-related sentinel errors. |
parser/item.go |
Adds ParserItem with rollback support for matcher/parser helpers. |
parser/lexer.go |
Adds snapshot/rollback support and spans; changes lexer input handling. |
parser/lexer_test.go |
Expands lexer tests for spans, rollback, and edge cases. |
parser/matcher.go |
Adds matcher helpers used by parser/item infrastructure and tests. |
parser/parser.go |
Rewrites parser around the new AST model, positional args, and better comma/closure handling. |
parser/parser_test.go |
Large expansion of parser/value/token/span/matcher tests. |
parser/span.go |
Introduces SourceSpan utilities. |
parser/strings.go |
Adds identifier validation helper used by tag parsing. |
parser/token.go |
Adds helper methods on Token (error check, OneOf, etc.). |
parser/value.go |
Adds typed accessors/converters and span-aware errors. |
Comments suppressed due to low confidence (1)
tag.go:101
- parseAttribsTagDisabled is currently unused in the repo (no call sites found). If it’s not needed, consider removing it to reduce maintenance surface; otherwise add/retain a call site or a test that justifies keeping it.
func parseAttribsTagDisabled(tag string) (result bool, _ error) {
parsed, err := parser.Parse(strings.NewReader(tag))
if err != nil {
return result, err
}
if parsed.Object == nil {
return result, nil
}
for _, attr := range parsed.Object.Attributes {
switch attr.Name {
case "disabled":
if result, err = attr.Value.AsBool(); err != nil {
return result, fmt.Errorf("%w: disabled not boolean", err)
}
default:
continue
}
}
return result, nil
}
💡 Add Copilot custom instructions for smarter, more guided reviews. Learn how to get started.
| return fmt.Sprintf("[span: %v] %v", p.span, p.message) | ||
| } | ||
|
|
||
| func (p parseError) Position() int { |
Comment on lines
+36
to
+60
| // Rollback to given snapshot | ||
| func (l *lexer) Rollback(to *Snapshot) error { | ||
| if to.pos > l.pos { | ||
| return io.EOF | ||
| } | ||
| if to.pos == l.pos { | ||
| return nil | ||
| } | ||
| l.reader = bufio.NewReader(strings.NewReader(l.content)) | ||
| // to.pos may exceed len(content) by one when an identifier/number read | ||
| // consumed EOF and incremented l.pos past the end of the string. Clamp | ||
| // the discard amount so that bufio.Discard does not hit EOF mid-stream. | ||
| discardTo := to.pos | ||
| if discardTo > len(l.content) { | ||
| discardTo = len(l.content) | ||
| } | ||
| disc, err := l.reader.Discard(discardTo) | ||
| if err != nil { | ||
| return err | ||
| } | ||
| if disc != discardTo { | ||
| return fmt.Errorf("expected to discard: %d but %d", discardTo, disc) | ||
| } | ||
| l.pos = to.pos | ||
|
|
| go get github.com/phonkee/attribs | ||
| ``` | ||
|
|
||
| Requires **Go 1.21+** (uses generics). |
Comment on lines
+30
to
+37
| case "disabled": | ||
| if result.Disabled, err = attr.Value.AsBool(); err != nil { | ||
| return result, fmt.Errorf("%w: disabled not boolean", err) | ||
| } | ||
| case "required": | ||
| if result.Required, err = attr.Value.AsBool(); err != nil { | ||
| return result, fmt.Errorf("%w: required not boolean", ErrInvalidTag) | ||
| } |
Comment on lines
+444
to
+454
| positionalIndex := 0 | ||
| for _, att := range parsed.Object.Attributes { | ||
| var prop *attr | ||
| if att.Name == "" { | ||
| // Positional argument: find the field declared with pos=positionalIndex. | ||
| for _, p := range a.Properties { | ||
| if p.IsPositional && p.Position == positionalIndex { | ||
| prop = p | ||
| break | ||
| } | ||
| } |
Comment on lines
11
to
20
| func newLexer(reader io.Reader) *lexer { | ||
| all, err := io.ReadAll(reader) // read all to get correct EOF position | ||
| if err != nil { | ||
| panic(err) | ||
| } | ||
| stringContent := string(all) | ||
| return &lexer{ | ||
| reader: bufio.NewReader(reader), | ||
| content: stringContent, | ||
| reader: bufio.NewReader(strings.NewReader(stringContent)), | ||
| } |
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment
Add this suggestion to a batch that can be applied as a single commit.This suggestion is invalid because no changes were made to the code.Suggestions cannot be applied while the pull request is closed.Suggestions cannot be applied while viewing a subset of changes.Only one suggestion per line can be applied in a batch.Add this suggestion to a batch that can be applied as a single commit.Applying suggestions on deleted lines is not supported.You must change the existing code in this line in order to create a valid suggestion.Outdated suggestions cannot be applied.This suggestion has been applied or marked resolved.Suggestions cannot be applied from pending reviews.Suggestions cannot be applied on multi-line comments.Suggestions cannot be applied while the pull request is queued to merge.Suggestion cannot be applied right now. Please check back later.
No description provided.