-
Notifications
You must be signed in to change notification settings - Fork 5
V1.6 #31
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
base: main
Are you sure you want to change the base?
Conversation
# Conflicts: # matter/spec/cluster.go # matter/spec/requirements.go # Conflicts: # matter/spec/commands.go # matter/spec/devicetype.go # matter/spec/event.go # matter/spec/requirements.go # Conflicts: # matter/spec/conditions.go # matter/spec/devicetype.go # matter/spec/doc.go # matter/spec/preparse.go # matter/spec/requirements.go # matter/spec/section.go # Conflicts: # disco/sections.go
/gemini review |
Warning Gemini encountered an error creating the summary. You can try again by commenting |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Code Review
This pull request introduces a significant and commendable refactoring to make spec parsing completely non-destructive. The core of this change is the new overlay
package and the addition of Clone()
methods across the data model, which is a solid approach for this kind of task. The changes are extensive and generally well-executed. I've identified a few issues, primarily related to incorrect or incomplete Clone()
implementations and some inconsistencies in the new traversal logic. Addressing these will help ensure the robustness and correctness of the new parsing mechanism.
func (db *DoubleBold) Clone() Element { | ||
return &Bold{position: db.position, raw: db.raw, AttributeList: db.AttributeList.Clone(), Elements: db.Elements.Clone()} | ||
} |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
The Clone()
method for DoubleBold
incorrectly returns a *Bold
instance instead of a *DoubleBold
instance. This will lead to type errors and unexpected behavior when cloning DoubleBold
elements.
func (db *DoubleBold) Clone() Element { | |
return &Bold{position: db.position, raw: db.raw, AttributeList: db.AttributeList.Clone(), Elements: db.Elements.Clone()} | |
} | |
func (db *DoubleBold) Clone() Element { | |
return &DoubleBold{position: db.position, raw: db.raw, AttributeList: db.AttributeList.Clone(), Elements: db.Elements.Clone()} | |
} |
func (sa *ShorthandAttribute) Clone() Attribute { | ||
return &ShorthandAttribute{ | ||
attribute: sa.attribute, | ||
Style: sa.Style.Clone().(*ShorthandStyle), | ||
ID: sa.ID.Clone().(*ShorthandID), | ||
Roles: make([]*ShorthandRole, len(sa.Roles)), | ||
Options: make([]*ShorthandOption, len(sa.Options)), | ||
} | ||
} |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
The Clone()
method for ShorthandAttribute
initializes new slices for Roles
and Options
but fails to copy and clone the elements from the original slices. This results in slices of nil
pointers, leading to data loss and potential panics. You should iterate over the original slices and clone each element individually.
func (sa *ShorthandAttribute) Clone() Attribute { | |
return &ShorthandAttribute{ | |
attribute: sa.attribute, | |
Style: sa.Style.Clone().(*ShorthandStyle), | |
ID: sa.ID.Clone().(*ShorthandID), | |
Roles: make([]*ShorthandRole, len(sa.Roles)), | |
Options: make([]*ShorthandOption, len(sa.Options)), | |
} | |
} | |
func (sa *ShorthandAttribute) Clone() Attribute { | |
cloned := &ShorthandAttribute{ | |
attribute: sa.attribute, | |
Style: sa.Style.Clone().(*ShorthandStyle), | |
ID: sa.ID.Clone().(*ShorthandID), | |
Roles: make([]*ShorthandRole, len(sa.Roles)), | |
Options: make([]*ShorthandOption, len(sa.Options)), | |
} | |
for i, r := range sa.Roles { | |
cloned.Roles[i] = r.Clone().(*ShorthandRole) | |
} | |
for i, o := range sa.Options { | |
cloned.Options[i] = o.Clone().(*ShorthandOption) | |
} | |
return cloned | |
} |
func (aa *AnchorAttribute) Children() Elements { | ||
return aa.ID | ||
} |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
The Children()
method returns aa.ID
, while the Append()
method modifies aa.Label
. This is inconsistent. The Parent
interface, which Children()
is part of, implies that Children()
should return the elements that can be modified by Append()
. To maintain consistency, Children()
should probably return aa.Label
.
func (aa *AnchorAttribute) Children() Elements { | |
return aa.ID | |
} | |
func (aa *AnchorAttribute) Children() Elements { | |
return aa.Label | |
} |
func (aa *Anchor) Traverse(parent Parent) iter.Seq2[Parent, Parent] { | ||
return func(yield func(Parent, Parent) bool) { | ||
if !yield(parent, &aa.ID) { | ||
return | ||
} | ||
} | ||
} |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
The Traverse
method for Anchor
only traverses the ID
field and omits the Elements
field, which holds the label. This is inconsistent with other parts of the code, such as Equals
and NewAnchor
, where the label is also considered part of the content. To ensure the entire content of an Anchor
is processed during traversal, the Elements
field should also be yielded.
func (aa *Anchor) Traverse(parent Parent) iter.Seq2[Parent, Parent] { | |
return func(yield func(Parent, Parent) bool) { | |
if !yield(parent, &aa.ID) { | |
return | |
} | |
} | |
} | |
func (aa *Anchor) Traverse(parent Parent) iter.Seq2[Parent, Parent] { | |
return func(yield func(Parent, Parent) bool) { | |
if !yield(parent, &aa.ID) { | |
return | |
} | |
if !yield(parent, &aa.Elements) { | |
return | |
} | |
} | |
} |
remove = true | ||
case *asciidoc.InlineIfNDef: | ||
if el.Eval(pps) { | ||
pps.state.overlays[el] = &elementOverlay{replace: el.Elements} |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
The elementOverlay
is created directly here, but the action
field is not set. This will cause the Replace()
method on overlayAction
to return false
, and the replacement will not be applied by the Reader
. The replace()
helper function should be used instead to ensure the overlayActionReplace
flag is set correctly.
pps.state.overlays[el] = &elementOverlay{replace: el.Elements} | |
pps.state.overlays.replace(el, el.Elements) |
# Conflicts: # asciidoc/fenced.go # cmd/dump/elements.go # disco/strings.go # go.mod # go.sum
Hefty reworking of spec parsing to be completely non-destructive