package.json: add 'go.diagnostic.vulncheck'

This replaces 'gopls.ui.diagnostic.vulncheck'.
The configuration adjustment follows what
passInlayHintConfigToGopls does.

Change-Id: I381d9a0d653a5aa4a38dffc616188bf9672210ca
Reviewed-on: https://go-review.googlesource.com/c/vscode-go/+/456038
Reviewed-by: Suzy Mueller <suzmue@golang.org>
Auto-Submit: Hyang-Ah Hana Kim <hyangah@gmail.com>
Run-TryBot: Hyang-Ah Hana Kim <hyangah@gmail.com>
TryBot-Result: kokoro <noreply+kokoro@google.com>
diff --git a/docs/settings.md b/docs/settings.md
index 767b316..baeefe4 100644
--- a/docs/settings.md
+++ b/docs/settings.md
@@ -151,6 +151,18 @@
 | `showLog` | Show log output from the delve debugger. Maps to dlv's `--log` flag. <br/> Default: `false` |
 | `showRegisters` | Boolean value to indicate whether register variables should be shown in the variables pane or not. <br/> Default: `false` |
 | `substitutePath` | An array of mappings from a local path to the remote path that is used by the debuggee. The debug adapter will replace the local path with the remote path in all of the calls. Overriden by `remotePath` (in attach request). |
+### `go.diagnostic.vulncheck`
+
+(Experimental) vulncheck enables vulnerability scanning.
+<br/>
+Allowed Options:
+
+* `Imports`: `"Imports"`: In Imports mode, `gopls` will report vulnerabilities that affect packages
+directly and indirectly used by the analyzed main module.
+* `Off`: `"Off"`: Disable vulnerability analysis.
+
+
+Default: `"Off"`
 ### `go.disableConcurrentTests`
 
 If true, tests will not run concurrently. When a new test run is started, the previous will be cancelled.
@@ -903,18 +915,6 @@
 
 
 Default: `false`
-### `ui.diagnostic.vulncheck`
-
-(Experimental) vulncheck enables vulnerability scanning.
-<br/>
-Allowed Options:
-
-* `Imports`: `"Imports"`: In Imports mode, `gopls` will report vulnerabilities that affect packages
-directly and indirectly used by the analyzed main module.
-* `Off`: `"Off"`: Disable vulnerability analysis.
-
-
-Default: `"Off"`
 ### `ui.documentation.hoverKind`
 
 hoverKind controls the information that appears in the hover text.
diff --git a/package.json b/package.json
index 83203f6..b731ec4 100644
--- a/package.json
+++ b/package.json
@@ -2516,20 +2516,6 @@
               "default": false,
               "scope": "resource"
             },
-            "ui.diagnostic.vulncheck": {
-              "type": "string",
-              "markdownDescription": "(Experimental) vulncheck enables vulnerability scanning.\n",
-              "enum": [
-                "Imports",
-                "Off"
-              ],
-              "markdownEnumDescriptions": [
-                "`\"Imports\"`: In Imports mode, `gopls` will report vulnerabilities that affect packages\ndirectly and indirectly used by the analyzed main module.\n",
-                "`\"Off\"`: Disable vulnerability analysis.\n"
-              ],
-              "default": "Off",
-              "scope": "resource"
-            },
             "ui.documentation.hoverKind": {
               "type": "string",
               "markdownDescription": "hoverKind controls the information that appears in the hover text.\nSingleLine and Structured are intended for use only by authors of editor plugins.\n",
@@ -2638,6 +2624,20 @@
             }
           }
         },
