package vset import ( "encoding/json" "fmt" "os" "edge-infra.dev/pkg/lib/build/bazel" ) // The Configure interface contains Configurator(), which guides the file through the configuration functions. // Each configuration function sets its respective field of settings.json to the desired value. // Fields that require structs as values have struct declarations in structs.go. type Configure interface { Configurator(string) error FileAssociations(...interface{}) map[string]interface{} FileWatcherExclude(...interface{}) map[string]interface{} GoAltTools() map[string]string GoLintFlags() []string Gopls(...interface{}) map[string]interface{} JSONConfig(...interface{}) map[string]interface{} StarlarkConfig(...interface{}) map[string]interface{} } func Configurator(path, goLintPath string) error { byteValue, err := os.ReadFile(path) if err != nil { return fmt.Errorf("failed to read existing settings.json: %w", err) } // Settings.json is Unmarshaled into settingsMap to be configured. var settingsMap map[string]interface{} if err = json.Unmarshal(byteValue, &settingsMap); err != nil { return fmt.Errorf("failed to unmarshal json, confirm that your settings.json is free of syntax errors: %w", err) } // Update settingsMap to reflect the correct settings for each field. settingsMap["[json]"] = JSONConfig(settingsMap["[json]"]) settingsMap["[starlark]"] = StarlarkConfig(settingsMap["[starlark]"]) settingsMap["bazel.buildifierFixOnFormat"] = true settingsMap["files.associations"] = FileAssociations(settingsMap["files.associations"]) settingsMap["files.watcherExclude"] = FileWatcherExclude(settingsMap["files.watcherExclude"]) settingsMap["go.lintFlags"] = GoLintFlags(goLintPath) settingsMap["go.lintOnSave"] = "package" settingsMap["go.lintTool"] = "golangci-lint" settingsMap["go.useLanguageServer"] = true settingsMap["gopls"] = Gopls(settingsMap["gopls"]) settingsMap["go.alternateTools"], err = GoAltTools() if err != nil { return err } // After configuration is complete, convert settingsMap back to json and write it to settings.json. byteValue, err = json.MarshalIndent(settingsMap, "", " ") if err != nil { return fmt.Errorf("failed to marshal json: %w", err) } if err = os.WriteFile(path, byteValue, 0644); err != nil { return fmt.Errorf("failed to rewrite settings.json: %w", err) } fmt.Println("...settings.json configured successfully!") fmt.Println("For more customization, see https://github.com/golang/vscode-go/blob/master/docs/settings.md") fmt.Println("Exiting...") return nil } func FileAssociations(fileSet ...interface{}) map[string]interface{} { fileMap := make(map[string]interface{}) if fileSet[0] != nil { fileMap = fileSet[0].(map[string]interface{}) } fileMap[".warehouse-dist/**/*"] = "json" return fileMap } func FileWatcherExclude(excludeSet ...interface{}) map[string]interface{} { excludeMap := make(map[string]interface{}) if excludeSet[0] != nil { excludeMap = excludeSet[0].(map[string]interface{}) } excludeMap["**/.git/objects/**"] = true excludeMap["**/.git/subtree-cache/**"] = true excludeMap["**/.warehouse-dist/**"] = true excludeMap["**/node_modules/*/**"] = true excludeMap["**/bazel-bin/*/**"] = true excludeMap["**/bazel-edge-infra/*/**"] = true excludeMap["**/bazel-out/*/**"] = true excludeMap["**/bazel-testlogs/*/**"] = true return excludeMap } func GoAltTools() (map[string]string, error) { goPath, err := bazel.FindRepoRoot(path) if err != nil { return nil, fmt.Errorf("failed to find repo root: %w", err) } goPath += "/bazel-edge-infra/external/go_sdk/bin/go" return map[string]string{ "go": goPath, }, nil } func GoLintFlags(goLintPath string) []string { return []string{ "--fast", "-c", goLintPath + "hack/tools/linters/golangcilint.yaml", } } func Gopls(goplsSet ...interface{}) map[string]interface{} { goplsMap := make(map[string]interface{}) if goplsSet[0] != nil { goplsMap = goplsSet[0].(map[string]interface{}) } goplsMap["build.directoryFilters"] = []string{ "-bazel-bin", "-bazel-edge-infra", "-bazel-out", "-bazel-testlogs", } goplsMap["formatting.local"] = "edge-infra.dev" // Delete problematic personal configs if present if _, exists := goplsMap["build.experimentalWorkspaceModule"]; exists { fmt.Println("WARNING: gopls:build.experimentalWorkspaceModule can be problematic and has been deleted.") delete(goplsMap, "build.experimentalWorkspaceModule") } return goplsMap } func JSONConfig(jsonSet ...interface{}) map[string]interface{} { jsonMap := make(map[string]interface{}) if jsonSet[0] != nil { jsonMap = jsonSet[0].(map[string]interface{}) } jsonMap["editor.formatOnSave"] = true jsonMap["editor.defaultFormatter"] = "vscode.json-language-features" return jsonMap } func StarlarkConfig(starlarkSet ...interface{}) map[string]interface{} { starlarkMap := make(map[string]interface{}) if starlarkSet[0] != nil { starlarkMap = starlarkSet[0].(map[string]interface{}) } starlarkMap["editor.formatOnSave"] = true starlarkMap["editor.tabSize"] = 4 return starlarkMap }