refactor(gitconfig): Use slice instead of treemap for storing entries

This commit is contained in:
Myzel394 2024-10-13 15:57:56 +02:00
parent ba1738c700
commit 45748a0634
No known key found for this signature in database
GPG Key ID: DEC4AAB876F73185
5 changed files with 92 additions and 29 deletions

View File

@ -3,8 +3,6 @@ package ast
import (
"config-lsp/common"
"config-lsp/common/parser"
"github.com/emirpasic/gods/maps/treemap"
)
type GitKey struct {
@ -41,7 +39,10 @@ type GitSectionHeader struct {
type GitSection struct {
common.LocationRange
Entries *treemap.Map
// This is a simple list because gitconfig supports multiline entries,
// and thus fetching by line number is not feasible
Entries []*GitEntry
Title *GitSectionHeader
}

View File

@ -1,6 +1,68 @@
package ast
import "slices"
func (c *GitConfig) Clear() {
c.Sections = []*GitSection{}
c.CommentLines = map[uint32]struct{}{}
}
func (c *GitConfig) FindSection(line uint32) *GitSection {
index, found := slices.BinarySearchFunc(
c.Sections,
line,
func(current *GitSection, target uint32) int {
if target > current.End.Line {
return -1
}
if target < current.Start.Line {
return 1
}
return 0
},
)
if !found {
return nil
}
return c.Sections[index]
}
func (c *GitConfig) FindOption(line uint32) (*GitSection, *GitEntry) {
section := c.FindSection(line)
if section == nil {
return nil, nil
}
entry := section.FindOption(line)
return section, entry
}
func (s *GitSection) FindOption(line uint32) *GitEntry {
index, found := slices.BinarySearchFunc(
s.Entries,
line,
func(current *GitEntry, target uint32) int {
if target > current.End.Line {
return -1
}
if target < current.Start.Line {
return 1
}
return 0
},
)
if !found {
return nil
}
return s.Entries[index]
}

View File

@ -46,10 +46,11 @@ func (s *gitconfigParserListener) EnterEntry(ctx *parser.EntryContext) {
LocationRange: location,
}
s.gitconfigContext.currentSection.Entries.Put(
location.Start.Line,
s.gitconfigContext.currentSection.Entries = append(
s.gitconfigContext.currentSection.Entries,
s.gitconfigContext.currentEntry,
)
s.gitconfigContext.currentSection.End = location.End
}
func (s *gitconfigParserListener) ExitEntry(ctx *parser.EntryContext) {

View File

@ -8,9 +8,7 @@ import (
"strings"
"github.com/antlr4-go/antlr/v4"
"github.com/emirpasic/gods/maps/treemap"
gods "github.com/emirpasic/gods/utils"
protocol "github.com/tliron/glsp/protocol_3_16"
)
@ -161,7 +159,7 @@ func (c *GitConfig) parseHeader(
LocationRange: location,
Title: input[leftBracketIndex+1 : rightBracketIndex],
},
Entries: treemap.NewWith(gods.UInt32Comparator),
Entries: make([]*GitEntry, 0),
}
c.Sections = append(c.Sections, context.currentSection)

View File

@ -26,23 +26,32 @@ func TestValidOneSectionExample(t *testing.T) {
section := config.Sections[0]
rawFirstOption, _ := section.Entries.Get(uint32(1))
firstOption := rawFirstOption.(*GitEntry)
firstOption := section.Entries[0]
if !(firstOption.Key.Value.Value == "repositoryformatversion" && firstOption.Value.Value == "0") {
t.Errorf("Expected repositoryformatversion, got %s", firstOption.Key.Value.Value)
}
rawSecondOption, _ := section.Entries.Get(uint32(2))
secondOption := rawSecondOption.(*GitEntry)
secondOption := section.Entries[1]
if !(secondOption.Key.Value.Value == "filemode" && secondOption.Value.Value == "true") {
t.Errorf("Expected filemode, got %s", secondOption.Key.Value.Value)
}
rawThirdOption, _ := section.Entries.Get(uint32(3))
thirdOption := rawThirdOption.(*GitEntry)
thirdOption := section.Entries[2]
if !(thirdOption.Key.Value.Value == "bare" && thirdOption.Value.Value == "false") {
t.Errorf("Expected bare, got %s", thirdOption.Key.Value.Value)
}
foundSection, foundEntry := config.FindOption(1)
if !(foundSection == section && foundEntry == firstOption) {
t.Errorf("Expected first option, got %s", foundEntry.Key.Value.Value)
}
foundSection, foundEntry = config.FindOption(0)
if !(foundSection == section && foundEntry == nil) {
t.Errorf("Expected nil, got %s", foundEntry)
}
}
func TestComplexExample(t *testing.T) {
@ -81,29 +90,23 @@ func TestComplexExample(t *testing.T) {
t.Errorf("Expected core, got %s", section.Title.Title)
}
if !(section.Entries.Size() == 3) {
t.Errorf("Expected 3 entries, got %d", section.Entries.Size())
if !(len(section.Entries) == 3) {
t.Errorf("Expected 3 entries, got %d", len(section.Entries))
}
rawFirstOption, _ := section.Entries.Get(uint32(1))
firstOption := rawFirstOption.(*GitEntry)
firstOption := section.Entries[0]
if !(firstOption.Key.Value.Value == "repositoryformatversion" && firstOption.Value.Value == "0" && firstOption.Start.Line == 1 && firstOption.End.Line == 1 && firstOption.Start.Character == 4 && firstOption.End.Character == 31) {
t.Errorf("Expected 0, got %s", firstOption)
}
_, found := section.Entries.Get(uint32(3))
if found {
t.Errorf("Expected no entry at line 3")
}
section = config.Sections[1]
if !(section.Title.Title == `remote "origin"`) {
t.Errorf("Expected remote \"origin\", got %s", section.Title.Title)
}
if !(section.Entries.Size() == 2) {
t.Errorf("Expected 2 entries, got %d", section.Entries.Size())
if !(len(section.Entries) == 2) {
t.Errorf("Expected 2 entries, got %d", len(section.Entries))
}
section = config.Sections[2]
@ -112,8 +115,7 @@ func TestComplexExample(t *testing.T) {
t.Errorf("Expected alias, got %s", section.Title.Title)
}
rawSecondOption, _ := section.Entries.Get(uint32(13))
secondOption := rawSecondOption.(*GitEntry)
secondOption := section.Entries[0]
if !(secondOption.Key.Value.Value == "ours" && secondOption.Value.Value == "!f() { git checkout --ours $@ && git add $@; }; f" && secondOption.Start.Character == 1 && secondOption.End.Character == 59) {
t.Errorf("Expected ours, got %s", secondOption.Key.Value.Value)
}
@ -162,8 +164,7 @@ func TestLeadingLine(t *testing.T) {
t.Errorf("Expected core, got %s", section.Title.Title)
}
rawFirstOption, _ := section.Entries.Get(uint32(1))
firstOption := rawFirstOption.(*GitEntry)
firstOption := section.Entries[0]
if !(firstOption.Key.Value.Value == "command" && firstOption.Value.Value == "git commit -m Hello World") {
t.Errorf("Expected command, got %s", firstOption.Key.Value.Value)
}