diff --git a/internal/fourslash/fourslash.go b/internal/fourslash/fourslash.go index a488f7d2c5..98fc8474d4 100644 --- a/internal/fourslash/fourslash.go +++ b/internal/fourslash/fourslash.go @@ -42,6 +42,7 @@ type FourslashTest struct { scriptInfos map[string]*scriptInfo converters *ls.Converters + userPreferences *ls.UserPreferences currentCaretPosition lsproto.Position lastKnownMarkerName *string activeFilename string @@ -268,6 +269,29 @@ func sendRequest[Params, Resp any](t *testing.T, f *FourslashTest, info lsproto. ) f.writeMsg(t, req.Message()) resp := f.readMsg(t) + if resp == nil { + return nil, *new(Resp), false + } + + // currently, the only request that may be sent by the server during a client request is one `config` request + // !!! remove if `config` is handled in initialization and there are no other server-initiated requests + if resp.Kind == lsproto.MessageKindRequest { + req := resp.AsRequest() + switch req.Method { + case lsproto.MethodWorkspaceConfiguration: + req := lsproto.ResponseMessage{ + ID: req.ID, + JSONRPC: req.JSONRPC, + Result: []any{f.userPreferences}, + } + f.writeMsg(t, req.Message()) + resp = f.readMsg(t) + default: + // other types of responses not yet used in fourslash; implement them if needed + t.Fatalf("Unexpected request received: %s", req) + } + } + if resp == nil { return nil, *new(Resp), false } @@ -300,6 +324,21 @@ func (f *FourslashTest) readMsg(t *testing.T) *lsproto.Message { return msg } +func (f *FourslashTest) Configure(t *testing.T, config *ls.UserPreferences) { + f.userPreferences = config + sendNotification(t, f, lsproto.WorkspaceDidChangeConfigurationInfo, &lsproto.DidChangeConfigurationParams{ + Settings: config, + }) +} + +func (f *FourslashTest) ConfigureWithReset(t *testing.T, config *ls.UserPreferences) (reset func()) { + originalConfig := f.userPreferences.Copy() + f.Configure(t, config) + return func() { + f.Configure(t, originalConfig) + } +} + func (f *FourslashTest) GoToMarkerOrRange(t *testing.T, markerOrRange MarkerOrRange) { f.goToMarker(t, markerOrRange) } @@ -541,6 +580,10 @@ func (f *FourslashTest) verifyCompletionsWorker(t *testing.T, expected *Completi Position: f.currentCaretPosition, Context: &lsproto.CompletionContext{}, } + if expected != nil && expected.UserPreferences != nil { + reset := f.ConfigureWithReset(t, expected.UserPreferences) + defer reset() + } resMsg, result, resultOk := sendRequest(t, f, lsproto.TextDocumentCompletionInfo, params) if resMsg == nil { t.Fatalf(prefix+"Nil response received for completion request", f.lastKnownMarkerName) @@ -1449,6 +1492,12 @@ func (f *FourslashTest) getCurrentPositionPrefix() string { } func (f *FourslashTest) BaselineAutoImportsCompletions(t *testing.T, markerNames []string) { + reset := f.ConfigureWithReset(t, &ls.UserPreferences{ + IncludeCompletionsForModuleExports: core.TSTrue, + IncludeCompletionsForImportStatements: core.TSTrue, + }) + defer reset() + for _, markerName := range markerNames { f.GoToMarker(t, markerName) params := &lsproto.CompletionParams{ diff --git a/internal/fourslash/tests/autoImportCompletion_test.go b/internal/fourslash/tests/autoImportCompletion_test.go index 7c5aeaf356..078eeac2c8 100644 --- a/internal/fourslash/tests/autoImportCompletion_test.go +++ b/internal/fourslash/tests/autoImportCompletion_test.go @@ -40,6 +40,21 @@ a/**/ }, }) f.BaselineAutoImportsCompletions(t, []string{""}) + f.VerifyCompletions(t, "", &fourslash.CompletionsExpectedList{ + UserPreferences: &ls.UserPreferences{ + // completion autoimport preferences off; this tests if fourslash server communication correctly registers changes in user preferences + IncludeCompletionsForModuleExports: core.TSUnknown, + IncludeCompletionsForImportStatements: core.TSUnknown, + }, + IsIncomplete: false, + ItemDefaults: &fourslash.CompletionsExpectedItemDefaults{ + CommitCharacters: &DefaultCommitCharacters, + EditRange: Ignored, + }, + Items: &fourslash.CompletionsExpectedItems{ + Excludes: []string{"anotherVar"}, + }, + }) } func TestAutoImportCompletion2(t *testing.T) { diff --git a/internal/ls/host.go b/internal/ls/host.go index dfeaa02a62..d5bdb03347 100644 --- a/internal/ls/host.go +++ b/internal/ls/host.go @@ -1,10 +1,13 @@ package ls -import "github.com/microsoft/typescript-go/internal/sourcemap" +import ( + "github.com/microsoft/typescript-go/internal/sourcemap" +) type Host interface { UseCaseSensitiveFileNames() bool ReadFile(path string) (contents string, ok bool) Converters() *Converters + UserPreferences() *UserPreferences GetECMALineInfo(fileName string) *sourcemap.ECMALineInfo } diff --git a/internal/ls/languageservice.go b/internal/ls/languageservice.go index c7c4596dce..d2fa5c886d 100644 --- a/internal/ls/languageservice.go +++ b/internal/ls/languageservice.go @@ -30,6 +30,10 @@ func (l *LanguageService) GetProgram() *compiler.Program { return l.program } +func (l *LanguageService) UserPreferences() *UserPreferences { + return l.host.UserPreferences() +} + func (l *LanguageService) tryGetProgramAndFile(fileName string) (*compiler.Program, *ast.SourceFile) { program := l.GetProgram() file := program.GetSourceFile(fileName) diff --git a/internal/ls/userpreferences.go b/internal/ls/userpreferences.go index 11be04d64a..99e65e80e5 100644 --- a/internal/ls/userpreferences.go +++ b/internal/ls/userpreferences.go @@ -1,10 +1,27 @@ package ls import ( + "strings" + "github.com/microsoft/typescript-go/internal/core" "github.com/microsoft/typescript-go/internal/modulespecifiers" + "github.com/microsoft/typescript-go/internal/tsoptions" ) +func NewDefaultUserPreferences() *UserPreferences { + return &UserPreferences{ + IncludeCompletionsForModuleExports: core.TSTrue, + IncludeCompletionsForImportStatements: core.TSTrue, + + AllowRenameOfImportPath: true, + ProvideRefactorNotApplicableReason: true, + IncludeCompletionsWithSnippetText: core.TSTrue, + DisplayPartsForJSDoc: true, + DisableLineTextInReferences: true, + InteractiveInlayHints: true, + } +} + type UserPreferences struct { QuotePreference QuotePreference LazyConfiguredProjectsFromExternalProject bool // !!! @@ -84,7 +101,7 @@ type UserPreferences struct { // This preference is ignored if organizeImportsCollation is not `unicode`. // // Default: `true` - OrganizeImportsAccentCollation OrganizeImportsAccentCollation // !!! + OrganizeImportsAccentCollation bool // !!! // Indicates whether upper case or lower case should sort first. When `false`, the default order for the locale // specified in organizeImportsCollationLocale is used. // @@ -97,7 +114,7 @@ type UserPreferences struct { OrganizeImportsCaseFirst OrganizeImportsCaseFirst // !!! // Indicates where named type-only imports should sort. "inline" sorts named imports without regard to if the import is type-only. // - // Default: `last` + // Default: `auto`, which defaults to `last` OrganizeImportsTypeOrder OrganizeImportsTypeOrder // !!! // ------- MoveToFile ------- @@ -137,12 +154,52 @@ type UserPreferences struct { type JsxAttributeCompletionStyle string const ( - JsxAttributeCompletionStyleUnknown JsxAttributeCompletionStyle = "" + JsxAttributeCompletionStyleUnknown JsxAttributeCompletionStyle = "" // !!! JsxAttributeCompletionStyleAuto JsxAttributeCompletionStyle = "auto" JsxAttributeCompletionStyleBraces JsxAttributeCompletionStyle = "braces" JsxAttributeCompletionStyleNone JsxAttributeCompletionStyle = "none" ) +func parseJsxAttributeCompletionStyle(val any) JsxAttributeCompletionStyle { + if s, ok := val.(string); ok { + switch strings.ToLower(s) { + case "braces": + return JsxAttributeCompletionStyleBraces + case "none": + return JsxAttributeCompletionStyleNone + } + } + return JsxAttributeCompletionStyleAuto +} + +func parseImportModuleSpecifierPreference(val any) modulespecifiers.ImportModuleSpecifierPreference { + if s, ok := val.(string); ok { + switch strings.ToLower(s) { + case "project-relative": + return modulespecifiers.ImportModuleSpecifierPreferenceProjectRelative + case "relative": + return modulespecifiers.ImportModuleSpecifierPreferenceRelative + case "non-relative": + return modulespecifiers.ImportModuleSpecifierPreferenceNonRelative + } + } + return modulespecifiers.ImportModuleSpecifierPreferenceShortest +} + +func parseImportModuleSpecifierEndingPreference(val any) modulespecifiers.ImportModuleSpecifierEndingPreference { + if s, ok := val.(string); ok { + switch strings.ToLower(s) { + case "minimal": + return modulespecifiers.ImportModuleSpecifierEndingPreferenceMinimal + case "index": + return modulespecifiers.ImportModuleSpecifierEndingPreferenceIndex + case "js": + return modulespecifiers.ImportModuleSpecifierEndingPreferenceJs + } + } + return modulespecifiers.ImportModuleSpecifierEndingPreferenceAuto +} + type IncludeInlayParameterNameHints string const ( @@ -151,15 +208,41 @@ const ( IncludeInlayParameterNameHintsLiterals IncludeInlayParameterNameHints = "literals" ) +func parseInlayParameterNameHints(val any) IncludeInlayParameterNameHints { + if prefStr, ok := val.(string); ok { + switch prefStr { + case "all": + return IncludeInlayParameterNameHintsAll + case "literals": + return IncludeInlayParameterNameHintsLiterals + } + } + return IncludeInlayParameterNameHintsNone +} + type IncludePackageJsonAutoImports string const ( - IncludePackageJsonAutoImportsUnknown IncludePackageJsonAutoImports = "" + IncludePackageJsonAutoImportsUnknown IncludePackageJsonAutoImports = "" // !!! IncludePackageJsonAutoImportsAuto IncludePackageJsonAutoImports = "auto" IncludePackageJsonAutoImportsOn IncludePackageJsonAutoImports = "on" IncludePackageJsonAutoImportsOff IncludePackageJsonAutoImports = "off" ) +func parseIncludePackageJsonAutoImports(val any) IncludePackageJsonAutoImports { + if s, ok := val.(string); ok { + switch strings.ToLower(s) { + case "on": + return IncludePackageJsonAutoImportsOn + case "off": + return IncludePackageJsonAutoImportsOff + default: + return IncludePackageJsonAutoImportsAuto + } + } + return IncludePackageJsonAutoImportsUnknown +} + type OrganizeImportsCollation bool const ( @@ -167,12 +250,12 @@ const ( OrganizeImportsCollationUnicode OrganizeImportsCollation = true ) -type OrganizeImportsAccentCollation int - -const ( - OrganizeImportsAccentCollationTrue OrganizeImportsAccentCollation = 0 - OrganizeImportsAccentCollationFalse OrganizeImportsAccentCollation = 1 -) +func parseOrganizeImportsCollation(val any) OrganizeImportsCollation { + if b, ok := val.(string); ok && strings.ToLower(b) == "unicode" { + return OrganizeImportsCollationUnicode + } + return OrganizeImportsCollationOrdinal +} type OrganizeImportsCaseFirst int @@ -182,14 +265,41 @@ const ( OrganizeImportsCaseFirstUpper OrganizeImportsCaseFirst = 2 ) +func parseOrganizeImportsCaseFirst(caseFirst any) OrganizeImportsCaseFirst { + if caseFirstStr, ok := caseFirst.(string); ok { + switch caseFirstStr { + case "lower": + return OrganizeImportsCaseFirstLower + case "upper": + return OrganizeImportsCaseFirstUpper + } + } + return OrganizeImportsCaseFirstFalse +} + type OrganizeImportsTypeOrder int const ( - OrganizeImportsTypeOrderLast OrganizeImportsTypeOrder = 0 - OrganizeImportsTypeOrderInline OrganizeImportsTypeOrder = 1 - OrganizeImportsTypeOrderFirst OrganizeImportsTypeOrder = 2 + OrganizeImportsTypeOrderAuto OrganizeImportsTypeOrder = 0 + OrganizeImportsTypeOrderLast OrganizeImportsTypeOrder = 1 + OrganizeImportsTypeOrderInline OrganizeImportsTypeOrder = 2 + OrganizeImportsTypeOrderFirst OrganizeImportsTypeOrder = 3 ) +func parseOrganizeImportsTypeOrder(typeOrder any) OrganizeImportsTypeOrder { + if typeOrderStr, ok := typeOrder.(string); ok { + switch typeOrderStr { + case "last": + return OrganizeImportsTypeOrderLast + case "inline": + return OrganizeImportsTypeOrderInline + case "first": + return OrganizeImportsTypeOrderFirst + } + } + return OrganizeImportsTypeOrderAuto +} + type QuotePreference string const ( @@ -199,7 +309,35 @@ const ( QuotePreferenceSingle QuotePreference = "single" ) -func (p *UserPreferences) Parse(config map[string]interface{}) { +func parseQuotePreference(val any) QuotePreference { + if s, ok := val.(string); ok { + switch strings.ToLower(s) { + case "auto": + return QuotePreferenceAuto + case "double": + return QuotePreferenceDouble + case "single": + return QuotePreferenceSingle + } + } + return QuotePreferenceUnknown +} + +func (p *UserPreferences) Copy() *UserPreferences { + if p == nil { + return nil + } + prefCopy := *p + copy(prefCopy.AutoImportSpecifierExcludeRegexes, p.AutoImportSpecifierExcludeRegexes) + copy(prefCopy.AutoImportFileExcludePatterns, p.AutoImportFileExcludePatterns) + return &prefCopy +} + +func (p *UserPreferences) CopyOrDefault() *UserPreferences { + if p == nil { + return NewDefaultUserPreferences() + } + return p.Copy() } func (p *UserPreferences) ModuleSpecifierPreferences() modulespecifiers.UserPreferences { @@ -209,3 +347,287 @@ func (p *UserPreferences) ModuleSpecifierPreferences() modulespecifiers.UserPref AutoImportSpecifierExcludeRegexes: p.AutoImportSpecifierExcludeRegexes, } } + +// ------ Parsing Config Response ------- + +// returns non-nil if should break loop +func (p *UserPreferences) Parse(item any) *UserPreferences { + if item == nil { + // continue + } else if config, ok := item.(map[string]any); ok { + p.parseWorker(config) + } else if item, ok := item.(*UserPreferences); ok { + // case for fourslash + return item.CopyOrDefault() + } + return nil +} + +func (p *UserPreferences) parseWorker(config map[string]interface{}) { + // Process unstable preferences first so that they do not overwrite stable properties + if unstable, ok := config["unstable"]; ok { + // unstable properties must be named the same as userPreferences + p.parseAll(unstable) + } + for name, values := range config { + switch name { + case "unstable": + continue + case "inlayHints": + p.parseInlayHints(values) + case "suggest": + p.parseSuggest(values) + case "preferences": + p.parsePreferences(values) + case "tsserver": + // !!! + case "tsc": + // !!! + case "experimental": + // !!! + default: + p.set(name, values) + } + } +} + +func (p *UserPreferences) parseAll(prefs any) { + prefsMap, ok := prefs.(map[string]any) + if !ok { + return + } + for name, value := range prefsMap { + p.set(name, value) + } +} + +func (p *UserPreferences) parseInlayHints(prefs any) { + inlayHintsPreferences, ok := prefs.(map[string]any) + if !ok { + return + } + for name, value := range inlayHintsPreferences { + if v, ok := value.(map[string]any); ok { + // vscode's inlay hints settings are nested objects with "enabled" and other properties + switch name { + case "parameterNames": + if enabled, ok := v["enabled"]; ok { + p.set("includeInlayParameterNameHints", enabled) + } + p.IncludeInlayParameterNameHintsWhenArgumentMatchesName = parseSupress(v, "supressWhenArgumentMatchesName") + case "parameterTypes": + p.IncludeInlayFunctionParameterTypeHints = parseEnabledBool(v) + case "variableTypes": + p.IncludeInlayVariableTypeHints = parseEnabledBool(v) + p.IncludeInlayVariableTypeHintsWhenTypeMatchesName = parseSupress(v, "supressWhenTypeMatchesName") + case "propertyDeclarationTypes": + p.IncludeInlayPropertyDeclarationTypeHints = parseEnabledBool(v) + case "functionLikeReturnTypes": + p.IncludeInlayFunctionLikeReturnTypeHints = parseEnabledBool(v) + case "enumMemberValues": + p.IncludeInlayEnumMemberValueHints = parseEnabledBool(v) + } + } else { + // non-vscode case + p.set(name, v) + } + } +} + +func (p *UserPreferences) parseSuggest(prefs any) { + completionsPreferences, ok := prefs.(map[string]any) + if !ok { + return + } + for name, value := range completionsPreferences { + switch name { + case "autoImports": + p.set("includeCompletionsForModuleExports", value) + case "objectLiteralMethodSnippets": + if v, ok := value.(map[string]any); ok { + p.set("includeCompletionsWithObjectLiteralMethodSnippets", parseEnabledBool(v)) + } + case "classMemberSnippets": + if v, ok := value.(map[string]any); ok { + p.set("includeCompletionsWithClassMemberSnippets", parseEnabledBool(v)) + } + case "includeAutomaticOptionalChainCompletions": + p.set("includeAutomaticOptionalChainCompletions", value) + case "includeCompletionsForImportStatements": + p.set("includeCompletionsForImportStatements", value) + } + } +} + +func (p *UserPreferences) parsePreferences(prefs any) { + prefsMap, ok := prefs.(map[string]any) + if !ok { + return + } + for name, value := range prefsMap { + if name == "organizeImports" { + p.parseOrganizeImportsPreferences(value) + } else { + p.set(name, value) + } + } +} + +func (p *UserPreferences) parseOrganizeImportsPreferences(prefs any) { + // !!! this used to be in the typescript-language-features extension + prefsMap, ok := prefs.(map[string]any) + if !ok { + return + } + if typeOrder, ok := prefsMap["typeOrder"]; ok { + p.set("organizeimportstypeorder", parseOrganizeImportsTypeOrder(typeOrder)) + } + if caseSensitivity, ok := prefsMap["caseSensitivity"]; ok { + if caseSensitivityStr, ok := caseSensitivity.(string); ok { + // default is already "auto" + switch caseSensitivityStr { + case "caseInsensitive": + p.OrganizeImportsIgnoreCase = core.TSTrue + case "caseSensitive": + p.OrganizeImportsIgnoreCase = core.TSFalse + } + } + } + if collation, ok := prefsMap["unicodeCollation"]; ok { + // The rest of the settings are only applicable when using unicode collation + if collationStr, ok := collation.(string); ok && collationStr == "unicode" { + p.set("organizeimportscollation", OrganizeImportsCollationUnicode) + if locale, ok := prefsMap["locale"]; ok { + p.set("organizeimportslocale", locale) + } + if numeric, ok := prefsMap["numericCollation"]; ok { + p.set("organizeimportsnumericcollation", numeric) + } + if accent, ok := prefsMap["accentCollation"]; ok { + p.set("organizeimportsaccentcollation", accent) + } + if caseFirst, ok := prefsMap["caseFirst"]; ok && !p.OrganizeImportsIgnoreCase.IsTrue() { + p.set("organizeimportscasefirst", caseFirst) + } + } + } +} + +func parseEnabledBool(v map[string]any) bool { + // vscode nested option + if enabled, ok := v["enabled"]; ok { + if e, ok := enabled.(bool); ok { + return e + } + } + return false +} + +func parseSupress(v map[string]any, name string) bool { + // vscode nested option + if val, ok := v[name]; ok { + if suppress, ok := val.(bool); ok { + return !suppress + } + } + return false +} + +func parseBoolWithDefault(val any, defaultV bool) bool { + if v, ok := val.(bool); ok { + return v + } + return defaultV +} + +func parseIntWithDefault(val any, defaultV int) int { + if v, ok := val.(int); ok { + return v + } + return defaultV +} + +func (p *UserPreferences) set(name string, value any) { + switch strings.ToLower(name) { + case "quotePreference": + p.QuotePreference = parseQuotePreference(value) + case "lazyconfiguredprojectsfromexternalproject": + p.LazyConfiguredProjectsFromExternalProject = parseBoolWithDefault(value, false) + case "maximumhoverlength": + p.MaximumHoverLength = parseIntWithDefault(value, 500) + case "includecompletionsformoduleexports": + p.IncludeCompletionsForModuleExports = tsoptions.ParseTristate(value) + case "includecompletionsforimportstatements": + p.IncludeCompletionsForImportStatements = tsoptions.ParseTristate(value) + case "includeautomaticoptionalchaincompletions": + p.IncludeAutomaticOptionalChainCompletions = tsoptions.ParseTristate(value) + case "includecompletionswithsnippettext": + p.IncludeCompletionsWithSnippetText = tsoptions.ParseTristate(value) + case "includecompletionswithclassmembersnippets": + p.IncludeCompletionsWithClassMemberSnippets = tsoptions.ParseTristate(value) + case "includecompletionswithobjectliteralmethodsnippets": + p.IncludeCompletionsWithObjectLiteralMethodSnippets = tsoptions.ParseTristate(value) + case "jsxattributecompletionstyle": + p.JsxAttributeCompletionStyle = parseJsxAttributeCompletionStyle(value) + case "importmodulespecifierpreference": + p.ImportModuleSpecifierPreference = parseImportModuleSpecifierPreference(value) + case "importmodulespecifierending": + p.ImportModuleSpecifierEnding = parseImportModuleSpecifierEndingPreference(value) + case "includepackagejsonautoimports": + p.IncludePackageJsonAutoImports = parseIncludePackageJsonAutoImports(value) + case "autoimportspecifierexcluderegexes": + p.AutoImportSpecifierExcludeRegexes = tsoptions.ParseStringArray(value) + case "autoimportfileexcludepatterns": + p.AutoImportFileExcludePatterns = tsoptions.ParseStringArray(value) + case "prefertypeonlyautoimports": + p.PreferTypeOnlyAutoImports = parseBoolWithDefault(value, false) + case "organizeimportsignorecase": + p.OrganizeImportsIgnoreCase = tsoptions.ParseTristate(value) + case "organizeimportscollation": + p.OrganizeImportsCollation = parseOrganizeImportsCollation(value) + case "organizeimportslocale": + p.OrganizeImportsLocale = tsoptions.ParseString(value) + case "organizeimportsnumericcollation": + p.OrganizeImportsNumericCollation = parseBoolWithDefault(value, false) + case "organizeimportsaccentcollation": + p.OrganizeImportsAccentCollation = parseBoolWithDefault(value, true) + case "organizeimportscasefirst": + p.OrganizeImportsCaseFirst = parseOrganizeImportsCaseFirst(value) + case "organizeimportstypeorder": + p.OrganizeImportsTypeOrder = parseOrganizeImportsTypeOrder(value) + case "allowtextchangesinnewfiles": + p.AllowTextChangesInNewFiles = parseBoolWithDefault(value, true) // !!! + case "usealiasesforrename", "provideprefixandsuffixtextforrename": + p.UseAliasesForRename = tsoptions.ParseTristate(value) + case "allowrenameofimportpath": + p.AllowRenameOfImportPath = parseBoolWithDefault(value, true) + case "providerefactornotapplicablereason": + p.ProvideRefactorNotApplicableReason = parseBoolWithDefault(value, true) + case "includeinlayparameternamehints": + p.IncludeInlayParameterNameHints = parseInlayParameterNameHints(value) + case "includeinlayparameternamehintswhenargumentmatchesname": + p.IncludeInlayParameterNameHintsWhenArgumentMatchesName = parseBoolWithDefault(value, false) + case "includeinlayfunctionparametertypeHints": + p.IncludeInlayFunctionParameterTypeHints = parseBoolWithDefault(value, false) + case "includeinlayvariabletypehints": + p.IncludeInlayVariableTypeHints = parseBoolWithDefault(value, false) + case "includeinlayvariabletypehintswhentypematchesname": + p.IncludeInlayVariableTypeHintsWhenTypeMatchesName = parseBoolWithDefault(value, false) + case "includeinlaypropertydeclarationtypehints": + p.IncludeInlayPropertyDeclarationTypeHints = parseBoolWithDefault(value, false) + case "includeinlayfunctionlikereturntypehints": + p.IncludeInlayFunctionLikeReturnTypeHints = parseBoolWithDefault(value, false) + case "includeinlayenummembervaluehints": + p.IncludeInlayEnumMemberValueHints = parseBoolWithDefault(value, false) + case "interactiveinlayhints": + p.InteractiveInlayHints = parseBoolWithDefault(value, true) + case "excludelibrarysymbolsinnavto": + p.ExcludeLibrarySymbolsInNavTo = parseBoolWithDefault(value, false) + case "disablesuggestions": + p.DisableSuggestions = parseBoolWithDefault(value, false) + case "disablelinetextinreferences": + p.DisableLineTextInReferences = parseBoolWithDefault(value, true) + case "displaypartsforjsdoc": + p.DisplayPartsForJSDoc = parseBoolWithDefault(value, true) + } +} diff --git a/internal/lsp/server.go b/internal/lsp/server.go index 54f78f2e16..23ddf5324d 100644 --- a/internal/lsp/server.go +++ b/internal/lsp/server.go @@ -218,6 +218,28 @@ func (s *Server) RefreshDiagnostics(ctx context.Context) error { return nil } +func (s *Server) RequestConfiguration(ctx context.Context) (*ls.UserPreferences, error) { + result, err := s.sendRequest(ctx, lsproto.MethodWorkspaceConfiguration, &lsproto.ConfigurationParams{ + Items: []*lsproto.ConfigurationItem{ + { + Section: ptrTo("typescript"), + }, + }, + }) + if err != nil { + return nil, fmt.Errorf("configure request failed: %w", err) + } + configs := result.([]any) + s.Log(fmt.Sprintf("\n\nconfiguration: %+v, %T\n\n", configs, configs)) + userPreferences := ls.NewDefaultUserPreferences() + for _, item := range configs { + if parsed := userPreferences.Parse(item); parsed != nil { + return parsed, nil + } + } + return userPreferences, nil +} + func (s *Server) Run() error { ctx, stop := signal.NotifyContext(context.Background(), os.Interrupt, syscall.SIGTERM) defer stop() @@ -441,6 +463,7 @@ var handlers = sync.OnceValue(func() handlerMap { registerRequestHandler(handlers, lsproto.ShutdownInfo, (*Server).handleShutdown) registerNotificationHandler(handlers, lsproto.ExitInfo, (*Server).handleExit) + registerNotificationHandler(handlers, lsproto.WorkspaceDidChangeConfigurationInfo, (*Server).handleDidChangeWorkspaceConfiguration) registerNotificationHandler(handlers, lsproto.TextDocumentDidOpenInfo, (*Server).handleDidOpen) registerNotificationHandler(handlers, lsproto.TextDocumentDidChangeInfo, (*Server).handleDidChange) registerNotificationHandler(handlers, lsproto.TextDocumentDidSaveInfo, (*Server).handleDidSave) @@ -686,6 +709,18 @@ func (s *Server) handleInitialized(ctx context.Context, params *lsproto.Initiali NpmExecutor: s, ParseCache: s.parseCache, }) + + // request userPreferences if not provided at initialization + if s.initializeParams.InitializationOptions == nil { + userPreferences, err := s.RequestConfiguration(ctx) + if err != nil { + return err + } + s.session.Configure(userPreferences) + } else { + // !!! handle userPreferences from initialization + } + // !!! temporary; remove when we have `handleDidChangeConfiguration`/implicit project config support if s.compilerOptionsForInferredProjects != nil { s.session.DidChangeCompilerOptionsForInferredProjects(ctx, s.compilerOptionsForInferredProjects) @@ -703,6 +738,15 @@ func (s *Server) handleExit(ctx context.Context, params any) error { return io.EOF } +func (s *Server) handleDidChangeWorkspaceConfiguration(ctx context.Context, params *lsproto.DidChangeConfigurationParams) error { + userPreferences := s.session.UserPreferences().CopyOrDefault() + if parsed := userPreferences.Parse(params.Settings); parsed != nil { + userPreferences = parsed + } + s.session.Configure(userPreferences) + return nil +} + func (s *Server) handleDidOpen(ctx context.Context, params *lsproto.DidOpenTextDocumentParams) error { s.session.DidOpenFile(ctx, params.TextDocument.Uri, params.TextDocument.Version, params.TextDocument.Text, params.TextDocument.LanguageId) return nil @@ -788,10 +832,8 @@ func (s *Server) handleCompletion(ctx context.Context, languageService *ls.Langu params.Position, params.Context, getCompletionClientCapabilities(s.initializeParams), - &ls.UserPreferences{ - IncludeCompletionsForModuleExports: core.TSTrue, - IncludeCompletionsForImportStatements: core.TSTrue, - }) + languageService.UserPreferences(), + ) } func (s *Server) handleCompletionItemResolve(ctx context.Context, params *lsproto.CompletionItem, reqMsg *lsproto.RequestMessage) (lsproto.CompletionResolveResponse, error) { @@ -809,10 +851,7 @@ func (s *Server) handleCompletionItemResolve(ctx context.Context, params *lsprot params, data, getCompletionClientCapabilities(s.initializeParams), - &ls.UserPreferences{ - IncludeCompletionsForModuleExports: core.TSTrue, - IncludeCompletionsForImportStatements: core.TSTrue, - }, + languageService.UserPreferences(), ) } @@ -890,7 +929,9 @@ func isBlockingMethod(method lsproto.Method) bool { lsproto.MethodTextDocumentDidChange, lsproto.MethodTextDocumentDidSave, lsproto.MethodTextDocumentDidClose, - lsproto.MethodWorkspaceDidChangeWatchedFiles: + lsproto.MethodWorkspaceDidChangeWatchedFiles, + lsproto.MethodWorkspaceDidChangeConfiguration, + lsproto.MethodWorkspaceConfiguration: return true } return false diff --git a/internal/modulespecifiers/types.go b/internal/modulespecifiers/types.go index 6cdfa3e689..c83dde2d83 100644 --- a/internal/modulespecifiers/types.go +++ b/internal/modulespecifiers/types.go @@ -68,7 +68,7 @@ type ModuleSpecifierGenerationHost interface { type ImportModuleSpecifierPreference string const ( - ImportModuleSpecifierPreferenceNone ImportModuleSpecifierPreference = "" + ImportModuleSpecifierPreferenceNone ImportModuleSpecifierPreference = "" // !!! ImportModuleSpecifierPreferenceShortest ImportModuleSpecifierPreference = "shortest" ImportModuleSpecifierPreferenceProjectRelative ImportModuleSpecifierPreference = "project-relative" ImportModuleSpecifierPreferenceRelative ImportModuleSpecifierPreference = "relative" @@ -78,7 +78,7 @@ const ( type ImportModuleSpecifierEndingPreference string const ( - ImportModuleSpecifierEndingPreferenceNone ImportModuleSpecifierEndingPreference = "" + ImportModuleSpecifierEndingPreferenceNone ImportModuleSpecifierEndingPreference = "" // !!! ImportModuleSpecifierEndingPreferenceAuto ImportModuleSpecifierEndingPreference = "auto" ImportModuleSpecifierEndingPreferenceMinimal ImportModuleSpecifierEndingPreference = "minimal" ImportModuleSpecifierEndingPreferenceIndex ImportModuleSpecifierEndingPreference = "index" diff --git a/internal/project/api.go b/internal/project/api.go index ea84b3adb5..ad96de170f 100644 --- a/internal/project/api.go +++ b/internal/project/api.go @@ -7,7 +7,7 @@ import ( ) func (s *Session) OpenProject(ctx context.Context, configFileName string) (*Project, error) { - fileChanges, overlays, ataChanges := s.flushChanges(ctx) + fileChanges, overlays, ataChanges, _ := s.flushChanges(ctx) newSnapshot := s.UpdateSnapshot(ctx, overlays, SnapshotChange{ fileChanges: fileChanges, ataChanges: ataChanges, diff --git a/internal/project/session.go b/internal/project/session.go index a51831ed21..1737ad73fe 100644 --- a/internal/project/session.go +++ b/internal/project/session.go @@ -79,6 +79,7 @@ type Session struct { // released from the parseCache. programCounter *programCounter + userPreferences *ls.UserPreferences compilerOptionsForInferredProjects *core.CompilerOptions typingsInstaller *ata.TypingsInstaller backgroundQueue *background.Queue @@ -92,6 +93,9 @@ type Session struct { snapshot *Snapshot snapshotMu sync.RWMutex + pendingConfigChanges bool + pendingConfigChangesMu sync.Mutex + // pendingFileChanges are accumulated from textDocument/* events delivered // by the LSP server through DidOpenFile(), DidChangeFile(), etc. They are // applied to the next snapshot update. @@ -151,6 +155,7 @@ func NewSession(init *SessionInit) *Session { extendedConfigCache, &ConfigFileRegistry{}, nil, + nil, toPath, ), pendingATAChanges: make(map[tspath.Path]*ATAStateChange), @@ -177,11 +182,22 @@ func (s *Session) GetCurrentDirectory() string { return s.options.CurrentDirectory } +func (s *Session) UserPreferences() *ls.UserPreferences { + return s.userPreferences +} + // Trace implements module.ResolutionHost func (s *Session) Trace(msg string) { panic("ATA module resolution should not use tracing") } +func (s *Session) Configure(userPreferences *ls.UserPreferences) { + s.pendingConfigChangesMu.Lock() + defer s.pendingConfigChangesMu.Unlock() + s.pendingConfigChanges = true + s.userPreferences = userPreferences +} + func (s *Session) DidOpenFile(ctx context.Context, uri lsproto.DocumentUri, version int32, content string, languageKind lsproto.LanguageKind) { s.cancelDiagnosticsRefresh() s.pendingFileChangesMu.Lock() @@ -341,8 +357,8 @@ func (s *Session) Snapshot() (*Snapshot, func()) { func (s *Session) GetLanguageService(ctx context.Context, uri lsproto.DocumentUri) (*ls.LanguageService, error) { var snapshot *Snapshot - fileChanges, overlays, ataChanges := s.flushChanges(ctx) - updateSnapshot := !fileChanges.IsEmpty() || len(ataChanges) > 0 + fileChanges, overlays, ataChanges, newConfig := s.flushChanges(ctx) + updateSnapshot := !fileChanges.IsEmpty() || len(ataChanges) > 0 || newConfig != nil if updateSnapshot { // If there are pending file changes, we need to update the snapshot. // Sending the requested URI ensures that the project for this URI is loaded. @@ -350,6 +366,7 @@ func (s *Session) GetLanguageService(ctx context.Context, uri lsproto.DocumentUr reason: UpdateReasonRequestedLanguageServicePendingChanges, fileChanges: fileChanges, ataChanges: ataChanges, + newConfig: newConfig, requestedURIs: []lsproto.DocumentUri{uri}, }) } else { @@ -394,6 +411,7 @@ func (s *Session) UpdateSnapshot(ctx context.Context, overlays map[tspath.Path]* } // Enqueue logging, watch updates, and diagnostic refresh tasks + // !!! userPreferences/configuration updates s.backgroundQueue.Enqueue(context.Background(), func(ctx context.Context) { if s.options.LoggingEnabled { s.logger.Write(newSnapshot.builderLogs.String()) @@ -553,7 +571,7 @@ func (s *Session) Close() { s.backgroundQueue.Close() } -func (s *Session) flushChanges(ctx context.Context) (FileChangeSummary, map[tspath.Path]*overlay, map[tspath.Path]*ATAStateChange) { +func (s *Session) flushChanges(ctx context.Context) (FileChangeSummary, map[tspath.Path]*overlay, map[tspath.Path]*ATAStateChange, *ls.UserPreferences) { s.pendingFileChangesMu.Lock() defer s.pendingFileChangesMu.Unlock() s.pendingATAChangesMu.Lock() @@ -561,7 +579,14 @@ func (s *Session) flushChanges(ctx context.Context) (FileChangeSummary, map[tspa pendingATAChanges := s.pendingATAChanges s.pendingATAChanges = make(map[tspath.Path]*ATAStateChange) fileChanges, overlays := s.flushChangesLocked(ctx) - return fileChanges, overlays, pendingATAChanges + s.pendingConfigChangesMu.Lock() + var newConfig *ls.UserPreferences + if s.pendingConfigChanges { + newConfig = s.userPreferences.Copy() + } + s.pendingConfigChanges = false + defer s.pendingConfigChangesMu.Unlock() + return fileChanges, overlays, pendingATAChanges, newConfig } // flushChangesLocked should only be called with s.pendingFileChangesMu held. diff --git a/internal/project/snapshot.go b/internal/project/snapshot.go index 8d41e426c5..f88f1ef7fa 100644 --- a/internal/project/snapshot.go +++ b/internal/project/snapshot.go @@ -33,6 +33,7 @@ type Snapshot struct { ProjectCollection *ProjectCollection ConfigFileRegistry *ConfigFileRegistry compilerOptionsForInferredProjects *core.CompilerOptions + userPreferences *ls.UserPreferences builderLogs *logging.LogTree apiError error @@ -47,6 +48,7 @@ func NewSnapshot( extendedConfigCache *extendedConfigCache, configFileRegistry *ConfigFileRegistry, compilerOptionsForInferredProjects *core.CompilerOptions, + userPreferences *ls.UserPreferences, toPath func(fileName string) tspath.Path, ) *Snapshot { s := &Snapshot{ @@ -59,6 +61,7 @@ func NewSnapshot( ConfigFileRegistry: configFileRegistry, ProjectCollection: &ProjectCollection{toPath: toPath}, compilerOptionsForInferredProjects: compilerOptionsForInferredProjects, + userPreferences: userPreferences.CopyOrDefault(), } s.converters = ls.NewConverters(s.sessionOptions.PositionEncoding, s.LSPLineMap) s.refCount.Store(1) @@ -89,6 +92,10 @@ func (s *Snapshot) GetECMALineInfo(fileName string) *sourcemap.ECMALineInfo { return nil } +func (s *Snapshot) UserPreferences() *ls.UserPreferences { + return s.userPreferences +} + func (s *Snapshot) Converters() *ls.Converters { return s.converters } @@ -126,6 +133,7 @@ type SnapshotChange struct { // It should only be set the value in the next snapshot should be changed. If nil, the // value from the previous snapshot will be copied to the new snapshot. compilerOptionsForInferredProjects *core.CompilerOptions + newConfig *ls.UserPreferences // ataChanges contains ATA-related changes to apply to projects in the new snapshot. ataChanges map[tspath.Path]*ATAStateChange apiRequest *APISnapshotRequest @@ -245,6 +253,11 @@ func (s *Snapshot) Clone(ctx context.Context, change SnapshotChange, overlays ma } } + userPreferences := s.userPreferences + if change.newConfig != nil { + userPreferences = change.newConfig + } + snapshotFS, _ := fs.Finalize() newSnapshot := NewSnapshot( newSnapshotID, @@ -254,6 +267,7 @@ func (s *Snapshot) Clone(ctx context.Context, change SnapshotChange, overlays ma session.extendedConfigCache, nil, compilerOptionsForInferredProjects, + userPreferences, s.toPath, ) newSnapshot.parentId = s.id diff --git a/internal/tsoptions/parsinghelpers.go b/internal/tsoptions/parsinghelpers.go index bf16518be2..91944af6a7 100644 --- a/internal/tsoptions/parsinghelpers.go +++ b/internal/tsoptions/parsinghelpers.go @@ -11,7 +11,7 @@ import ( "github.com/microsoft/typescript-go/internal/tspath" ) -func parseTristate(value any) core.Tristate { +func ParseTristate(value any) core.Tristate { if value == nil { return core.TSUnknown } @@ -25,7 +25,7 @@ func parseTristate(value any) core.Tristate { } } -func parseStringArray(value any) []string { +func ParseStringArray(value any) []string { if arr, ok := value.([]any); ok { if arr == nil { return nil @@ -45,14 +45,14 @@ func parseStringMap(value any) *collections.OrderedMap[string, []string] { if m, ok := value.(*collections.OrderedMap[string, any]); ok { result := collections.NewOrderedMapWithSizeHint[string, []string](m.Size()) for k, v := range m.Entries() { - result.Set(k, parseStringArray(v)) + result.Set(k, ParseStringArray(v)) } return result } return nil } -func parseString(value any) string { +func ParseString(value any) string { if str, ok := value.(string); ok { return str } @@ -186,119 +186,119 @@ func parseCompilerOptions(key string, value any, allOptions *core.CompilerOption } switch key { case "allowJs": - allOptions.AllowJs = parseTristate(value) + allOptions.AllowJs = ParseTristate(value) case "allowImportingTsExtensions": - allOptions.AllowImportingTsExtensions = parseTristate(value) + allOptions.AllowImportingTsExtensions = ParseTristate(value) case "allowSyntheticDefaultImports": - allOptions.AllowSyntheticDefaultImports = parseTristate(value) + allOptions.AllowSyntheticDefaultImports = ParseTristate(value) case "allowNonTsExtensions": - allOptions.AllowNonTsExtensions = parseTristate(value) + allOptions.AllowNonTsExtensions = ParseTristate(value) case "allowUmdGlobalAccess": - allOptions.AllowUmdGlobalAccess = parseTristate(value) + allOptions.AllowUmdGlobalAccess = ParseTristate(value) case "allowUnreachableCode": - allOptions.AllowUnreachableCode = parseTristate(value) + allOptions.AllowUnreachableCode = ParseTristate(value) case "allowUnusedLabels": - allOptions.AllowUnusedLabels = parseTristate(value) + allOptions.AllowUnusedLabels = ParseTristate(value) case "allowArbitraryExtensions": - allOptions.AllowArbitraryExtensions = parseTristate(value) + allOptions.AllowArbitraryExtensions = ParseTristate(value) case "alwaysStrict": - allOptions.AlwaysStrict = parseTristate(value) + allOptions.AlwaysStrict = ParseTristate(value) case "assumeChangesOnlyAffectDirectDependencies": - allOptions.AssumeChangesOnlyAffectDirectDependencies = parseTristate(value) + allOptions.AssumeChangesOnlyAffectDirectDependencies = ParseTristate(value) case "baseUrl": - allOptions.BaseUrl = parseString(value) + allOptions.BaseUrl = ParseString(value) case "build": - allOptions.Build = parseTristate(value) + allOptions.Build = ParseTristate(value) case "checkJs": - allOptions.CheckJs = parseTristate(value) + allOptions.CheckJs = ParseTristate(value) case "customConditions": - allOptions.CustomConditions = parseStringArray(value) + allOptions.CustomConditions = ParseStringArray(value) case "composite": - allOptions.Composite = parseTristate(value) + allOptions.Composite = ParseTristate(value) case "declarationDir": - allOptions.DeclarationDir = parseString(value) + allOptions.DeclarationDir = ParseString(value) case "diagnostics": - allOptions.Diagnostics = parseTristate(value) + allOptions.Diagnostics = ParseTristate(value) case "disableSizeLimit": - allOptions.DisableSizeLimit = parseTristate(value) + allOptions.DisableSizeLimit = ParseTristate(value) case "disableSourceOfProjectReferenceRedirect": - allOptions.DisableSourceOfProjectReferenceRedirect = parseTristate(value) + allOptions.DisableSourceOfProjectReferenceRedirect = ParseTristate(value) case "disableSolutionSearching": - allOptions.DisableSolutionSearching = parseTristate(value) + allOptions.DisableSolutionSearching = ParseTristate(value) case "disableReferencedProjectLoad": - allOptions.DisableReferencedProjectLoad = parseTristate(value) + allOptions.DisableReferencedProjectLoad = ParseTristate(value) case "declarationMap": - allOptions.DeclarationMap = parseTristate(value) + allOptions.DeclarationMap = ParseTristate(value) case "declaration": - allOptions.Declaration = parseTristate(value) + allOptions.Declaration = ParseTristate(value) case "downlevelIteration": - allOptions.DownlevelIteration = parseTristate(value) + allOptions.DownlevelIteration = ParseTristate(value) case "erasableSyntaxOnly": - allOptions.ErasableSyntaxOnly = parseTristate(value) + allOptions.ErasableSyntaxOnly = ParseTristate(value) case "emitDeclarationOnly": - allOptions.EmitDeclarationOnly = parseTristate(value) + allOptions.EmitDeclarationOnly = ParseTristate(value) case "extendedDiagnostics": - allOptions.ExtendedDiagnostics = parseTristate(value) + allOptions.ExtendedDiagnostics = ParseTristate(value) case "emitDecoratorMetadata": - allOptions.EmitDecoratorMetadata = parseTristate(value) + allOptions.EmitDecoratorMetadata = ParseTristate(value) case "emitBOM": - allOptions.EmitBOM = parseTristate(value) + allOptions.EmitBOM = ParseTristate(value) case "esModuleInterop": - allOptions.ESModuleInterop = parseTristate(value) + allOptions.ESModuleInterop = ParseTristate(value) case "exactOptionalPropertyTypes": - allOptions.ExactOptionalPropertyTypes = parseTristate(value) + allOptions.ExactOptionalPropertyTypes = ParseTristate(value) case "explainFiles": - allOptions.ExplainFiles = parseTristate(value) + allOptions.ExplainFiles = ParseTristate(value) case "experimentalDecorators": - allOptions.ExperimentalDecorators = parseTristate(value) + allOptions.ExperimentalDecorators = ParseTristate(value) case "forceConsistentCasingInFileNames": - allOptions.ForceConsistentCasingInFileNames = parseTristate(value) + allOptions.ForceConsistentCasingInFileNames = ParseTristate(value) case "generateCpuProfile": - allOptions.GenerateCpuProfile = parseString(value) + allOptions.GenerateCpuProfile = ParseString(value) case "generateTrace": - allOptions.GenerateTrace = parseString(value) + allOptions.GenerateTrace = ParseString(value) case "isolatedModules": - allOptions.IsolatedModules = parseTristate(value) + allOptions.IsolatedModules = ParseTristate(value) case "ignoreDeprecations": - allOptions.IgnoreDeprecations = parseString(value) + allOptions.IgnoreDeprecations = ParseString(value) case "importHelpers": - allOptions.ImportHelpers = parseTristate(value) + allOptions.ImportHelpers = ParseTristate(value) case "incremental": - allOptions.Incremental = parseTristate(value) + allOptions.Incremental = ParseTristate(value) case "init": - allOptions.Init = parseTristate(value) + allOptions.Init = ParseTristate(value) case "inlineSourceMap": - allOptions.InlineSourceMap = parseTristate(value) + allOptions.InlineSourceMap = ParseTristate(value) case "inlineSources": - allOptions.InlineSources = parseTristate(value) + allOptions.InlineSources = ParseTristate(value) case "isolatedDeclarations": - allOptions.IsolatedDeclarations = parseTristate(value) + allOptions.IsolatedDeclarations = ParseTristate(value) case "jsx": allOptions.Jsx = floatOrInt32ToFlag[core.JsxEmit](value) case "jsxFactory": - allOptions.JsxFactory = parseString(value) + allOptions.JsxFactory = ParseString(value) case "jsxFragmentFactory": - allOptions.JsxFragmentFactory = parseString(value) + allOptions.JsxFragmentFactory = ParseString(value) case "jsxImportSource": - allOptions.JsxImportSource = parseString(value) + allOptions.JsxImportSource = ParseString(value) case "lib": if _, ok := value.([]string); ok { allOptions.Lib = value.([]string) } else { - allOptions.Lib = parseStringArray(value) + allOptions.Lib = ParseStringArray(value) } case "libReplacement": - allOptions.LibReplacement = parseTristate(value) + allOptions.LibReplacement = ParseTristate(value) case "listEmittedFiles": - allOptions.ListEmittedFiles = parseTristate(value) + allOptions.ListEmittedFiles = ParseTristate(value) case "listFiles": - allOptions.ListFiles = parseTristate(value) + allOptions.ListFiles = ParseTristate(value) case "listFilesOnly": - allOptions.ListFilesOnly = parseTristate(value) + allOptions.ListFilesOnly = ParseTristate(value) case "locale": - allOptions.Locale = parseString(value) + allOptions.Locale = ParseString(value) case "mapRoot": - allOptions.MapRoot = parseString(value) + allOptions.MapRoot = ParseString(value) case "module": allOptions.Module = floatOrInt32ToFlag[core.ModuleKind](value) case "moduleDetectionKind": @@ -306,143 +306,143 @@ func parseCompilerOptions(key string, value any, allOptions *core.CompilerOption case "moduleResolution": allOptions.ModuleResolution = floatOrInt32ToFlag[core.ModuleResolutionKind](value) case "moduleSuffixes": - allOptions.ModuleSuffixes = parseStringArray(value) + allOptions.ModuleSuffixes = ParseStringArray(value) case "moduleDetection": allOptions.ModuleDetection = floatOrInt32ToFlag[core.ModuleDetectionKind](value) case "noCheck": - allOptions.NoCheck = parseTristate(value) + allOptions.NoCheck = ParseTristate(value) case "noFallthroughCasesInSwitch": - allOptions.NoFallthroughCasesInSwitch = parseTristate(value) + allOptions.NoFallthroughCasesInSwitch = ParseTristate(value) case "noEmitForJsFiles": - allOptions.NoEmitForJsFiles = parseTristate(value) + allOptions.NoEmitForJsFiles = ParseTristate(value) case "noErrorTruncation": - allOptions.NoErrorTruncation = parseTristate(value) + allOptions.NoErrorTruncation = ParseTristate(value) case "noImplicitAny": - allOptions.NoImplicitAny = parseTristate(value) + allOptions.NoImplicitAny = ParseTristate(value) case "noImplicitThis": - allOptions.NoImplicitThis = parseTristate(value) + allOptions.NoImplicitThis = ParseTristate(value) case "noLib": - allOptions.NoLib = parseTristate(value) + allOptions.NoLib = ParseTristate(value) case "noPropertyAccessFromIndexSignature": - allOptions.NoPropertyAccessFromIndexSignature = parseTristate(value) + allOptions.NoPropertyAccessFromIndexSignature = ParseTristate(value) case "noUncheckedIndexedAccess": - allOptions.NoUncheckedIndexedAccess = parseTristate(value) + allOptions.NoUncheckedIndexedAccess = ParseTristate(value) case "noEmitHelpers": - allOptions.NoEmitHelpers = parseTristate(value) + allOptions.NoEmitHelpers = ParseTristate(value) case "noEmitOnError": - allOptions.NoEmitOnError = parseTristate(value) + allOptions.NoEmitOnError = ParseTristate(value) case "noImplicitReturns": - allOptions.NoImplicitReturns = parseTristate(value) + allOptions.NoImplicitReturns = ParseTristate(value) case "noUnusedLocals": - allOptions.NoUnusedLocals = parseTristate(value) + allOptions.NoUnusedLocals = ParseTristate(value) case "noUnusedParameters": - allOptions.NoUnusedParameters = parseTristate(value) + allOptions.NoUnusedParameters = ParseTristate(value) case "noImplicitOverride": - allOptions.NoImplicitOverride = parseTristate(value) + allOptions.NoImplicitOverride = ParseTristate(value) case "noUncheckedSideEffectImports": - allOptions.NoUncheckedSideEffectImports = parseTristate(value) + allOptions.NoUncheckedSideEffectImports = ParseTristate(value) case "outFile": - allOptions.OutFile = parseString(value) + allOptions.OutFile = ParseString(value) case "noResolve": - allOptions.NoResolve = parseTristate(value) + allOptions.NoResolve = ParseTristate(value) case "paths": allOptions.Paths = parseStringMap(value) case "preserveWatchOutput": - allOptions.PreserveWatchOutput = parseTristate(value) + allOptions.PreserveWatchOutput = ParseTristate(value) case "preserveConstEnums": - allOptions.PreserveConstEnums = parseTristate(value) + allOptions.PreserveConstEnums = ParseTristate(value) case "preserveSymlinks": - allOptions.PreserveSymlinks = parseTristate(value) + allOptions.PreserveSymlinks = ParseTristate(value) case "project": - allOptions.Project = parseString(value) + allOptions.Project = ParseString(value) case "pretty": - allOptions.Pretty = parseTristate(value) + allOptions.Pretty = ParseTristate(value) case "resolveJsonModule": - allOptions.ResolveJsonModule = parseTristate(value) + allOptions.ResolveJsonModule = ParseTristate(value) case "resolvePackageJsonExports": - allOptions.ResolvePackageJsonExports = parseTristate(value) + allOptions.ResolvePackageJsonExports = ParseTristate(value) case "resolvePackageJsonImports": - allOptions.ResolvePackageJsonImports = parseTristate(value) + allOptions.ResolvePackageJsonImports = ParseTristate(value) case "reactNamespace": - allOptions.ReactNamespace = parseString(value) + allOptions.ReactNamespace = ParseString(value) case "rewriteRelativeImportExtensions": - allOptions.RewriteRelativeImportExtensions = parseTristate(value) + allOptions.RewriteRelativeImportExtensions = ParseTristate(value) case "rootDir": - allOptions.RootDir = parseString(value) + allOptions.RootDir = ParseString(value) case "rootDirs": - allOptions.RootDirs = parseStringArray(value) + allOptions.RootDirs = ParseStringArray(value) case "removeComments": - allOptions.RemoveComments = parseTristate(value) + allOptions.RemoveComments = ParseTristate(value) case "strict": - allOptions.Strict = parseTristate(value) + allOptions.Strict = ParseTristate(value) case "strictBindCallApply": - allOptions.StrictBindCallApply = parseTristate(value) + allOptions.StrictBindCallApply = ParseTristate(value) case "strictBuiltinIteratorReturn": - allOptions.StrictBuiltinIteratorReturn = parseTristate(value) + allOptions.StrictBuiltinIteratorReturn = ParseTristate(value) case "strictFunctionTypes": - allOptions.StrictFunctionTypes = parseTristate(value) + allOptions.StrictFunctionTypes = ParseTristate(value) case "strictNullChecks": - allOptions.StrictNullChecks = parseTristate(value) + allOptions.StrictNullChecks = ParseTristate(value) case "strictPropertyInitialization": - allOptions.StrictPropertyInitialization = parseTristate(value) + allOptions.StrictPropertyInitialization = ParseTristate(value) case "skipDefaultLibCheck": - allOptions.SkipDefaultLibCheck = parseTristate(value) + allOptions.SkipDefaultLibCheck = ParseTristate(value) case "sourceMap": - allOptions.SourceMap = parseTristate(value) + allOptions.SourceMap = ParseTristate(value) case "sourceRoot": - allOptions.SourceRoot = parseString(value) + allOptions.SourceRoot = ParseString(value) case "stripInternal": - allOptions.StripInternal = parseTristate(value) + allOptions.StripInternal = ParseTristate(value) case "suppressOutputPathCheck": - allOptions.SuppressOutputPathCheck = parseTristate(value) + allOptions.SuppressOutputPathCheck = ParseTristate(value) case "target": allOptions.Target = floatOrInt32ToFlag[core.ScriptTarget](value) case "traceResolution": - allOptions.TraceResolution = parseTristate(value) + allOptions.TraceResolution = ParseTristate(value) case "tsBuildInfoFile": - allOptions.TsBuildInfoFile = parseString(value) + allOptions.TsBuildInfoFile = ParseString(value) case "typeRoots": - allOptions.TypeRoots = parseStringArray(value) + allOptions.TypeRoots = ParseStringArray(value) case "types": - allOptions.Types = parseStringArray(value) + allOptions.Types = ParseStringArray(value) case "useDefineForClassFields": - allOptions.UseDefineForClassFields = parseTristate(value) + allOptions.UseDefineForClassFields = ParseTristate(value) case "useUnknownInCatchVariables": - allOptions.UseUnknownInCatchVariables = parseTristate(value) + allOptions.UseUnknownInCatchVariables = ParseTristate(value) case "verbatimModuleSyntax": - allOptions.VerbatimModuleSyntax = parseTristate(value) + allOptions.VerbatimModuleSyntax = ParseTristate(value) case "version": - allOptions.Version = parseTristate(value) + allOptions.Version = ParseTristate(value) case "help": - allOptions.Help = parseTristate(value) + allOptions.Help = ParseTristate(value) case "all": - allOptions.All = parseTristate(value) + allOptions.All = ParseTristate(value) case "maxNodeModuleJsDepth": allOptions.MaxNodeModuleJsDepth = parseNumber(value) case "skipLibCheck": - allOptions.SkipLibCheck = parseTristate(value) + allOptions.SkipLibCheck = ParseTristate(value) case "noEmit": - allOptions.NoEmit = parseTristate(value) + allOptions.NoEmit = ParseTristate(value) case "showConfig": - allOptions.ShowConfig = parseTristate(value) + allOptions.ShowConfig = ParseTristate(value) case "configFilePath": - allOptions.ConfigFilePath = parseString(value) + allOptions.ConfigFilePath = ParseString(value) case "noDtsResolution": - allOptions.NoDtsResolution = parseTristate(value) + allOptions.NoDtsResolution = ParseTristate(value) case "pathsBasePath": - allOptions.PathsBasePath = parseString(value) + allOptions.PathsBasePath = ParseString(value) case "outDir": - allOptions.OutDir = parseString(value) + allOptions.OutDir = ParseString(value) case "newLine": allOptions.NewLine = floatOrInt32ToFlag[core.NewLineKind](value) case "watch": - allOptions.Watch = parseTristate(value) + allOptions.Watch = ParseTristate(value) case "pprofDir": - allOptions.PprofDir = parseString(value) + allOptions.PprofDir = ParseString(value) case "singleThreaded": - allOptions.SingleThreaded = parseTristate(value) + allOptions.SingleThreaded = ParseTristate(value) case "quiet": - allOptions.Quiet = parseTristate(value) + allOptions.Quiet = ParseTristate(value) default: // different than any key above return false @@ -477,11 +477,11 @@ func ParseWatchOptions(key string, value any, allOptions *core.WatchOptions) []* allOptions.FallbackPolling = value.(core.PollingKind) } case "synchronousWatchDirectory": - allOptions.SyncWatchDir = parseTristate(value) + allOptions.SyncWatchDir = ParseTristate(value) case "excludeDirectories": - allOptions.ExcludeDir = parseStringArray(value) + allOptions.ExcludeDir = ParseStringArray(value) case "excludeFiles": - allOptions.ExcludeFiles = parseStringArray(value) + allOptions.ExcludeFiles = ParseStringArray(value) } return nil } @@ -495,13 +495,13 @@ func ParseTypeAcquisition(key string, value any, allOptions *core.TypeAcquisitio } switch key { case "enable": - allOptions.Enable = parseTristate(value) + allOptions.Enable = ParseTristate(value) case "include": - allOptions.Include = parseStringArray(value) + allOptions.Include = ParseStringArray(value) case "exclude": - allOptions.Exclude = parseStringArray(value) + allOptions.Exclude = ParseStringArray(value) case "disableFilenameBasedTypeAcquisition": - allOptions.DisableFilenameBasedTypeAcquisition = parseTristate(value) + allOptions.DisableFilenameBasedTypeAcquisition = ParseTristate(value) } return nil } @@ -519,15 +519,15 @@ func ParseBuildOptions(key string, value any, allOptions *core.BuildOptions) []* } switch key { case "clean": - allOptions.Clean = parseTristate(value) + allOptions.Clean = ParseTristate(value) case "dry": - allOptions.Dry = parseTristate(value) + allOptions.Dry = ParseTristate(value) case "force": - allOptions.Force = parseTristate(value) + allOptions.Force = ParseTristate(value) case "stopBuildOnErrors": - allOptions.StopBuildOnErrors = parseTristate(value) + allOptions.StopBuildOnErrors = ParseTristate(value) case "verbose": - allOptions.Verbose = parseTristate(value) + allOptions.Verbose = ParseTristate(value) } return nil }