[gopls-release-branch.0.14] gopls/internal/lsp: fix code action panic on params of external funcs

Fix a panic when inspecting a nil function body.

Fixes golang/go#63755

Change-Id: I39342902b44192dd373dfdb24947079b40dbe115
Reviewed-on: https://go-review.googlesource.com/c/tools/+/537878
LUCI-TryBot-Result: Go LUCI <golang-scoped@luci-project-accounts.iam.gserviceaccount.com>
Reviewed-by: Alan Donovan <adonovan@google.com>
(cherry picked from commit 080c20204649f4ff382fee2ae9b7304c044286ae)
Reviewed-on: https://go-review.googlesource.com/c/tools/+/537879
Auto-Submit: Robert Findley <rfindley@google.com>
Reviewed-by: Peter Weinberger <pjw@google.com>
diff --git a/gopls/internal/lsp/code_action.go b/gopls/internal/lsp/code_action.go
index d756748..45a4c47 100644
--- a/gopls/internal/lsp/code_action.go
+++ b/gopls/internal/lsp/code_action.go
@@ -541,6 +541,10 @@
 		return false
 	}
 
+	if info.Decl.Body == nil {
+		return false // external function
+	}
+
 	if len(info.Field.Names) == 0 {
 		return true // no names => field is unused
 	}
diff --git a/gopls/internal/regtest/misc/fix_test.go b/gopls/internal/regtest/misc/fix_test.go
index 7a5e530..67e37c9 100644
--- a/gopls/internal/regtest/misc/fix_test.go
+++ b/gopls/internal/regtest/misc/fix_test.go
@@ -101,3 +101,36 @@
 		env.AfterChange(NoDiagnostics(ForFile("main.go")))
 	})
 }
+
+func TestUnusedParameter_Issue63755(t *testing.T) {
+	// This test verifies the fix for #63755, where codeActions panicked on parameters
+	// of functions with no function body.
+
+	// We should not detect parameters as unused for external functions.
+
+	const files = `
+-- go.mod --
+module unused.mod
+
+go 1.18
+
+-- external.go --
+package external
+
+func External(z int) //@codeaction("refactor.rewrite", "z", "z", recursive)
+
+func _() {
+	External(1)
+}
+	`
+	Run(t, files, func(t *testing.T, env *Env) {
+		env.OpenFile("external.go")
+		actions, err := env.Editor.CodeAction(env.Ctx, env.RegexpSearch("external.go", "z"), nil)
+		if err != nil {
+			t.Fatal(err)
+		}
+		if len(actions) > 0 {
+			t.Errorf("CodeAction(): got %d code actions, want 0", len(actions))
+		}
+	})
+}