x/text: fix nil dereference in gotext extract
Ident.Obj may be nil if the referenced declaration is in another file.
Fixes golang/go#60555
Change-Id: I730af89c7f52540b305b3da8c19448d089e9744c
Reviewed-on: https://go-review.googlesource.com/c/text/+/545055
Reviewed-by: Emmanuel Odeke <emmanuel@orijtech.com>
Reviewed-by: Junyang Shao <shaojunyang@google.com>
LUCI-TryBot-Result: Go LUCI <golang-scoped@luci-project-accounts.iam.gserviceaccount.com>
Reviewed-by: Sean Liao <sean@liao.dev>
Auto-Submit: Emmanuel Odeke <emmanuel@orijtech.com>
Reviewed-by: Michael Knyszek <mknyszek@google.com>
diff --git a/message/pipeline/extract.go b/message/pipeline/extract.go
index 23e58f0..7d8385d 100644
--- a/message/pipeline/extract.go
+++ b/message/pipeline/extract.go
@@ -597,9 +597,13 @@
key := []string{}
if ident, ok := format.(*ast.Ident); ok {
key = append(key, ident.Name)
- if v, ok := ident.Obj.Decl.(*ast.ValueSpec); ok && v.Comment != nil {
- // TODO: get comment above ValueSpec as well
- comment = v.Comment.Text()
+ // Ident.Obj may be nil if the referenced declaration is in another
+ // file.
+ if ident.Obj != nil {
+ if v, ok := ident.Obj.Decl.(*ast.ValueSpec); ok && v.Comment != nil {
+ // TODO: get comment above ValueSpec as well
+ comment = v.Comment.Text()
+ }
}
}
if c := px.getComment(call.Args[0]); c != "" {
diff --git a/message/pipeline/testdata/test60555/catalog_gen.go b/message/pipeline/testdata/test60555/catalog_gen.go
new file mode 100644
index 0000000..dce54af
--- /dev/null
+++ b/message/pipeline/testdata/test60555/catalog_gen.go
@@ -0,0 +1,38 @@
+// Code generated by running "go generate" in golang.org/x/text. DO NOT EDIT.
+
+package main
+
+import (
+ "golang.org/x/text/language"
+ "golang.org/x/text/message"
+ "golang.org/x/text/message/catalog"
+)
+
+type dictionary struct {
+ index []uint32
+ data string
+}
+
+func (d *dictionary) Lookup(key string) (data string, ok bool) {
+ p, ok := messageKeyToIndex[key]
+ if !ok {
+ return "", false
+ }
+ start, end := d.index[p], d.index[p+1]
+ if start == end {
+ return "", false
+ }
+ return d.data[start:end], true
+}
+
+func init() {
+ dict := map[string]catalog.Dictionary{}
+ fallback := language.MustParse("en-US")
+ cat, err := catalog.NewFromMap(dict, catalog.Fallback(fallback))
+ if err != nil {
+ panic(err)
+ }
+ message.DefaultCatalog = cat
+}
+
+var messageKeyToIndex = map[string]int{}
diff --git a/message/pipeline/testdata/test60555/extracted.gotext.json.want b/message/pipeline/testdata/test60555/extracted.gotext.json.want
new file mode 100644
index 0000000..2abf7b7
--- /dev/null
+++ b/message/pipeline/testdata/test60555/extracted.gotext.json.want
@@ -0,0 +1,15 @@
+{
+ "language": "en-US",
+ "messages": [
+ {
+ "id": [
+ "testMessage",
+ "Test message"
+ ],
+ "key": "Test message",
+ "message": "Test message",
+ "translation": "",
+ "position": "testdata/test60555/main.go:17:10"
+ }
+ ]
+}
\ No newline at end of file
diff --git a/message/pipeline/testdata/test60555/main.go b/message/pipeline/testdata/test60555/main.go
new file mode 100644
index 0000000..69b7529
--- /dev/null
+++ b/message/pipeline/testdata/test60555/main.go
@@ -0,0 +1,18 @@
+// Copyright 2025 The Go Authors. All rights reserved.
+// Use of this source code is governed by a BSD-style
+// license that can be found in the LICENSE file.
+
+package main
+
+import (
+ "golang.org/x/text/language"
+ "golang.org/x/text/message"
+)
+
+// Ensures that we can catch any regressions with nil dereferences
+// from const declarations in other files within the same package.
+// See issue https://golang.org/issues/60555
+func main() {
+ p := message.NewPrinter(language.English)
+ p.Printf(testMessage)
+}
diff --git a/message/pipeline/testdata/test60555/message.go b/message/pipeline/testdata/test60555/message.go
new file mode 100644
index 0000000..ea2a98c
--- /dev/null
+++ b/message/pipeline/testdata/test60555/message.go
@@ -0,0 +1,7 @@
+// Copyright 2025 The Go Authors. All rights reserved.
+// Use of this source code is governed by a BSD-style
+// license that can be found in the LICENSE file.
+
+package main
+
+const testMessage = "Test message"