From 5a13487db893e2123294297b40ea86b0f2db71e1 Mon Sep 17 00:00:00 2001 From: Myzel394 <50424412+Myzel394@users.noreply.github.com> Date: Wed, 9 Oct 2024 14:41:40 +0200 Subject: [PATCH] fix(fstab): Improvements; Bugfixes --- server/handlers/fstab/analyzer/values.go | 10 +- server/handlers/fstab/ast/fstab_fields.go | 49 +++- server/handlers/fstab/fields/mountoptions.go | 217 +++++++++--------- server/handlers/fstab/handlers/completions.go | 31 ++- server/handlers/fstab/handlers/hover.go | 11 +- 5 files changed, 178 insertions(+), 140 deletions(-) diff --git a/server/handlers/fstab/analyzer/values.go b/server/handlers/fstab/analyzer/values.go index 8ef69b9..fd6d731 100644 --- a/server/handlers/fstab/analyzer/values.go +++ b/server/handlers/fstab/analyzer/values.go @@ -16,11 +16,16 @@ func analyzeValuesAreValid( for it.Next() { entry := it.Value().(*ast.FstabEntry) + mountOptions := entry.FetchMountOptionsField(true) checkField(ctx, entry.Fields.Spec, fields.SpecField) checkField(ctx, entry.Fields.MountPoint, fields.MountPointField) checkField(ctx, entry.Fields.FilesystemType, fields.FileSystemTypeField) - checkField(ctx, entry.Fields.Options, entry.GetMountOptionsField()) + + if mountOptions != nil { + checkField(ctx, entry.Fields.Options, mountOptions) + } + checkField(ctx, entry.Fields.Freq, fields.FreqField) checkField(ctx, entry.Fields.Pass, fields.PassField) } @@ -34,8 +39,7 @@ func checkField( invalidValues := docOption.DeprecatedCheckIsValid(field.Value.Value) for _, invalidValue := range invalidValues { - err := docvalues.LSPErrorFromInvalidValue(field.Start.Line, *invalidValue) - err.ShiftCharacter(field.Start.Character) + err := docvalues.LSPErrorFromInvalidValue(field.Start.Line, *invalidValue).ShiftCharacter(field.Start.Character) ctx.diagnostics = append(ctx.diagnostics, protocol.Diagnostic{ Range: err.Range.ToLSPRange(), diff --git a/server/handlers/fstab/ast/fstab_fields.go b/server/handlers/fstab/ast/fstab_fields.go index b72877e..468f625 100644 --- a/server/handlers/fstab/ast/fstab_fields.go +++ b/server/handlers/fstab/ast/fstab_fields.go @@ -4,6 +4,7 @@ import ( "config-lsp/common" docvalues "config-lsp/doc-values" "config-lsp/handlers/fstab/fields" + "config-lsp/utils" ) // func (c FstabConfig) GetEntry(line uint32) *FstabEntry { @@ -40,16 +41,44 @@ func (e FstabEntry) GetFieldAtPosition(position common.Position) FstabFieldName return FstabFieldPass } -func (e FstabEntry) GetMountOptionsField() docvalues.DeprecatedValue { - fileSystemType := e.Fields.FilesystemType.Value.Value - - var optionsField docvalues.DeprecatedValue - - if foundField, found := fields.MountOptionsMapField[fileSystemType]; found { - optionsField = foundField - } else { - optionsField = fields.DefaultMountOptionsField +// Create a mount options field for the entry +func (e FstabEntry) FetchMountOptionsField(includeDefaults bool) docvalues.DeprecatedValue { + if e.Fields.FilesystemType == nil { + return nil } - return optionsField + option, found := fields.MountOptionsMapField[e.Fields.FilesystemType.Value.Value] + + if !found { + return nil + } + + var enums []docvalues.EnumString + var assignable map[docvalues.EnumString]docvalues.DeprecatedValue + + if includeDefaults { + enums = append(option.Enums, fields.DefaultOptions...) + assignable = utils.MergeMaps(option.Assignable, fields.DefaultAssignOptions) + } else { + enums = option.Enums + assignable = option.Assignable + } + + return &docvalues.ArrayValue{ + Separator: ",", + DuplicatesExtractor: &fields.MountOptionsExtractor, + SubValue: docvalues.OrValue{ + Values: []docvalues.DeprecatedValue{ + docvalues.KeyEnumAssignmentValue{ + Values: assignable, + ValueIsOptional: false, + Separator: "=", + }, + docvalues.EnumValue{ + EnforceValues: true, + Values: enums, + }, + }, + }, + } } diff --git a/server/handlers/fstab/fields/mountoptions.go b/server/handlers/fstab/fields/mountoptions.go index ed2d4ed..2ebf666 100644 --- a/server/handlers/fstab/fields/mountoptions.go +++ b/server/handlers/fstab/fields/mountoptions.go @@ -6,7 +6,7 @@ import ( "strings" ) -var mountOptionsExtractor = func(value string) string { +var MountOptionsExtractor = func(value string) string { separatorIndex := strings.Index(value, "=") if separatorIndex == -1 { @@ -17,7 +17,7 @@ var mountOptionsExtractor = func(value string) string { } // From https://www.man7.org/linux/man-pages/man8/mount.8.html -var defaultOptions = []docvalues.EnumString{ +var DefaultOptions = []docvalues.EnumString{ // Default options docvalues.CreateEnumStringWithDoc( "async", @@ -228,7 +228,7 @@ type assignOption struct { Handler func(context docvalues.KeyValueAssignmentContext) docvalues.DeprecatedValue } -var defaultAssignOptions = map[docvalues.EnumString]docvalues.DeprecatedValue{ +var DefaultAssignOptions = map[docvalues.EnumString]docvalues.DeprecatedValue{ docvalues.CreateEnumStringWithDoc( "context", "The context= option is useful when mounting filesystems that do not support extended attributes, such as a floppy or hard disk formatted with VFAT, or systems that are not normally running under SELinux, such as an ext3 or ext4 formatted disk from a non-SELinux workstation. You can also use context= on filesystems you do not trust, such as a floppy. It also helps in compatibility with xattr-supporting filesystems on earlier 2.4. kernel versions. Even where xattrs are supported, you can save time not having to label every file by assigning the entire disk one security context. A commonly used option for removable media is context=\"system_u:object_r:removable_t\".", @@ -347,7 +347,7 @@ func createMountOptionField( return docvalues.ArrayValue{ Separator: ",", - DuplicatesExtractor: &mountOptionsExtractor, + DuplicatesExtractor: &MountOptionsExtractor, SubValue: docvalues.OrValue{ Values: []docvalues.DeprecatedValue{ docvalues.KeyEnumAssignmentValue{ @@ -364,103 +364,114 @@ func createMountOptionField( } } -var DefaultMountOptionsField = createMountOptionField(defaultOptions, defaultAssignOptions) - -var MountOptionsMapField = map[string]docvalues.DeprecatedValue{ - "adfs": createMountOptionField( - commondocumentation.AdfsDocumentationEnums, - commondocumentation.AdfsDocumentationAssignable, - ), - "affs": createMountOptionField( - commondocumentation.AffsDocumentationEnums, - commondocumentation.AffsDocumentationAssignable, - ), - "btrfs": createMountOptionField( - commondocumentation.BtrfsDocumentationEnums, - commondocumentation.BtrfsDocumentationAssignable, - ), - "debugfs": createMountOptionField( - commondocumentation.DebugfsDocumentationEnums, - commondocumentation.DebugfsDocumentationAssignable, - ), - "ext2": createMountOptionField( - commondocumentation.Ext2DocumentationEnums, - commondocumentation.Ext2DocumentationAssignable, - ), - "ext3": createMountOptionField( - append(commondocumentation.Ext2DocumentationEnums, commondocumentation.Ext3DocumentationEnums...), - docvalues.MergeKeyEnumAssignmentMaps(commondocumentation.Ext2DocumentationAssignable, commondocumentation.Ext3DocumentationAssignable), - ), - "ext4": createMountOptionField( - append(append(commondocumentation.Ext2DocumentationEnums, commondocumentation.Ext3DocumentationEnums...), commondocumentation.Ext4DocumentationEnums...), - docvalues.MergeKeyEnumAssignmentMaps(commondocumentation.Ext2DocumentationAssignable, docvalues.MergeKeyEnumAssignmentMaps(commondocumentation.Ext3DocumentationAssignable, commondocumentation.Ext4DocumentationAssignable)), - ), - "devpts": createMountOptionField( - commondocumentation.DevptsDocumentationEnums, - commondocumentation.DevptsDocumentationAssignable, - ), - "fat": createMountOptionField( - commondocumentation.FatDocumentationEnums, - commondocumentation.FatDocumentationAssignable, - ), - "hfs": createMountOptionField( - commondocumentation.HfsDocumentationEnums, - commondocumentation.HfsDocumentationAssignable, - ), - "hpfs": createMountOptionField( - commondocumentation.HpfsDocumentationEnums, - commondocumentation.HpfsDocumentationAssignable, - ), - "iso9660": createMountOptionField( - commondocumentation.Iso9660DocumentationEnums, - commondocumentation.Iso9660DocumentationAssignable, - ), - "jfs": createMountOptionField( - commondocumentation.JfsDocumentationEnums, - commondocumentation.JfsDocumentationAssignable, - ), - "msdos": createMountOptionField( - commondocumentation.MsdosDocumentationEnums, - commondocumentation.MsdosDocumentationAssignable, - ), - "ncpfs": createMountOptionField( - commondocumentation.NcpfsDocumentationEnums, - commondocumentation.NcpfsDocumentationAssignable, - ), - "ntfs": createMountOptionField( - commondocumentation.NtfsDocumentationEnums, - commondocumentation.NtfsDocumentationAssignable, - ), - "overlay": createMountOptionField( - commondocumentation.OverlayDocumentationEnums, - commondocumentation.OverlayDocumentationAssignable, - ), - "reiserfs": createMountOptionField( - commondocumentation.ReiserfsDocumentationEnums, - commondocumentation.ReiserfsDocumentationAssignable, - ), - "usbfs": createMountOptionField( - commondocumentation.UsbfsDocumentationEnums, - commondocumentation.UsbfsDocumentationAssignable, - ), - "ubifs": createMountOptionField( - commondocumentation.UbifsDocumentationEnums, - commondocumentation.UbifsDocumentationAssignable, - ), - "udf": createMountOptionField( - commondocumentation.UdfDocumentationEnums, - commondocumentation.UdfDocumentationAssignable, - ), - "ufs": createMountOptionField( - commondocumentation.UfsDocumentationEnums, - commondocumentation.UfsDocumentationAssignable, - ), - "umsdos": createMountOptionField( - commondocumentation.UmsdosDocumentationEnums, - commondocumentation.UmsdosDocumentationAssignable, - ), - "vfat": createMountOptionField( - commondocumentation.VfatDocumentationEnums, - commondocumentation.VfatDocumentationAssignable, - ), +type optionField struct { + Assignable map[docvalues.EnumString]docvalues.DeprecatedValue + Enums []docvalues.EnumString +} + +var DefaultMountOptionsField = createMountOptionField(DefaultOptions, DefaultAssignOptions) + +var MountOptionsMapField = map[string]optionField{ + "adfs": { + Enums: commondocumentation.AdfsDocumentationEnums, + Assignable: commondocumentation.AdfsDocumentationAssignable, + }, + "affs": { + Enums: commondocumentation.AffsDocumentationEnums, + Assignable: commondocumentation.AffsDocumentationAssignable, + }, + "btrfs": { + Enums: commondocumentation.BtrfsDocumentationEnums, + Assignable: commondocumentation.BtrfsDocumentationAssignable, + }, + "debugfs": { + Enums: commondocumentation.DebugfsDocumentationEnums, + Assignable: commondocumentation.DebugfsDocumentationAssignable, + }, + "ext2": { + Enums: commondocumentation.Ext2DocumentationEnums, + Assignable: commondocumentation.Ext2DocumentationAssignable, + }, + "ext3": { + Enums: append(commondocumentation.Ext2DocumentationEnums, commondocumentation.Ext3DocumentationEnums...), + Assignable: docvalues.MergeKeyEnumAssignmentMaps(commondocumentation.Ext2DocumentationAssignable, commondocumentation.Ext3DocumentationAssignable), + }, + "ext4": { + Enums: append( + append( + commondocumentation.Ext2DocumentationEnums, + commondocumentation.Ext3DocumentationEnums..., + ), + commondocumentation.Ext4DocumentationEnums..., + ), + Assignable: docvalues.MergeKeyEnumAssignmentMaps(commondocumentation.Ext2DocumentationAssignable, docvalues.MergeKeyEnumAssignmentMaps(commondocumentation.Ext3DocumentationAssignable, commondocumentation.Ext4DocumentationAssignable)), + }, + "devpts": { + Enums: commondocumentation.DevptsDocumentationEnums, + Assignable: commondocumentation.DevptsDocumentationAssignable, + }, + "fat": { + Enums: commondocumentation.FatDocumentationEnums, + Assignable: commondocumentation.FatDocumentationAssignable, + }, + "hfs": { + Enums: commondocumentation.HfsDocumentationEnums, + Assignable: commondocumentation.HfsDocumentationAssignable, + }, + "hpfs": { + Enums: commondocumentation.HpfsDocumentationEnums, + Assignable: commondocumentation.HpfsDocumentationAssignable, + }, + "iso9660": { + Enums: commondocumentation.Iso9660DocumentationEnums, + Assignable: commondocumentation.Iso9660DocumentationAssignable, + }, + "jfs": { + Enums: commondocumentation.JfsDocumentationEnums, + Assignable: commondocumentation.JfsDocumentationAssignable, + }, + "msdos": { + Enums: commondocumentation.MsdosDocumentationEnums, + Assignable: commondocumentation.MsdosDocumentationAssignable, + }, + "ncpfs": { + Enums: commondocumentation.NcpfsDocumentationEnums, + Assignable: commondocumentation.NcpfsDocumentationAssignable, + }, + "ntfs": { + Enums: commondocumentation.NtfsDocumentationEnums, + Assignable: commondocumentation.NtfsDocumentationAssignable, + }, + "overlay": { + Enums: commondocumentation.OverlayDocumentationEnums, + Assignable: commondocumentation.OverlayDocumentationAssignable, + }, + "reiserfs": { + Enums: commondocumentation.ReiserfsDocumentationEnums, + Assignable: commondocumentation.ReiserfsDocumentationAssignable, + }, + "usbfs": { + Enums: commondocumentation.UsbfsDocumentationEnums, + Assignable: commondocumentation.UsbfsDocumentationAssignable, + }, + "ubifs": { + Enums: commondocumentation.UbifsDocumentationEnums, + Assignable: commondocumentation.UbifsDocumentationAssignable, + }, + "udf": { + Enums: commondocumentation.UdfDocumentationEnums, + Assignable: commondocumentation.UdfDocumentationAssignable, + }, + "ufs": { + Enums: commondocumentation.UfsDocumentationEnums, + Assignable: commondocumentation.UfsDocumentationAssignable, + }, + "umsdos": { + Enums: commondocumentation.UmsdosDocumentationEnums, + Assignable: commondocumentation.UmsdosDocumentationAssignable, + }, + "vfat": { + Enums: commondocumentation.VfatDocumentationEnums, + Assignable: commondocumentation.VfatDocumentationAssignable, + }, } diff --git a/server/handlers/fstab/handlers/completions.go b/server/handlers/fstab/handlers/completions.go index 8b4598c..9d10d90 100644 --- a/server/handlers/fstab/handlers/completions.go +++ b/server/handlers/fstab/handlers/completions.go @@ -42,6 +42,7 @@ func GetCompletion( fileSystemType := entry.Fields.FilesystemType.Value.Value completions := make([]protocol.CompletionItem, 0, 50) + println("fetching field options now", line, cursor) for _, completion := range fields.DefaultMountOptionsField.DeprecatedFetchCompletions(line, cursor) { var documentation string @@ -59,23 +60,21 @@ func GetCompletion( completions = append(completions, completion) } - if optionsField, found := fields.MountOptionsMapField[fileSystemType]; found { - for _, completion := range optionsField.DeprecatedFetchCompletions(line, cursor) { - var documentation string + for _, completion := range entry.FetchMountOptionsField(false).DeprecatedFetchCompletions(line, cursor) { + var documentation string - switch completion.Documentation.(type) { - case string: - documentation = completion.Documentation.(string) - case *string: - documentation = *completion.Documentation.(*string) - } - - completion.Documentation = protocol.MarkupContent{ - Kind: protocol.MarkupKindMarkdown, - Value: documentation + "\n\n" + fmt.Sprintf("From: _%s_", fileSystemType), - } - completions = append(completions, completion) + switch completion.Documentation.(type) { + case string: + documentation = completion.Documentation.(string) + case *string: + documentation = *completion.Documentation.(*string) } + + completion.Documentation = protocol.MarkupContent{ + Kind: protocol.MarkupKindMarkdown, + Value: documentation + "\n\n" + fmt.Sprintf("From: _%s_", fileSystemType), + } + completions = append(completions, completion) } return completions, nil @@ -109,5 +108,5 @@ func getFieldSafely(field *ast.FstabField, cursor common.CursorPosition) (string return "", 0 } - return field.Value.Raw, common.CursorToCharacterIndex(uint32(cursor)) - field.Start.Character + return field.Value.Raw, common.CursorToCharacterIndex(uint32(cursor) - field.Start.Character) } diff --git a/server/handlers/fstab/handlers/hover.go b/server/handlers/fstab/handlers/hover.go index 1c4997d..0216a62 100644 --- a/server/handlers/fstab/handlers/hover.go +++ b/server/handlers/fstab/handlers/hover.go @@ -2,9 +2,7 @@ package handlers import ( "config-lsp/common" - "config-lsp/doc-values" "config-lsp/handlers/fstab/ast" - "config-lsp/handlers/fstab/fields" "strings" "github.com/tliron/glsp/protocol_3_16" @@ -25,13 +23,10 @@ func GetHoverInfo( case ast.FstabFieldFileSystemType: return &FileSystemTypeField, nil case ast.FstabFieldOptions: - fileSystemType := entry.Fields.FilesystemType.Value.Value - var optionsField docvalues.DeprecatedValue + optionsField := entry.FetchMountOptionsField(true) - if foundField, found := fields.MountOptionsMapField[fileSystemType]; found { - optionsField = foundField - } else { - optionsField = fields.DefaultMountOptionsField + if optionsField == nil { + return nil, nil } relativeCursor := uint32(index) - entry.Fields.Options.Start.Character