Skip to content

Commit

Permalink
Provide ref text for data types referenced inside of tables
Browse files Browse the repository at this point in the history
  • Loading branch information
hasty committed Nov 8, 2024
1 parent ff6c5b2 commit b583863
Show file tree
Hide file tree
Showing 6 changed files with 100 additions and 35 deletions.
2 changes: 1 addition & 1 deletion asciidoc/table.go
Original file line number Diff line number Diff line change
Expand Up @@ -363,7 +363,7 @@ type Table struct {
Set
}

func (Table) Type() ElementType {
func (*Table) Type() ElementType {
return ElementTypeBlock
}

Expand Down
114 changes: 83 additions & 31 deletions disco/references.go
Original file line number Diff line number Diff line change
Expand Up @@ -8,10 +8,12 @@ import (
"github.com/project-chip/alchemy/internal/log"
"github.com/project-chip/alchemy/internal/parse"
"github.com/project-chip/alchemy/internal/text"
"github.com/project-chip/alchemy/matter"
"github.com/project-chip/alchemy/matter/spec"
"github.com/project-chip/alchemy/matter/types"
)

func (p AnchorNormalizer) rewriteCrossReferences(doc *spec.Doc) {
func (an AnchorNormalizer) rewriteCrossReferences(doc *spec.Doc) {
for id, xrefs := range doc.CrossReferences() {
anchor := doc.FindAnchor(id)
if anchor == nil {
Expand Down Expand Up @@ -63,43 +65,93 @@ func (p AnchorNormalizer) rewriteCrossReferences(doc *spec.Doc) {
}
}
}
if p.options.normalizeAnchors {
parse.Traverse(nil, doc.Base.Elements(), func(icr *asciidoc.CrossReference, parent parse.HasElements, index int) parse.SearchShould {
if len(icr.Set) > 0 {
return parse.SearchShouldContinue
}
anchor := doc.FindAnchor(icr.ID)
if anchor == nil {
return parse.SearchShouldContinue
}
section, isSection := anchor.Element.(*asciidoc.Section)
if !isSection {
return parse.SearchShouldContinue
}
sectionName := section.Name()
elements := parent.Elements()
if index >= len(elements)-1 {
return parse.SearchShouldContinue
}
nextElement := elements[index+1]
nextString, ok := nextElement.(*asciidoc.String)
if !ok {
return parse.SearchShouldContinue
if an.options.normalizeAnchors {
parse.Traverse(nil, doc.Base.Elements(), func(el asciidoc.Element, parent parse.HasElements, index int) parse.SearchShould {
if se, ok := el.(*spec.Element); ok {
el = se.Base
}
lastSpaceIndex := strings.LastIndex(sectionName, " ")
if lastSpaceIndex == -1 {
switch el := el.(type) {
case *asciidoc.CrossReference:
removeCrossReferenceStutter(doc, el, parent, index)
return parse.SearchShouldContinue
}
suffix := sectionName[lastSpaceIndex:]
if !text.HasCaseInsensitivePrefix(nextString.Value, suffix) {
case *asciidoc.Table:
an.normalizeTypeCrossReferencesInTable(doc, el)
return parse.SearchShouldSkip
default:
return parse.SearchShouldContinue
}
replacement := text.TrimCaseInsensitivePrefix(nextString.Value, suffix)
nextString.Value = replacement
return parse.SearchShouldContinue
})
}
}

func removeCrossReferenceStutter(doc *spec.Doc, icr *asciidoc.CrossReference, parent parse.HasElements, index int) {
if len(icr.Set) > 0 {
return
}
anchor := doc.FindAnchor(icr.ID)
if anchor == nil {
return
}
section, isSection := anchor.Element.(*asciidoc.Section)
if !isSection {
return
}
sectionName := section.Name()
elements := parent.Elements()
if index >= len(elements)-1 {
return
}
nextElement := elements[index+1]
nextString, ok := nextElement.(*asciidoc.String)
if !ok {
return
}
lastSpaceIndex := strings.LastIndex(sectionName, " ")
if lastSpaceIndex == -1 {
return
}
suffix := sectionName[lastSpaceIndex:]
if !text.HasCaseInsensitivePrefix(nextString.Value, suffix) {
return
}
replacement := text.TrimCaseInsensitivePrefix(nextString.Value, suffix)
nextString.Value = replacement
}

func (an AnchorNormalizer) normalizeTypeCrossReferencesInTable(doc *spec.Doc, table *asciidoc.Table) {
parse.Traverse(table, table.Set, func(icr *asciidoc.CrossReference, parent parse.HasElements, index int) parse.SearchShould {
if len(icr.Set) > 0 {
// Don't touch existing labels
return parse.SearchShouldContinue
}
anchor := doc.FindAnchor(icr.ID)
if anchor == nil {
return parse.SearchShouldContinue
}
section, isSection := anchor.Element.(*asciidoc.Section)
if !isSection {
return parse.SearchShouldContinue
}
entities, ok := anchor.Document.EntitiesForSection(section)
if !ok {
return parse.SearchShouldContinue
}
if len(entities) != 1 {
return parse.SearchShouldContinue
}
entity := entities[0]
if !types.IsDataTypeEntity(entity.EntityType()) {
return parse.SearchShouldContinue
}
normalizedLabel := normalizeAnchorLabel(section.Name(), section)
if labelText(normalizedLabel) != section.Name() {
icr.Set = normalizedLabel
slog.Debug("Added label to type xref in table", matter.LogEntity("type", entity), "label", labelText(icr.Set))
}

return parse.SearchShouldContinue
})

}

func findRefSection(parent any) *spec.Section {
Expand Down
2 changes: 1 addition & 1 deletion matter/spec/datatypes.go
Original file line number Diff line number Diff line change
Expand Up @@ -166,7 +166,7 @@ func getCustomDataTypeFromReference(spec *Specification, cluster *matter.Cluster
}
switch el := anchor.Element.(type) {
case *asciidoc.Section:
entities := doc.entitiesBySection[el]
entities := anchor.Document.entitiesBySection[el]
if len(entities) == 1 {
e = entities[0]
return
Expand Down
5 changes: 5 additions & 0 deletions matter/spec/doc.go
Original file line number Diff line number Diff line change
Expand Up @@ -135,6 +135,11 @@ func (doc *Doc) OrderedEntities() (entities []types.Entity, err error) {
return doc.orderedEntities, nil
}

func (d *Doc) EntitiesForSection(section *asciidoc.Section) ([]types.Entity, bool) {
e, ok := d.entitiesBySection[section]
return e, ok
}

func (doc *Doc) Reference(ref string) (types.Entity, bool) {

a := doc.FindAnchor(ref)
Expand Down
4 changes: 2 additions & 2 deletions matter/spec/table_info.go
Original file line number Diff line number Diff line change
Expand Up @@ -312,7 +312,7 @@ func (ti *TableInfo) buildConstraintValue(els asciidoc.Set, sb *strings.Builder)
case asciidoc.AttributeReference:
sb.WriteString(fmt.Sprintf("{%s}", v.Name()))
default:
slog.Warn("unknown constraint value element", log.Element("path", ti.Doc.Path, el), "type", fmt.Sprintf("%T", el))
slog.Warn("unknown constraint value element", log.Element("source", ti.Doc.Path, el), "type", fmt.Sprintf("%T", el))
}
}
return
Expand Down Expand Up @@ -483,7 +483,7 @@ func buildDataTypeString(d *Doc, cellElements asciidoc.Set, sb *strings.Builder)
case *asciidoc.Paragraph:
source = buildDataTypeString(d, v.Elements(), sb)
default:
slog.Warn("unknown data type value element", log.Element("path", d.Path, el), "type", fmt.Sprintf("%T", v))
slog.Warn("unknown data type value element", log.Element("source", d.Path, el), "type", fmt.Sprintf("%T", v))
}
}
return
Expand Down
8 changes: 8 additions & 0 deletions matter/types/entity.go
Original file line number Diff line number Diff line change
Expand Up @@ -72,3 +72,11 @@ func (et EntityType) MarshalJSON() ([]byte, error) {
type EntityStore interface {
Entities() ([]Entity, error)
}

func IsDataTypeEntity(entityType EntityType) bool {
switch entityType {
case EntityTypeBitmap, EntityTypeEnum, EntityTypeStruct, EntityTypeCommand, EntityTypeEvent:
return true
}
return false
}

0 comments on commit b583863

Please sign in to comment.