mirror of
https://github.com/Myzel394/config-lsp.git
synced 2025-06-18 23:15:26 +02:00
chore(hosts): Use TreeMap for entries
This commit is contained in:
parent
b27081aa8e
commit
65572886f2
@ -3,10 +3,9 @@ package analyzer
|
||||
import (
|
||||
"config-lsp/common"
|
||||
"config-lsp/handlers/hosts"
|
||||
"config-lsp/handlers/hosts/ast"
|
||||
"config-lsp/handlers/hosts/shared"
|
||||
"config-lsp/utils"
|
||||
"net"
|
||||
"slices"
|
||||
)
|
||||
|
||||
func ipToString(ip net.IPAddr) string {
|
||||
@ -19,14 +18,11 @@ func analyzeDoubleIPs(d *hosts.HostsDocument) []common.LSPError {
|
||||
|
||||
d.Indexes.DoubleIPs = make(map[uint32]shared.DuplicateIPDeclaration)
|
||||
|
||||
// TODO: `range` does not seem to properly
|
||||
// iterate in a sorted way.
|
||||
// Instead, use a treemap
|
||||
lines := utils.KeysOfMap(d.Parser.Tree.Entries)
|
||||
slices.Sort(lines)
|
||||
it := d.Parser.Tree.Entries.Iterator()
|
||||
|
||||
for _, lineNumber := range lines {
|
||||
entry := d.Parser.Tree.Entries[lineNumber]
|
||||
for it.Next() {
|
||||
lineNumber := it.Key().(uint32)
|
||||
entry := it.Value().(*ast.HostsEntry)
|
||||
|
||||
if entry.IPAddress != nil {
|
||||
key := ipToString(entry.IPAddress.Value)
|
||||
|
@ -21,48 +21,50 @@ func TestValidSimpleExampleWorks(
|
||||
t.Fatalf("Expected no errors, but got %v", errors)
|
||||
}
|
||||
|
||||
if !(len(parser.Tree.Entries) == 1) {
|
||||
t.Errorf("Expected 1 entry, but got %v", len(parser.Tree.Entries))
|
||||
if !(parser.Tree.Entries.Size() == 1) {
|
||||
t.Errorf("Expected 1 entry, but got %v", parser.Tree.Entries.Size())
|
||||
}
|
||||
|
||||
if parser.Tree.Entries[0].IPAddress == nil {
|
||||
t.Errorf("Expected IP address to be present, but got nil")
|
||||
rawEntry, found := parser.Tree.Entries.Get(uint32(0))
|
||||
if !found {
|
||||
t.Fatalf("Expected IP address to be present, but got nil")
|
||||
}
|
||||
|
||||
if !(parser.Tree.Entries[0].IPAddress.Value.String() == net.ParseIP("1.2.3.4").String()) {
|
||||
t.Errorf("Expected IP address to be 1.2.3.4, but got %v", parser.Tree.Entries[0].IPAddress.Value)
|
||||
entry := rawEntry.(*ast.HostsEntry)
|
||||
if !(entry.IPAddress.Value.String() == net.ParseIP("1.2.3.4").String()) {
|
||||
t.Errorf("Expected IP address to be 1.2.3.4, but got %v", entry.IPAddress.Value)
|
||||
}
|
||||
|
||||
if !(parser.Tree.Entries[0].Hostname.Value == "hello.com") {
|
||||
t.Errorf("Expected hostname to be hello.com, but got %v", parser.Tree.Entries[0].Hostname.Value)
|
||||
if !(entry.Hostname.Value == "hello.com") {
|
||||
t.Errorf("Expected hostname to be hello.com, but got %v", entry.Hostname.Value)
|
||||
}
|
||||
|
||||
if !(parser.Tree.Entries[0].Aliases == nil) {
|
||||
t.Errorf("Expected no aliases, but got %v", parser.Tree.Entries[0].Aliases)
|
||||
if !(entry.Aliases == nil) {
|
||||
t.Errorf("Expected no aliases, but got %v", entry.Aliases)
|
||||
}
|
||||
|
||||
if !(parser.Tree.Entries[0].Location.Start.Line == 0) {
|
||||
t.Errorf("Expected line to be 1, but got %v", parser.Tree.Entries[0].Location.Start.Line)
|
||||
if !(entry.Location.Start.Line == 0) {
|
||||
t.Errorf("Expected line to be 1, but got %v", entry.Location.Start.Line)
|
||||
}
|
||||
|
||||
if !(parser.Tree.Entries[0].Location.Start.Character == 0) {
|
||||
t.Errorf("Expected start to be 0, but got %v", parser.Tree.Entries[0].Location.Start)
|
||||
if !(entry.Location.Start.Character == 0) {
|
||||
t.Errorf("Expected start to be 0, but got %v", entry.Location.Start)
|
||||
}
|
||||
|
||||
if !(parser.Tree.Entries[0].Location.End.Character == 17) {
|
||||
t.Errorf("Expected end to be 17, but got %v", parser.Tree.Entries[0].Location.End.Character)
|
||||
if !(entry.Location.End.Character == 17) {
|
||||
t.Errorf("Expected end to be 17, but got %v", entry.Location.End.Character)
|
||||
}
|
||||
|
||||
if !(parser.Tree.Entries[0].IPAddress.Location.Start.Line == 0) {
|
||||
t.Errorf("Expected IP address line to be 1, but got %v", parser.Tree.Entries[0].IPAddress.Location.Start.Line)
|
||||
if !(entry.IPAddress.Location.Start.Line == 0) {
|
||||
t.Errorf("Expected IP address line to be 1, but got %v", entry.IPAddress.Location.Start.Line)
|
||||
}
|
||||
|
||||
if !(parser.Tree.Entries[0].IPAddress.Location.Start.Character == 0) {
|
||||
t.Errorf("Expected IP address start to be 0, but got %v", parser.Tree.Entries[0].IPAddress.Location.Start.Character)
|
||||
if !(entry.IPAddress.Location.Start.Character == 0) {
|
||||
t.Errorf("Expected IP address start to be 0, but got %v", entry.IPAddress.Location.Start.Character)
|
||||
}
|
||||
|
||||
if !(parser.Tree.Entries[0].IPAddress.Location.End.Character == 7) {
|
||||
t.Errorf("Expected IP address end to be 7, but got %v", parser.Tree.Entries[0].IPAddress.Location.End.Character)
|
||||
if !(entry.IPAddress.Location.End.Character == 7) {
|
||||
t.Errorf("Expected IP address end to be 7, but got %v", entry.IPAddress.Location.End.Character)
|
||||
}
|
||||
|
||||
if !(len(parser.CommentLines) == 0) {
|
||||
@ -88,16 +90,18 @@ func TestValidComplexExampleWorks(
|
||||
t.Fatalf("Expected no errors, but got %v", errors)
|
||||
}
|
||||
|
||||
if !(len(parser.Tree.Entries) == 3) {
|
||||
t.Errorf("Expected 3 entries, but got %v", len(parser.Tree.Entries))
|
||||
if !(parser.Tree.Entries.Size() == 3) {
|
||||
t.Fatalf("Expected 3 entries, but got %v", parser.Tree.Entries.Size())
|
||||
}
|
||||
|
||||
if parser.Tree.Entries[2].IPAddress == nil {
|
||||
rawEntry, _ := parser.Tree.Entries.Get(uint32(2))
|
||||
entry := rawEntry.(*ast.HostsEntry)
|
||||
if entry.IPAddress == nil {
|
||||
t.Errorf("Expected IP address to be present, but got nil")
|
||||
}
|
||||
|
||||
if !(parser.Tree.Entries[2].IPAddress.Value.String() == net.ParseIP("1.2.3.4").String()) {
|
||||
t.Errorf("Expected IP address to be 1.2.3.4, but got %v", parser.Tree.Entries[2].IPAddress.Value)
|
||||
if !(entry.IPAddress.Value.String() == net.ParseIP("1.2.3.4").String()) {
|
||||
t.Errorf("Expected IP address to be 1.2.3.4, but got %v", entry.IPAddress.Value)
|
||||
}
|
||||
|
||||
if !(len(parser.CommentLines) == 1) {
|
||||
@ -123,23 +127,25 @@ func TestInvalidExampleWorks(
|
||||
t.Fatalf("Expected errors, but got none")
|
||||
}
|
||||
|
||||
if !(len(parser.Tree.Entries) == 1) {
|
||||
t.Errorf("Expected 1 entries, but got %v", len(parser.Tree.Entries))
|
||||
if !(parser.Tree.Entries.Size() == 1) {
|
||||
t.Errorf("Expected 1 entries, but got %v", parser.Tree.Entries.Size())
|
||||
}
|
||||
|
||||
if !(len(parser.CommentLines) == 0) {
|
||||
t.Errorf("Expected no comment lines, but got %v", len(parser.CommentLines))
|
||||
}
|
||||
|
||||
if !(parser.Tree.Entries[0].IPAddress.Value.String() == net.ParseIP("1.2.3.4").String()) {
|
||||
t.Errorf("Expected IP address to be nil, but got %v", parser.Tree.Entries[0].IPAddress)
|
||||
rawEntry, _ := parser.Tree.Entries.Get(uint32(0))
|
||||
entry := rawEntry.(*ast.HostsEntry)
|
||||
if !(entry.IPAddress.Value.String() == net.ParseIP("1.2.3.4").String()) {
|
||||
t.Errorf("Expected IP address to be nil, but got %v", entry.IPAddress)
|
||||
}
|
||||
|
||||
if !(parser.Tree.Entries[0].Hostname == nil) {
|
||||
t.Errorf("Expected hostname to be nil, but got %v", parser.Tree.Entries[0].Hostname)
|
||||
if !(entry.Hostname == nil) {
|
||||
t.Errorf("Expected hostname to be nil, but got %v", entry.Hostname)
|
||||
}
|
||||
|
||||
if !(parser.Tree.Entries[0].Aliases == nil) {
|
||||
t.Errorf("Expected aliases to be nil, but got %v", parser.Tree.Entries[0].Aliases)
|
||||
if !(entry.Aliases == nil) {
|
||||
t.Errorf("Expected aliases to be nil, but got %v", entry.Aliases)
|
||||
}
|
||||
}
|
||||
|
@ -38,7 +38,12 @@ func createResolverFromParser(p ast.HostsParser) (indexes.Resolver, []common.LSP
|
||||
Entries: make(map[string]indexes.ResolverEntry),
|
||||
}
|
||||
|
||||
for lineNumber, entry := range p.Tree.Entries {
|
||||
it := p.Tree.Entries.Iterator()
|
||||
|
||||
for it.Next() {
|
||||
lineNumber := it.Key().(uint32)
|
||||
entry := it.Value().(*ast.HostsEntry)
|
||||
|
||||
if entry.IPAddress != nil && entry.Hostname != nil {
|
||||
hostNames := append(
|
||||
[]hostnameEntry{
|
@ -14,7 +14,12 @@ func analyzeEntriesSetCorrectly(
|
||||
) []common.LSPError {
|
||||
err := make([]common.LSPError, 0)
|
||||
|
||||
for lineNumber, entry := range parser.Tree.Entries {
|
||||
it := parser.Tree.Entries.Iterator()
|
||||
|
||||
for it.Next() {
|
||||
lineNumber := it.Key().(uint32)
|
||||
entry := it.Value().(*ast.HostsEntry)
|
||||
|
||||
if entry.IPAddress == nil {
|
||||
err = append(err, common.LSPError{
|
||||
Range: common.CreateFullLineRange(lineNumber),
|
||||
@ -40,7 +45,11 @@ func analyzeEntriesAreValid(
|
||||
) []common.LSPError {
|
||||
err := make([]common.LSPError, 0)
|
||||
|
||||
for _, entry := range parser.Tree.Entries {
|
||||
it := parser.Tree.Entries.Iterator()
|
||||
|
||||
for it.Next() {
|
||||
entry := it.Value().(*ast.HostsEntry)
|
||||
|
||||
err = append(
|
||||
err,
|
||||
utils.Map(
|
||||
|
@ -4,6 +4,8 @@ import (
|
||||
"config-lsp/common"
|
||||
"fmt"
|
||||
"net"
|
||||
|
||||
"github.com/emirpasic/gods/maps/treemap"
|
||||
)
|
||||
|
||||
type HostsParser struct {
|
||||
@ -13,7 +15,7 @@ type HostsParser struct {
|
||||
|
||||
type HostsTree struct {
|
||||
// [line]entry
|
||||
Entries map[uint32]*HostsEntry
|
||||
Entries *treemap.Map
|
||||
}
|
||||
|
||||
type HostsEntry struct {
|
||||
|
@ -31,9 +31,9 @@ func (s *hostsParserListener) EnterEntry(ctx *parser2.EntryContext) {
|
||||
location := common.CharacterRangeFromCtx(ctx.BaseParserRuleContext)
|
||||
location.ChangeBothLines(s.hostsContext.line)
|
||||
|
||||
s.Parser.Tree.Entries[location.Start.Line] = &HostsEntry{
|
||||
s.Parser.Tree.Entries.Put(location.Start.Line, &HostsEntry{
|
||||
Location: location,
|
||||
}
|
||||
})
|
||||
}
|
||||
|
||||
var containsPortPattern = regexp.MustCompile(`:[0-9]+$`)
|
||||
@ -69,7 +69,8 @@ func (s *hostsParserListener) EnterIpAddress(ctx *parser2.IpAddressContext) {
|
||||
})
|
||||
}
|
||||
|
||||
entry := s.Parser.Tree.Entries[location.Start.Line]
|
||||
rawEntry, _ := s.Parser.Tree.Entries.Get(location.Start.Line)
|
||||
entry := rawEntry.(*HostsEntry)
|
||||
|
||||
entry.IPAddress = &HostsIPAddress{
|
||||
Location: location,
|
||||
@ -81,21 +82,21 @@ func (s *hostsParserListener) EnterHostname(ctx *parser2.HostnameContext) {
|
||||
location := common.CharacterRangeFromCtx(ctx.BaseParserRuleContext)
|
||||
location.ChangeBothLines(s.hostsContext.line)
|
||||
|
||||
entry := s.Parser.Tree.Entries[location.Start.Line]
|
||||
rawEntry, _ := s.Parser.Tree.Entries.Get(location.Start.Line)
|
||||
entry := rawEntry.(*HostsEntry)
|
||||
|
||||
entry.Hostname = &HostsHostname{
|
||||
Location: location,
|
||||
Value: ctx.GetText(),
|
||||
}
|
||||
|
||||
s.Parser.Tree.Entries[location.Start.Line] = entry
|
||||
}
|
||||
|
||||
func (s *hostsParserListener) EnterAliases(ctx *parser2.AliasesContext) {
|
||||
location := common.CharacterRangeFromCtx(ctx.BaseParserRuleContext)
|
||||
location.ChangeBothLines(s.hostsContext.line)
|
||||
|
||||
entry := s.Parser.Tree.Entries[location.Start.Line]
|
||||
rawEntry, _ := s.Parser.Tree.Entries.Get(location.Start.Line)
|
||||
entry := rawEntry.(*HostsEntry)
|
||||
|
||||
aliases := make([]*HostsHostname, 0)
|
||||
|
||||
@ -106,7 +107,8 @@ func (s *hostsParserListener) EnterAlias(ctx *parser2.AliasContext) {
|
||||
location := common.CharacterRangeFromCtx(ctx.BaseParserRuleContext)
|
||||
location.ChangeBothLines(s.hostsContext.line)
|
||||
|
||||
entry := s.Parser.Tree.Entries[location.Start.Line]
|
||||
rawEntry, _ := s.Parser.Tree.Entries.Get(location.Start.Line)
|
||||
entry := rawEntry.(*HostsEntry)
|
||||
|
||||
alias := HostsHostname{
|
||||
Location: location,
|
||||
|
@ -7,11 +7,14 @@ import (
|
||||
"regexp"
|
||||
|
||||
"github.com/antlr4-go/antlr/v4"
|
||||
"github.com/emirpasic/gods/maps/treemap"
|
||||
|
||||
gods "github.com/emirpasic/gods/utils"
|
||||
)
|
||||
|
||||
func (p *HostsParser) Clear() {
|
||||
p.Tree = HostsTree{
|
||||
Entries: make(map[uint32]*HostsEntry),
|
||||
Entries: treemap.NewWith(gods.UInt32Comparator),
|
||||
}
|
||||
p.CommentLines = make(map[uint32]struct{})
|
||||
}
|
||||
@ -44,8 +47,8 @@ func (p *HostsParser) parseStatement(
|
||||
antlrParser.LineStatement(),
|
||||
)
|
||||
|
||||
errors = append(errors, errorListener.Errors...)
|
||||
errors = append(errors, listener.Errors...)
|
||||
errors = append(errors, errorListener.Errors...)
|
||||
|
||||
return errors
|
||||
}
|
||||
|
@ -18,3 +18,34 @@ func TestParserInvalidWithPort(
|
||||
t.Fatalf("Expected 1 error, but got %v", errors)
|
||||
}
|
||||
}
|
||||
|
||||
func TestParserValidComplexExample(
|
||||
t *testing.T,
|
||||
) {
|
||||
input := utils.Dedent(`
|
||||
1.2.3.4 hello.com alias.com example.com
|
||||
1.2.3.5 hello1.com alias1.com example1.com
|
||||
192.168.1.1 goodbye.com
|
||||
`)
|
||||
parser := NewHostsParser()
|
||||
errors := parser.Parse(input)
|
||||
|
||||
if len(errors) != 0 {
|
||||
t.Fatalf("Expected no errors, but got %v", errors)
|
||||
}
|
||||
|
||||
if !(parser.Tree.Entries.Size() == 3) {
|
||||
t.Fatalf("Expected 3 entries, but got %v", parser.Tree.Entries.Size())
|
||||
}
|
||||
|
||||
rawEntry, _ := parser.Tree.Entries.Get(uint32(0))
|
||||
entry := rawEntry.(*HostsEntry)
|
||||
|
||||
if !(entry.IPAddress.Value.String() == "1.2.3.4") {
|
||||
t.Errorf("Expected IP address to be 1.2.3.4, but got %v", entry.IPAddress.Value)
|
||||
}
|
||||
|
||||
if !(entry.Hostname.Value == "hello.com") {
|
||||
t.Errorf("Expected hostname to be hello.com, but got %v", entry.Hostname.Value)
|
||||
}
|
||||
}
|
||||
|
@ -9,5 +9,5 @@ var IPAddressField = docvalues.IPAddressValue{
|
||||
|
||||
var HostnameField = docvalues.DocumentationValue{
|
||||
Documentation: `Host names may contain only alphanumeric characters, minus signs ("-"), and periods ("."). They must begin with an alphabetic character and end with an alphanumeric character. Optional aliases provide for name changes, alternate spellings, shorter hostnames, or generic hostnames (for example, localhost).`,
|
||||
Value: docvalues.DomainValue(),
|
||||
Value: docvalues.StringValue{},
|
||||
}
|
||||
|
@ -36,14 +36,17 @@ func CodeActionInlineAliasesArgsFromArguments(arguments map[string]any) CodeActi
|
||||
}
|
||||
|
||||
func (args CodeActionInlineAliasesArgs) RunCommand(hostsParser ast.HostsParser) (*protocol.ApplyWorkspaceEditParams, error) {
|
||||
fromEntry := hostsParser.Tree.Entries[args.FromLine]
|
||||
toEntry := hostsParser.Tree.Entries[args.ToLine]
|
||||
rawFromEntry, foundFromEntry := hostsParser.Tree.Entries.Get(args.FromLine)
|
||||
rawToEntry, foundToEntry := hostsParser.Tree.Entries.Get(args.ToLine)
|
||||
|
||||
if fromEntry == nil || toEntry == nil {
|
||||
if !foundFromEntry || !foundToEntry {
|
||||
// Weird
|
||||
return nil, nil
|
||||
}
|
||||
|
||||
fromEntry := rawFromEntry.(*ast.HostsEntry)
|
||||
toEntry := rawToEntry.(*ast.HostsEntry)
|
||||
|
||||
var insertCharacter uint32
|
||||
|
||||
if toEntry.Aliases != nil {
|
||||
|
@ -25,13 +25,14 @@ func TextDocumentHover(
|
||||
return nil, nil
|
||||
}
|
||||
|
||||
entry, found := document.Parser.Tree.Entries[line]
|
||||
rawEntry, found := document.Parser.Tree.Entries.Get(line)
|
||||
|
||||
if !found {
|
||||
// Empty line
|
||||
return nil, nil
|
||||
}
|
||||
|
||||
entry := rawEntry.(*ast.HostsEntry)
|
||||
target := handlers.GetHoverTargetInEntry(*entry, character)
|
||||
|
||||
var hostname *ast.HostsHostname
|
||||
|
Loading…
x
Reference in New Issue
Block a user