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

@ -193,13 +193,13 @@ var defaultOptions = []docvalues.EnumString{
), ),
docvalues.CreateEnumStringWithDoc( docvalues.CreateEnumStringWithDoc(
"x-systemd.automount", "x-systemd.automount",
`An automount unit will be created for the file system. See systemd.automount(5) for details. `An automount unit will be created for the file system. See systemd.automount(5) for details.
Added in version 215.`, Added in version 215.`,
), ),
docvalues.CreateEnumStringWithDoc( docvalues.CreateEnumStringWithDoc(
"x-systemd.makefs", "x-systemd.makefs",
`The file system will be initialized on the device. If the device is not "empty", i.e. it contains any signature, the operation will be skipped. It is hence expected that this option remains set even after the device has been initialized. `The file system will be initialized on the device. If the device is not "empty", i.e. it contains any signature, the operation will be skipped. It is hence expected that this option remains set even after the device has been initialized.
Note that this option can only be used in /etc/fstab, and will be ignored when part of the Options= setting in a unit file. Note that this option can only be used in /etc/fstab, and will be ignored when part of the Options= setting in a unit file.
@ -211,7 +211,7 @@ Added in version 236.`,
), ),
docvalues.CreateEnumStringWithDoc( docvalues.CreateEnumStringWithDoc(
"x-systemd.growfs", "x-systemd.growfs",
`The file system will be grown to occupy the full block device. If the file system is already at maximum size, no action will be performed. It is hence expected that this option remains set even after the file system has been grown. Only certain file system types are supported, see systemd-makefs@.service(8) for details. `The file system will be grown to occupy the full block device. If the file system is already at maximum size, no action will be performed. It is hence expected that this option remains set even after the file system has been grown. Only certain file system types are supported, see systemd-makefs@.service(8) for details.
Note that this option can only be used in /etc/fstab, and will be ignored when part of the Options= setting in a unit file. Note that this option can only be used in /etc/fstab, and will be ignored when part of the Options= setting in a unit file.
@ -219,7 +219,7 @@ Added in version 236.`,
), ),
docvalues.CreateEnumStringWithDoc( docvalues.CreateEnumStringWithDoc(
"x-systemd.pcrfs", "x-systemd.pcrfs",
`Measures file system identity information (mount point, type, label, UUID, partition label, partition UUID) into PCR 15 after the file system has been mounted. This ensures the systemd-pcrfs@.service(8) or systemd-pcrfs-root.service services are pulled in by the mount unit. `Measures file system identity information (mount point, type, label, UUID, partition label, partition UUID) into PCR 15 after the file system has been mounted. This ensures the systemd-pcrfs@.service(8) or systemd-pcrfs-root.service services are pulled in by the mount unit.
Note that this option can only be used in /etc/fstab, and will be ignored when part of the Options= setting in a unit file. It is also implied for the root and /usr/ partitions discovered by systemd-gpt-auto-generator(8). Note that this option can only be used in /etc/fstab, and will be ignored when part of the Options= setting in a unit file. It is also implied for the root and /usr/ partitions discovered by systemd-gpt-auto-generator(8).
@ -227,13 +227,13 @@ Added in version 253.`,
), ),
docvalues.CreateEnumStringWithDoc( docvalues.CreateEnumStringWithDoc(
"x-systemd.rw-only", "x-systemd.rw-only",
`If a mount operation fails to mount the file system read-write, it normally tries mounting the file system read-only instead. This option disables that behaviour, and causes the mount to fail immediately instead. This option is translated into the ReadWriteOnly= setting in a unit file. `If a mount operation fails to mount the file system read-write, it normally tries mounting the file system read-only instead. This option disables that behaviour, and causes the mount to fail immediately instead. This option is translated into the ReadWriteOnly= setting in a unit file.
Added in version 246.`, Added in version 246.`,
), ),
docvalues.CreateEnumStringWithDoc( docvalues.CreateEnumStringWithDoc(
"x-initrd.mount", "x-initrd.mount",
`An additional filesystem to be mounted in the initrd. See initrd-fs.target description in systemd.special(7). This is both an indicator to the initrd to mount this partition early and an indicator to the host to leave the partition mounted until final shutdown. Or in other words, if this flag is set it is assumed the mount shall be active during the entire regular runtime of the system, i.e. established before the initrd transitions into the host all the way until the host transitions to the final shutdown phase. `An additional filesystem to be mounted in the initrd. See initrd-fs.target description in systemd.special(7). This is both an indicator to the initrd to mount this partition early and an indicator to the host to leave the partition mounted until final shutdown. Or in other words, if this flag is set it is assumed the mount shall be active during the entire regular runtime of the system, i.e. established before the initrd transitions into the host all the way until the host transitions to the final shutdown phase.
Added in version 215.`, Added in version 215.`,
), ),
@ -299,19 +299,19 @@ Added in version 245.`,
): docvalues.StringValue{}, ): docvalues.StringValue{},
docvalues.CreateEnumStringWithDoc( docvalues.CreateEnumStringWithDoc(
"x-systemd.wants-mounts-for", "x-systemd.wants-mounts-for",
`Configures a RequiresMountsFor= or WantsMountsFor= dependency between the created mount unit and other mount units. The argument must be an absolute path. This option may be specified more than once. See RequiresMountsFor= or WantsMountsFor= in systemd.unit(5) for details. `Configures a RequiresMountsFor= or WantsMountsFor= dependency between the created mount unit and other mount units. The argument must be an absolute path. This option may be specified more than once. See RequiresMountsFor= or WantsMountsFor= in systemd.unit(5) for details.
Added in version 220.`, Added in version 220.`,
): docvalues.StringValue{}, ): docvalues.StringValue{},
docvalues.CreateEnumStringWithDoc( docvalues.CreateEnumStringWithDoc(
"x-systemd.requires-mounts-for", "x-systemd.requires-mounts-for",
`Configures a RequiresMountsFor= or WantsMountsFor= dependency between the created mount unit and other mount units. The argument must be an absolute path. This option may be specified more than once. See RequiresMountsFor= or WantsMountsFor= in systemd.unit(5) for details. `Configures a RequiresMountsFor= or WantsMountsFor= dependency between the created mount unit and other mount units. The argument must be an absolute path. This option may be specified more than once. See RequiresMountsFor= or WantsMountsFor= in systemd.unit(5) for details.
Added in version 220.`, Added in version 220.`,
): docvalues.StringValue{}, ): docvalues.StringValue{},
docvalues.CreateEnumStringWithDoc( docvalues.CreateEnumStringWithDoc(
"x-systemd.device-bound", "x-systemd.device-bound",
`Takes a boolean argument. If true or no argument, a BindsTo= dependency on the backing device is set. If false, the mount unit is not stopped no matter whether the backing device is still present. This is useful when the file system is backed by volume managers. If not set, and the mount comes from unit fragments, i.e. generated from /etc/fstab by systemd-fstab-generator(8) or loaded from a manually configured mount unit, a combination of Requires= and StopPropagatedFrom= dependencies is set on the backing device. If doesn't, only Requires= is used. `Takes a boolean argument. If true or no argument, a BindsTo= dependency on the backing device is set. If false, the mount unit is not stopped no matter whether the backing device is still present. This is useful when the file system is backed by volume managers. If not set, and the mount comes from unit fragments, i.e. generated from /etc/fstab by systemd-fstab-generator(8) or loaded from a manually configured mount unit, a combination of Requires= and StopPropagatedFrom= dependencies is set on the backing device. If doesn't, only Requires= is used.
Added in version 233.`, Added in version 233.`,
): docvalues.EnumValue{ ): docvalues.EnumValue{
@ -323,13 +323,13 @@ Added in version 233.`,
}, },
docvalues.CreateEnumStringWithDoc( docvalues.CreateEnumStringWithDoc(
"x-systemd.idle-timeout", "x-systemd.idle-timeout",
`Configures the idle timeout of the automount unit. See TimeoutIdleSec= in systemd.automount(5) for details. `Configures the idle timeout of the automount unit. See TimeoutIdleSec= in systemd.automount(5) for details.
Added in version 220.`, Added in version 220.`,
): docvalues.StringValue{}, ): docvalues.StringValue{},
docvalues.CreateEnumStringWithDoc( docvalues.CreateEnumStringWithDoc(
"x-systemd.device-timeout", "x-systemd.device-timeout",
`Configure how long systemd should wait for a device to show up before giving up on an entry from /etc/fstab. Specify a time in seconds or explicitly append a unit such as "s", "min", "h", "ms". `Configure how long systemd should wait for a device to show up before giving up on an entry from /etc/fstab. Specify a time in seconds or explicitly append a unit such as "s", "min", "h", "ms".
Note that this option can only be used in /etc/fstab, and will be ignored when part of the Options= setting in a unit file. Note that this option can only be used in /etc/fstab, and will be ignored when part of the Options= setting in a unit file.
@ -337,7 +337,7 @@ Added in version 215.`,
): docvalues.StringValue{}, ): docvalues.StringValue{},
docvalues.CreateEnumStringWithDoc( docvalues.CreateEnumStringWithDoc(
"x-systemd.mount-timeout", "x-systemd.mount-timeout",
`Configure how long systemd should wait for the mount command to finish before giving up on an entry from /etc/fstab. Specify a time in seconds or explicitly append a unit such as "s", "min", "h", "ms". `Configure how long systemd should wait for the mount command to finish before giving up on an entry from /etc/fstab. Specify a time in seconds or explicitly append a unit such as "s", "min", "h", "ms".
Note that this option can only be used in /etc/fstab, and will be ignored when part of the Options= setting in a unit file. Note that this option can only be used in /etc/fstab, and will be ignored when part of the Options= setting in a unit file.

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{}