+        "go.diagnostic.vulncheck": {
+          "type": "string",
+          "markdownDescription": "(Experimental) vulncheck enables vulnerability scanning.\n",
+          "enum": [
+            "Imports",
+            "Off"
+          ],
+          "markdownEnumDescriptions": [
+            "`\"Imports\"`: In Imports mode, `gopls` will report vulnerabilities that affect packages\ndirectly and indirectly used by the analyzed main module.\n",
+            "`\"Off\"`: Disable vulnerability analysis.\n"
+          ],
+          "default": "Off",
+          "scope": "resource"
+        },
         "go.inlayHints.assignVariableTypes": {
           "type": "boolean",
           "markdownDescription": "Enable/disable inlay hints for variable types in assign statements:\n```go\n\ti/* int*/, j/* int*/ := 0, len(r)-1\n```",
diff --git a/src/language/goLanguageServer.ts b/src/language/goLanguageServer.ts
index d20b0dd..fda9374 100644
--- a/src/language/goLanguageServer.ts
+++ b/src/language/goLanguageServer.ts
@@ -788,8 +788,10 @@
 
 	workspaceConfig = filterGoplsDefaultConfigValues(workspaceConfig, resource);
 	// note: workspaceConfig is a modifiable, valid object.
-	workspaceConfig = passGoConfigToGoplsConfigValues(workspaceConfig, getGoConfig(resource));
-	workspaceConfig = await passInlayHintConfigToGopls(cfg, workspaceConfig, getGoConfig(resource));
+	const goConfig = getGoConfig(resource);
+	workspaceConfig = passGoConfigToGoplsConfigValues(workspaceConfig, goConfig);
+	workspaceConfig = await passInlayHintConfigToGopls(cfg, workspaceConfig, goConfig);
+	workspaceConfig = await passVulncheckConfigToGopls(cfg, workspaceConfig, goConfig);
 
 	// Only modify the user's configurations for the Nightly.
 	if (!extensionInfo.isPreview) {
@@ -803,7 +805,7 @@
 
 async function passInlayHintConfigToGopls(cfg: LanguageServerConfig, goplsConfig: any, goConfig: any) {
 	const goplsVersion = await getLocalGoplsVersion(cfg);
-	if (!goplsVersion) return;
+	if (!goplsVersion) return goplsConfig ?? {};
 	const version = semver.parse(goplsVersion.version);
 	if ((version?.compare('0.8.4') ?? 1) > 0) {
 		const { inlayHints } = goConfig;
@@ -814,6 +816,19 @@
 	return goplsConfig;
 }
 
+async function passVulncheckConfigToGopls(cfg: LanguageServerConfig, goplsConfig: any, goConfig: any) {
+	const goplsVersion = await getLocalGoplsVersion(cfg);
+	if (!goplsVersion) return goplsConfig ?? {};
+	const version = semver.parse(goplsVersion.version);
+	if ((version?.compare('0.10.1') ?? 1) > 0) {
+		const vulncheck = goConfig.get('diagnostic.vulncheck');
+		if (vulncheck) {
+			goplsConfig['ui.vulncheck'] = vulncheck;
+		}
+	}
+	return goplsConfig;
+}
+
 // createTestCodeLens adds the go.test.cursor and go.debug.cursor code lens
 function createTestCodeLens(lens: vscode.CodeLens): vscode.CodeLens[] {
 	// CodeLens argument signature in gopls is [fileName: string, testFunctions: string[], benchFunctions: string[]],
diff --git a/tools/goplssetting/goplssetting.go b/tools/goplssetting/goplssetting.go
index c9125ee..c8b75f8 100644
--- a/tools/goplssetting/goplssetting.go
+++ b/tools/goplssetting/goplssetting.go
@@ -229,49 +229,15 @@
 			continue
 		}
 		for _, opt := range m[hierarchy] {
-			doc := opt.Doc
-			if mappedTo, ok := associatedToExtensionProperties[opt.Name]; ok {
-				doc = fmt.Sprintf("%v\nIf unspecified, values of `%v` will be propagated.\n", doc, strings.Join(mappedTo, ", "))
+			obj, err := toObject(opt)
+			if err != nil {
+				return nil, nil, err
 			}
-			obj := &Object{
-				MarkdownDescription: doc,
-				// TODO: are all gopls settings in the resource scope?
-				Scope: "resource",
-				// TODO: consider 'additionalProperties' if gopls api-json
-				// outputs acceptable properties.
-				// TODO: deprecation attribute
+			// TODO(hyangah): move diagnostic to all go.diagnostic.
+			if hierarchy == "ui.diagnostic" && opt.Name == "vulncheck" {
+				goProperties["go.diagnostic.vulncheck"] = obj
+				continue
 			}
-			// Handle any enum types.
-			if opt.Type == "enum" {
-				for _, v := range opt.EnumValues {
-					unquotedName, err := strconv.Unquote(v.Value)
-					if err != nil {
-						return nil, nil, err
-					}
-					obj.Enum = append(obj.Enum, unquotedName)
-					obj.MarkdownEnumDescriptions = append(obj.MarkdownEnumDescriptions, v.Doc)
-				}
-			}
-			// Handle any objects whose keys are enums.
-			if len(opt.EnumKeys.Keys) > 0 {
-				if obj.Properties == nil {
-					obj.Properties = map[string]*Object{}
-				}
-				for _, k := range opt.EnumKeys.Keys {
-					unquotedName, err := strconv.Unquote(k.Name)
-					if err != nil {
-						return nil, nil, err
-					}
-					obj.Properties[unquotedName] = &Object{
-						Type:                propertyType(opt.EnumKeys.ValueType),
-						MarkdownDescription: k.Doc,
-						Default:             formatDefault(k.Default, opt.EnumKeys.ValueType),
-					}
-				}
-			}
-			obj.Type = propertyType(opt.Type)
-			obj.Default = formatOptionDefault(opt)
-
 			key := opt.Name
 			if hierarchy != "" {
 				key = hierarchy + "." + key
@@ -282,6 +248,53 @@
 	return goplsProperties, goProperties, nil
 }
 
+func toObject(opt *OptionJSON) (*Object, error) {
+	doc := opt.Doc
+	if mappedTo, ok := associatedToExtensionProperties[opt.Name]; ok {
+		doc = fmt.Sprintf("%v\nIf unspecified, values of `%v` will be propagated.\n", doc, strings.Join(mappedTo, ", "))
+	}
+	obj := &Object{
+		MarkdownDescription: doc,
+		// TODO: are all gopls settings in the resource scope?
+		Scope: "resource",
+		// TODO: consider 'additionalProperties' if gopls api-json
+		// outputs acceptable properties.
+		// TODO: deprecation attribute
+	}
+	// Handle any enum types.
+	if opt.Type == "enum" {
+		for _, v := range opt.EnumValues {
+			unquotedName, err := strconv.Unquote(v.Value)
+			if err != nil {
+				return nil, err
+			}
+			obj.Enum = append(obj.Enum, unquotedName)
+			obj.MarkdownEnumDescriptions = append(obj.MarkdownEnumDescriptions, v.Doc)
+		}
+	}
+	// Handle any objects whose keys are enums.
+	if len(opt.EnumKeys.Keys) > 0 {
+		if obj.Properties == nil {
+			obj.Properties = map[string]*Object{}
+		}
+		for _, k := range opt.EnumKeys.Keys {
+			unquotedName, err := strconv.Unquote(k.Name)
+			if err != nil {
+				return nil, err
+			}
+			obj.Properties[unquotedName] = &Object{
+				Type:                propertyType(opt.EnumKeys.ValueType),
+				MarkdownDescription: k.Doc,
+				Default:             formatDefault(k.Default, opt.EnumKeys.ValueType),
+			}
+		}
+	}
+	obj.Type = propertyType(opt.Type)
+	obj.Default = formatOptionDefault(opt)
+
+	return obj, nil
+}
+
 func formatOptionDefault(opt *OptionJSON) interface{} {
 	// Each key will have its own default value, instead of one large global
 	// one. (Alternatively, we can build the default from the keys.)