refactor(fstab): Migrating more stuff

This commit is contained in:
Myzel394 2024-10-08 12:33:19 +02:00
parent 1f4717deba
commit 558b9b7c98
No known key found for this signature in database
GPG Key ID: ED20A1D1D423AF3F
17 changed files with 229 additions and 80 deletions

View File

@ -43,3 +43,4 @@ type FstabConfig struct {
// [uint32]{} - line number to empty struct for comments // [uint32]{} - line number to empty struct for comments
CommentLines map[uint32]struct{} CommentLines map[uint32]struct{}
} }

View File

@ -0,0 +1,35 @@
package ast
// func (c FstabConfig) GetEntry(line uint32) *FstabEntry {
// entry, found := c.Entries.Get(line)
//
// if !found {
// return nil
// }
//
// return entry.(*FstabEntry)
// }
func (e FstabEntry) GetFieldAtPosition(cursor uint32) FstabFieldName {
if e.Fields.Spec == nil || (cursor >= e.Fields.Spec.Start.Character && cursor <= e.Fields.Spec.End.Character) {
return FstabFieldSpec
}
if e.Fields.MountPoint == nil || (cursor >= e.Fields.MountPoint.Start.Character && cursor <= e.Fields.MountPoint.End.Character) {
return FstabFieldMountPoint
}
if e.Fields.FilesystemType == nil || (cursor >= e.Fields.FilesystemType.Start.Character && cursor <= e.Fields.FilesystemType.End.Character) {
return FstabFieldFileSystemType
}
if e.Fields.Options == nil || (cursor >= e.Fields.Options.Start.Character && cursor <= e.Fields.Options.End.Character) {
return FstabFieldOptions
}
if e.Fields.Freq == nil || (cursor >= e.Fields.Freq.Start.Character && cursor <= e.Fields.Freq.End.Character) {
return FstabFieldFreq
}
return FstabFieldPass
}

View File

