diff --git a/internal/ls/lsutil/userpreferences.go b/internal/ls/lsutil/userpreferences.go index 8fc5146d634..9ce32c8dcdf 100644 --- a/internal/ls/lsutil/userpreferences.go +++ b/internal/ls/lsutil/userpreferences.go @@ -1,6 +1,7 @@ package lsutil import ( + "maps" "reflect" "slices" "strings" @@ -886,7 +887,21 @@ func ParseUserPreferences(items map[string]any) UserPreferences { // editor < javascript < typescript < js/ts if editorItem, ok := items["editor"]; ok && editorItem != nil { if editorSettings, ok := editorItem.(map[string]any); ok { - prefs = prefs.withConfig(map[string]any{"unstable": editorSettings}) + unstableEditorSettings := make(map[string]any, len(editorSettings)+2) + maps.Copy(unstableEditorSettings, editorSettings) + // VS Code editor settings use "insertSpaces" and "tabSize"; map them to + // tsserver raw formatting setting names consumed by "unstable". + if tabSize, ok := unstableEditorSettings["tabSize"]; ok { + if _, hasIndentSize := unstableEditorSettings["indentSize"]; !hasIndentSize { + unstableEditorSettings["indentSize"] = tabSize + } + } + if insertSpaces, ok := unstableEditorSettings["insertSpaces"]; ok { + if _, hasConvertTabs := unstableEditorSettings["convertTabsToSpaces"]; !hasConvertTabs { + unstableEditorSettings["convertTabsToSpaces"] = insertSpaces + } + } + prefs = prefs.withConfig(map[string]any{"unstable": unstableEditorSettings}) } } // Apply javascript, then typescript, then js/ts (highest precedence). diff --git a/internal/ls/lsutil/userpreferences_test.go b/internal/ls/lsutil/userpreferences_test.go index 153f737b345..bb597be2bf7 100644 --- a/internal/ls/lsutil/userpreferences_test.go +++ b/internal/ls/lsutil/userpreferences_test.go @@ -511,6 +511,34 @@ func TestUserPreferencesParseServerFeaturePreferences(t *testing.T) { }) } +func TestUserPreferencesParseEditorFormattingSettings(t *testing.T) { + t.Parallel() + + t.Run("editor insertSpaces and tabSize apply to format settings", func(t *testing.T) { + t.Parallel() + prefs := ParseUserPreferences(map[string]any{ + "editor": map[string]any{ + "tabSize": 2, + "insertSpaces": false, + }, + }) + assert.Equal(t, prefs.FormatCodeSettings.TabSize, 2) + assert.Equal(t, prefs.FormatCodeSettings.IndentSize, 2) + assert.Equal(t, prefs.FormatCodeSettings.ConvertTabsToSpaces, core.TSFalse) + }) + + t.Run("editor raw formatting setting wins over insertSpaces alias", func(t *testing.T) { + t.Parallel() + prefs := ParseUserPreferences(map[string]any{ + "editor": map[string]any{ + "insertSpaces": false, + "convertTabsToSpaces": true, + }, + }) + assert.Equal(t, prefs.FormatCodeSettings.ConvertTabsToSpaces, core.TSTrue) + }) +} + func TestUserPreferencesParseJSDocCompletionPreferences(t *testing.T) { t.Parallel()