mirror of
https://github.com/golang/go.git
synced 2025-05-05 23:53:05 +00:00
go/types, types2: better error messages for invalid qualified identifiers
This change borrows code from CL 631356 by Emmanuel Odeke (thanks!). Fixes #70549. Change-Id: Id6f794ea2a95b4297999456f22c6e02890fce13b Reviewed-on: https://go-review.googlesource.com/c/go/+/662775 LUCI-TryBot-Result: Go LUCI <golang-scoped@luci-project-accounts.iam.gserviceaccount.com> Auto-Submit: Robert Griesemer <gri@google.com> Reviewed-by: Robert Griesemer <gri@google.com> Reviewed-by: Mark Freeman <mark@golang.org>
This commit is contained in:
parent
ab2926291b
commit
5eaeb7b455
@ -720,7 +720,14 @@ func (check *Checker) selector(x *operand, e *syntax.SelectorExpr, def *TypeName
|
|||||||
exp = pkg.scope.Lookup(sel)
|
exp = pkg.scope.Lookup(sel)
|
||||||
if exp == nil {
|
if exp == nil {
|
||||||
if !pkg.fake && isValidName(sel) {
|
if !pkg.fake && isValidName(sel) {
|
||||||
check.errorf(e.Sel, UndeclaredImportedName, "undefined: %s", syntax.Expr(e))
|
// Try to give a better error message when selector matches an object name ignoring case.
|
||||||
|
exps := pkg.scope.lookupIgnoringCase(sel, true)
|
||||||
|
if len(exps) >= 1 {
|
||||||
|
// report just the first one
|
||||||
|
check.errorf(e.Sel, UndeclaredImportedName, "undefined: %s (but have %s)", syntax.Expr(e), exps[0].Name())
|
||||||
|
} else {
|
||||||
|
check.errorf(e.Sel, UndeclaredImportedName, "undefined: %s", syntax.Expr(e))
|
||||||
|
}
|
||||||
}
|
}
|
||||||
goto Error
|
goto Error
|
||||||
}
|
}
|
||||||
|
@ -83,6 +83,19 @@ func (s *Scope) Lookup(name string) Object {
|
|||||||
return obj
|
return obj
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// lookupIgnoringCase returns the objects in scope s whose names match
|
||||||
|
// the given name ignoring case. If exported is set, only exported names
|
||||||
|
// are returned.
|
||||||
|
func (s *Scope) lookupIgnoringCase(name string, exported bool) []Object {
|
||||||
|
var matches []Object
|
||||||
|
for _, n := range s.Names() {
|
||||||
|
if (!exported || isExported(n)) && strings.EqualFold(n, name) {
|
||||||
|
matches = append(matches, s.Lookup(n))
|
||||||
|
}
|
||||||
|
}
|
||||||
|
return matches
|
||||||
|
}
|
||||||
|
|
||||||
// Insert attempts to insert an object obj into scope s.
|
// Insert attempts to insert an object obj into scope s.
|
||||||
// If s already contains an alternative object alt with
|
// If s already contains an alternative object alt with
|
||||||
// the same name, Insert leaves s unchanged and returns alt.
|
// the same name, Insert leaves s unchanged and returns alt.
|
||||||
|
@ -722,7 +722,14 @@ func (check *Checker) selector(x *operand, e *ast.SelectorExpr, def *TypeName, w
|
|||||||
exp = pkg.scope.Lookup(sel)
|
exp = pkg.scope.Lookup(sel)
|
||||||
if exp == nil {
|
if exp == nil {
|
||||||
if !pkg.fake && isValidName(sel) {
|
if !pkg.fake && isValidName(sel) {
|
||||||
check.errorf(e.Sel, UndeclaredImportedName, "undefined: %s", ast.Expr(e))
|
// Try to give a better error message when selector matches an object name ignoring case.
|
||||||
|
exps := pkg.scope.lookupIgnoringCase(sel, true)
|
||||||
|
if len(exps) >= 1 {
|
||||||
|
// report just the first one
|
||||||
|
check.errorf(e.Sel, UndeclaredImportedName, "undefined: %s (but have %s)", ast.Expr(e), exps[0].Name())
|
||||||
|
} else {
|
||||||
|
check.errorf(e.Sel, UndeclaredImportedName, "undefined: %s", ast.Expr(e))
|
||||||
|
}
|
||||||
}
|
}
|
||||||
goto Error
|
goto Error
|
||||||
}
|
}
|
||||||
|
@ -86,6 +86,19 @@ func (s *Scope) Lookup(name string) Object {
|
|||||||
return obj
|
return obj
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// lookupIgnoringCase returns the objects in scope s whose names match
|
||||||
|
// the given name ignoring case. If exported is set, only exported names
|
||||||
|
// are returned.
|
||||||
|
func (s *Scope) lookupIgnoringCase(name string, exported bool) []Object {
|
||||||
|
var matches []Object
|
||||||
|
for _, n := range s.Names() {
|
||||||
|
if (!exported || isExported(n)) && strings.EqualFold(n, name) {
|
||||||
|
matches = append(matches, s.Lookup(n))
|
||||||
|
}
|
||||||
|
}
|
||||||
|
return matches
|
||||||
|
}
|
||||||
|
|
||||||
// Insert attempts to insert an object obj into scope s.
|
// Insert attempts to insert an object obj into scope s.
|
||||||
// If s already contains an alternative object alt with
|
// If s already contains an alternative object alt with
|
||||||
// the same name, Insert leaves s unchanged and returns alt.
|
// the same name, Insert leaves s unchanged and returns alt.
|
||||||
|
15
src/internal/types/testdata/fixedbugs/issue70549.go
vendored
Normal file
15
src/internal/types/testdata/fixedbugs/issue70549.go
vendored
Normal file
@ -0,0 +1,15 @@
|
|||||||
|
// 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 p
|
||||||
|
|
||||||
|
import "math"
|
||||||
|
|
||||||
|
var (
|
||||||
|
_ = math.Sin
|
||||||
|
_ = math.SIn /* ERROR "undefined: math.SIn (but have Sin)" */
|
||||||
|
_ = math.sin /* ERROR "name sin not exported by package math" */
|
||||||
|
_ = math.Foo /* ERROR "undefined: math.Foo" */
|
||||||
|
_ = math.foo /* ERROR "undefined: math.foo" */
|
||||||
|
)
|
Loading…
x
Reference in New Issue
Block a user