@ -15,7 +15,7 @@ var LabelField = docvalues.RegexValue{
var SpecField = docvalues.OrValue{ var SpecField = docvalues.OrValue{
Values: []docvalues.DeprecatedValue{ Values: []docvalues.DeprecatedValue{
docvalues.PathValue{ docvalues.PathValue{
RequiredType: docvalues.PathTypeFile & docvalues.PathTypeExistenceOptional, RequiredType: docvalues.PathTypeFile,
}, },
docvalues.KeyEnumAssignmentValue{ docvalues.KeyEnumAssignmentValue{
Separator: "=", Separator: "=",

View File

@ -1,7 +1,7 @@
package fstab package fstab
import ( import (
fstabdocumentation "config-lsp/handlers/fstab/documentation" fstabdocumentation "config-lsp/handlers/fstab/fields"
handlers "config-lsp/handlers/fstab/handlers" handlers "config-lsp/handlers/fstab/handlers"
"config-lsp/handlers/fstab/parser" "config-lsp/handlers/fstab/parser"
"config-lsp/utils" "config-lsp/utils"
@ -158,6 +158,12 @@ UUID=b411dc99-f0a0-4c87-9e05-184977be8539 /home ext4 defaults 0 2
if len(errors) > 0 { if len(errors) > 0 {
t.Fatalf("ParseFromContent failed with error %v", errors) t.Fatalf("ParseFromContent failed with error %v", errors)
} }
diagnostics := p.AnalyzeValues()
if len(diagnostics) > 0 {
t.Errorf("AnalyzeValues failed with error %v", diagnostics)
}
} }
func TestArchExample2(t *testing.T) { func TestArchExample2(t *testing.T) {
@ -192,6 +198,12 @@ LABEL=Swap none swap defaults 0 0
if len(errors) > 0 { if len(errors) > 0 {
t.Fatalf("ParseFromContent failed with error %v", errors) t.Fatalf("ParseFromContent failed with error %v", errors)
} }
diagnostics := p.AnalyzeValues()
if len(diagnostics) > 0 {
t.Errorf("AnalyzeValues failed with error %v", diagnostics)
}
} }
func TestArchExample4(t *testing.T) { func TestArchExample4(t *testing.T) {
@ -209,6 +221,12 @@ UUID=f9fe0b69-a280-415d-a03a-a32752370dee none swap defaults 0 0
if len(errors) > 0 { if len(errors) > 0 {
t.Fatalf("ParseFromContent failed with error %v", errors) t.Fatalf("ParseFromContent failed with error %v", errors)
} }
diagnostics := p.AnalyzeValues()
if len(diagnostics) > 0 {
t.Errorf("AnalyzeValues failed with error %v", diagnostics)
}
} }
func TestArchExample5(t *testing.T) { func TestArchExample5(t *testing.T) {
@ -226,6 +244,12 @@ PARTLABEL=Swap none swap defaults 0 0
if len(errors) > 0 { if len(errors) > 0 {
t.Fatalf("ParseFromContent failed with error %v", errors) t.Fatalf("ParseFromContent failed with error %v", errors)
} }
diagnostics := p.AnalyzeValues()
if len(diagnostics) > 0 {
t.Errorf("AnalyzeValues failed with error %v", diagnostics)
}
} }
func TestArchExample6(t *testing.T) { func TestArchExample6(t *testing.T) {
@ -243,5 +267,89 @@ PARTUUID=039b6c1c-7553-4455-9537-1befbc9fbc5b none swap defaults 0 0
if len(errors) > 0 { if len(errors) > 0 {
t.Fatalf("ParseFromContent failed with error %v", errors) t.Fatalf("ParseFromContent failed with error %v", errors)
} }
diagnostics := p.AnalyzeValues()
if len(diagnostics) > 0 {
t.Errorf("AnalyzeValues failed with error %v", diagnostics)
}
} }
func TestLinuxConfigExample(t *testing.T) {
input := utils.Dedent(`
UUID=80b496fa-ce2d-4dcf-9afc-bcaa731a67f1 /mnt/example ext4 defaults 0 2
`)
p := parser.FstabParser{}
p.Clear()
errors := p.ParseFromContent(input)
if len(errors) > 0 {
t.Fatalf("ParseFromContent failed with error %v", errors)
}
diagnostics := p.AnalyzeValues()
if len(diagnostics) > 0 {
t.Errorf("AnalyzeValues failed with error %v", diagnostics)
}
}
func Test1(t *testing.T) {
input := utils.Dedent(`
PARTLABEL="rootfs" / ext4 noatime,lazytime,rw 0 0
`)
p := parser.FstabParser{}
p.Clear()
errors := p.ParseFromContent(input)
if len(errors) > 0 {
t.Fatalf("ParseFromContent failed with error %v", errors)
}
diagnostics := p.AnalyzeValues()
if len(diagnostics) > 0 {
t.Errorf("AnalyzeValues failed with error %v", diagnostics)
}
}
func Test2(t *testing.T) {
input := utils.Dedent(`
/dev/sda /home1 xfs defaults 1 2
/dev/sdb /homeB xfs noauto,nobarrier,rw,relatime,attr2,inode64,logbufs=8,logbsize=32k,noquota 0 0
/dev/sdc /homeC xfs noauto,defaults 0 0
/dev/sdd /homeD xfs noauto,rw,attr2,inode64,logbufs=8,logbsize=32k,noquota 0 0
/dev/sde /homeE xfs defaults 0 0
`)
p := parser.FstabParser{}
p.Clear()
errors := p.ParseFromContent(input)
if len(errors) > 0 {
t.Fatalf("ParseFromContent failed with error %v", errors)
}
}
func Test3(t *testing.T) {
input := utils.Dedent(`
/dev/disk/by-label/dsp /dsp auto ro
/dev/disk/by-partlabel/modem_a /firmware auto ro
/dev/disk/by-partlabel/persist /persist auto ro,discard,nosuid,nodev,noexec
/dev/disk/by-partlabel/userdata /data auto discard,noatime,nodiratime,nosuid,nodev,nofail 0 0
/dev/disk/by-partlabel/cache /cache ext4 relatime,data=ordered,noauto_da_alloc,discard,noexec,nodev,nosuid,x-systemd.makefs 0 0
/dev/nvme0n1 /data/media auto discard,nosuid,nodev,nofail,x-systemd.device-timeout=5s 0 0
tmpfs /var tmpfs rw,nosuid,nodev,size=128M,mode=755 0 0
tmpfs /tmp tmpfs rw,nosuid,nodev,size=150M,mode=1777 0 0
`)
p := parser.FstabParser{}
p.Clear()
errors := p.ParseFromContent(input)
if len(errors) > 0 {
t.Fatalf("ParseFromContent failed with error %v", errors)
}
}

View File

@ -2,41 +2,42 @@ package handlers
import ( import (
"config-lsp/doc-values" "config-lsp/doc-values"
"config-lsp/handlers/fstab/documentation" "config-lsp/handlers/fstab/ast"
"config-lsp/handlers/fstab/parser" "config-lsp/handlers/fstab/fields"
"github.com/tliron/glsp/protocol_3_16" "github.com/tliron/glsp/protocol_3_16"
) )
func GetCompletion( func GetCompletion(
line parser.FstabLine, entry *ast.FstabEntry,
cursor uint32, cursor uint32,
) ([]protocol.CompletionItem, error) { ) ([]protocol.CompletionItem, error) {
targetField := line.GetFieldAtPosition(cursor) targetField := entry.GetFieldAtPosition(cursor)
switch targetField { switch targetField {
case parser.FstabFieldSpec: case ast.FstabFieldSpec:
value, cursor := GetFieldSafely(line.Fields.Spec, cursor) value, cursor := getFieldSafely(entry.Fields.Spec, cursor)
return fstabdocumentation.SpecField.DeprecatedFetchCompletions( return fstabdocumentation.SpecField.DeprecatedFetchCompletions(
value, value,
cursor, cursor,
), nil ), nil
case parser.FstabFieldMountPoint: case ast.FstabFieldMountPoint:
value, cursor := GetFieldSafely(line.Fields.MountPoint, cursor) value, cursor := getFieldSafely(entry.Fields.MountPoint, cursor)
return fstabdocumentation.MountPointField.DeprecatedFetchCompletions( return fstabdocumentation.MountPointField.DeprecatedFetchCompletions(
value, value,
cursor, cursor,
), nil ), nil
case parser.FstabFieldFileSystemType: case ast.FstabFieldFileSystemType:
value, cursor := GetFieldSafely(line.Fields.FilesystemType, cursor) value, cursor := getFieldSafely(entry.Fields.FilesystemType, cursor)
return fstabdocumentation.FileSystemTypeField.DeprecatedFetchCompletions( return fstabdocumentation.FileSystemTypeField.DeprecatedFetchCompletions(
value, value,
cursor, cursor,
), nil ), nil
case parser.FstabFieldOptions: case ast.FstabFieldOptions:
fileSystemType := line.Fields.FilesystemType.Value fileSystemType := entry.Fields.FilesystemType.Value.Value
var optionsField docvalues.DeprecatedValue var optionsField docvalues.DeprecatedValue
@ -46,7 +47,7 @@ func GetCompletion(
optionsField = fstabdocumentation.DefaultMountOptionsField optionsField = fstabdocumentation.DefaultMountOptionsField
} }
value, cursor := GetFieldSafely(line.Fields.Options, cursor) value, cursor := getFieldSafely(entry.Fields.Options, cursor)
completions := optionsField.DeprecatedFetchCompletions( completions := optionsField.DeprecatedFetchCompletions(
value, value,
@ -54,15 +55,15 @@ func GetCompletion(
) )
return completions, nil return completions, nil
case parser.FstabFieldFreq: case ast.FstabFieldFreq:
value, cursor := GetFieldSafely(line.Fields.Freq, cursor) value, cursor := getFieldSafely(entry.Fields.Freq, cursor)
return fstabdocumentation.FreqField.DeprecatedFetchCompletions( return fstabdocumentation.FreqField.DeprecatedFetchCompletions(
value, value,
cursor, cursor,
), nil ), nil
case parser.FstabFieldPass: case ast.FstabFieldPass:
value, cursor := GetFieldSafely(line.Fields.Pass, cursor) value, cursor := getFieldSafely(entry.Fields.Pass, cursor)
return fstabdocumentation.PassField.DeprecatedFetchCompletions( return fstabdocumentation.PassField.DeprecatedFetchCompletions(
value, value,
@ -75,14 +76,14 @@ func GetCompletion(
// Safely get value and new cursor position // Safely get value and new cursor position
// If field is nil, return empty string and 0 // If field is nil, return empty string and 0
func GetFieldSafely(field *parser.Field, character uint32) (string, uint32) { func getFieldSafely(field *ast.FstabField, character uint32) (string, uint32) {
if field == nil { if field == nil {
return "", 0 return "", 0
} }
if field.Value == "" { if field.Value.Value == "" {
return "", 0 return "", 0
} }
return field.Value, character - field.Start return field.Value.Raw, character - field.Start.Character
} }

View File

@ -2,25 +2,29 @@ package handlers
import ( import (
"config-lsp/doc-values" "config-lsp/doc-values"
"config-lsp/handlers/fstab/documentation" "config-lsp/handlers/fstab/ast"
"config-lsp/handlers/fstab/parser" "config-lsp/handlers/fstab/fields"
"github.com/tliron/glsp/protocol_3_16"
"strings" "strings"
"github.com/tliron/glsp/protocol_3_16"
) )
func GetHoverInfo(entry *parser.FstabEntry, cursor uint32) (*protocol.Hover, error) { func GetHoverInfo(
line := entry.Line line uint32,
targetField := line.GetFieldAtPosition(cursor) cursor uint32,
entry *ast.FstabEntry,
) (*protocol.Hover, error) {
targetField := entry.GetFieldAtPosition(cursor)
switch targetField { switch targetField {
case parser.FstabFieldSpec: case ast.FstabFieldSpec:
return &SpecHoverField, nil return &SpecHoverField, nil
case parser.FstabFieldMountPoint: case ast.FstabFieldMountPoint:
return &MountPointHoverField, nil return &MountPointHoverField, nil
case parser.FstabFieldFileSystemType: case ast.FstabFieldFileSystemType:
return &FileSystemTypeField, nil return &FileSystemTypeField, nil
case parser.FstabFieldOptions: case ast.FstabFieldOptions:
fileSystemType := line.Fields.FilesystemType.Value fileSystemType := entry.Fields.FilesystemType.Value.Value
var optionsField docvalues.DeprecatedValue var optionsField docvalues.DeprecatedValue
if foundField, found := fstabdocumentation.MountOptionsMapField[fileSystemType]; found { if foundField, found := fstabdocumentation.MountOptionsMapField[fileSystemType]; found {
@ -29,8 +33,8 @@ func GetHoverInfo(entry *parser.FstabEntry, cursor uint32) (*protocol.Hover, err
optionsField = fstabdocumentation.DefaultMountOptionsField optionsField = fstabdocumentation.DefaultMountOptionsField
} }
relativeCursor := cursor - line.Fields.Options.Start relativeCursor := cursor - entry.Fields.Options.Start.Character
fieldInfo := optionsField.DeprecatedFetchHoverInfo(line.Fields.Options.Value, relativeCursor) fieldInfo := optionsField.DeprecatedFetchHoverInfo(entry.Fields.Options.Value.Value, relativeCursor)
hover := protocol.Hover{ hover := protocol.Hover{
Contents: protocol.MarkupContent{ Contents: protocol.MarkupContent{
@ -40,9 +44,9 @@ func GetHoverInfo(entry *parser.FstabEntry, cursor uint32) (*protocol.Hover, err
} }
return &hover, nil return &hover, nil
case parser.FstabFieldFreq: case ast.FstabFieldFreq:
return &FreqHoverField, nil return &FreqHoverField, nil
case parser.FstabFieldPass: case ast.FstabFieldPass:
return &PassHoverField, nil return &PassHoverField, nil
} }

View File

@ -2,9 +2,9 @@ package lsp
import ( import (
"config-lsp/common" "config-lsp/common"
fstabdocumentation "config-lsp/handlers/fstab/documentation" "config-lsp/handlers/fstab/ast"
fstabdocumentation "config-lsp/handlers/fstab/fields"
"config-lsp/handlers/fstab/handlers" "config-lsp/handlers/fstab/handlers"
"config-lsp/handlers/fstab/parser"
"config-lsp/handlers/fstab/shared" "config-lsp/handlers/fstab/shared"
"github.com/tliron/glsp" "github.com/tliron/glsp"
@ -12,9 +12,9 @@ import (
) )
func TextDocumentCompletion(context *glsp.Context, params *protocol.CompletionParams) (any, error) { func TextDocumentCompletion(context *glsp.Context, params *protocol.CompletionParams) (any, error) {
p := shared.DocumentParserMap[params.TextDocument.URI] c := shared.DocumentParserMap[params.TextDocument.URI]
entry, found := p.GetEntry(params.Position.Line) rawEntry, found := c.Entries.Get(params.Position.Line)
if !found { if !found {
// Empty line, return spec completions // Empty line, return spec completions
@ -24,12 +24,9 @@ func TextDocumentCompletion(context *glsp.Context, params *protocol.CompletionPa
), nil ), nil
} }
if entry.Type == parser.FstabEntryTypeComment { entry := rawEntry.(*ast.FstabEntry)
return nil, nil
}
cursor := common.CursorToCharacterIndex(params.Position.Character) cursor := common.CursorToCharacterIndex(params.Position.Character)
line := entry.Line
return handlers.GetCompletion(line, cursor) return handlers.GetCompletion(entry, cursor)
} }

View File

@ -19,17 +19,17 @@ func TextDocumentDidChange(
p.Clear() p.Clear()
diagnostics := make([]protocol.Diagnostic, 0) diagnostics := make([]protocol.Diagnostic, 0)
errors := p.ParseFromContent(content) errors := p.Parse(content)
if len(errors) > 0 { if len(errors) > 0 {
diagnostics = append(diagnostics, utils.Map( diagnostics = append(diagnostics, utils.Map(
errors, errors,
func(err common.ParseError) protocol.Diagnostic { func(err common.LSPError) protocol.Diagnostic {
return err.ToDiagnostic() return err.ToDiagnostic()
}, },
)...) )...)
} else { } else {
diagnostics = append(diagnostics, p.AnalyzeValues()...) // diagnostics = append(diagnostics, p.AnalyzeValues()...)
} }
if len(diagnostics) > 0 { if len(diagnostics) > 0 {

View File

@ -2,9 +2,10 @@ package lsp
import ( import (
"config-lsp/common" "config-lsp/common"
"config-lsp/handlers/fstab/parser" "config-lsp/handlers/fstab/ast"
"config-lsp/handlers/fstab/shared" "config-lsp/handlers/fstab/shared"
"config-lsp/utils" "config-lsp/utils"
"github.com/tliron/glsp" "github.com/tliron/glsp"
protocol "github.com/tliron/glsp/protocol_3_16" protocol "github.com/tliron/glsp/protocol_3_16"
) )
@ -15,24 +16,23 @@ func TextDocumentDidOpen(
) error { ) error {
common.ClearDiagnostics(context, params.TextDocument.URI) common.ClearDiagnostics(context, params.TextDocument.URI)
p := parser.FstabParser{} p := ast.NewFstabConfig()
p.Clear() shared.DocumentParserMap[params.TextDocument.URI] = p
shared.DocumentParserMap[params.TextDocument.URI] = &p
content := params.TextDocument.Text content := params.TextDocument.Text
diagnostics := make([]protocol.Diagnostic, 0) diagnostics := make([]protocol.Diagnostic, 0)
errors := p.ParseFromContent(content) errors := p.Parse(content)
if len(errors) > 0 { if len(errors) > 0 {
diagnostics = append(diagnostics, utils.Map( diagnostics = append(diagnostics, utils.Map(
errors, errors,
func(err common.ParseError) protocol.Diagnostic { func(err common.LSPError) protocol.Diagnostic {
return err.ToDiagnostic() return err.ToDiagnostic()
}, },
)...) )...)
} else { } else {
diagnostics = append(diagnostics, p.AnalyzeValues()...) // diagnostics = append(diagnostics, p.AnalyzeValues()...)
} }
if len(diagnostics) > 0 { if len(diagnostics) > 0 {

View File

@ -1,29 +1,32 @@
package lsp package lsp
import ( import (
"config-lsp/handlers/fstab/ast"
"config-lsp/handlers/fstab/handlers" "config-lsp/handlers/fstab/handlers"
"config-lsp/handlers/fstab/parser"
"config-lsp/handlers/fstab/shared" "config-lsp/handlers/fstab/shared"
"github.com/tliron/glsp" "github.com/tliron/glsp"
protocol "github.com/tliron/glsp/protocol_3_16" protocol "github.com/tliron/glsp/protocol_3_16"
) )
func TextDocumentHover(context *glsp.Context, params *protocol.HoverParams) (*protocol.Hover, error) { func TextDocumentHover(context *glsp.Context, params *protocol.HoverParams) (*protocol.Hover, error) {
line := params.Position.Line
cursor := params.Position.Character cursor := params.Position.Character
p := shared.DocumentParserMap[params.TextDocument.URI] p := shared.DocumentParserMap[params.TextDocument.URI]
entry, found := p.GetEntry(params.Position.Line) rawEntry, found := p.Entries.Get(params.Position.Line)
// Empty line // Empty line
if !found { if !found {
return nil, nil return nil, nil
} }
// Comment line entry := rawEntry.(*ast.FstabEntry)
if entry.Type == parser.FstabEntryTypeComment {
return nil, nil
}
return handlers.GetHoverInfo(entry, cursor) return handlers.GetHoverInfo(
line,
cursor,
entry,
)
} }

View File

@ -3,7 +3,7 @@ package parser
import ( import (
"config-lsp/common" "config-lsp/common"
docvalues "config-lsp/doc-values" docvalues "config-lsp/doc-values"
fstabdocumentation "config-lsp/handlers/fstab/documentation" fstabdocumentation "config-lsp/handlers/fstab/fields"
"fmt" "fmt"
"regexp" "regexp"
"strings" "strings"
@ -378,8 +378,6 @@ func (p *FstabParser) AnalyzeValues() []protocol.Diagnostic {
if len(newDiagnostics) > 0 { if len(newDiagnostics) > 0 {
diagnostics = append(diagnostics, newDiagnostics...) diagnostics = append(diagnostics, newDiagnostics...)
} }
case FstabEntryTypeComment:
// Do nothing
} }
} }

View File

@ -1,8 +1,10 @@
package shared package shared
import ( import (
"config-lsp/handlers/fstab/parser" "config-lsp/handlers/fstab/ast"
protocol "github.com/tliron/glsp/protocol_3_16" protocol "github.com/tliron/glsp/protocol_3_16"
) )
var DocumentParserMap = map[protocol.DocumentUri]*parser.FstabParser{} var DocumentParserMap = map[protocol.DocumentUri]*ast.FstabConfig{}