mirror of
https://github.com/golang/go
synced 2024-11-23 17:00:07 -07:00
cmd/vet: do not import net/http at startup
The httpresponse.go module wants to be able to tell if a particular type t is net/http.Response (and also net/http.Client). It does this by importing net/http, looking up Response, and then comparing that saved type against each t. Instead of doing an eager import of net/http, wait until we have a type t to ask a question about, and then just look to see if that t is http.Response. This kind of lazy check does not require assuming that net/http is available or will be important (perhaps the check is disabled in this run, or perhaps other conditions that lead to the comparison are not satisfied). Not loading these kinds of types at startup time will scale better. Change-Id: Ibb00623901a96e725a4ff6f231e6d15127979dfd Reviewed-on: https://go-review.googlesource.com/74353 Run-TryBot: Russ Cox <rsc@golang.org> Reviewed-by: Ian Lance Taylor <iant@golang.org> TryBot-Result: Gobot Gobot <gobot@golang.org>
This commit is contained in:
parent
c1e026a5f6
commit
9364c0e337
@ -19,10 +19,6 @@ func init() {
|
||||
}
|
||||
|
||||
func checkHTTPResponse(f *File, node ast.Node) {
|
||||
// If http.Response or http.Client are not defined, skip this check.
|
||||
if httpResponseType == nil || httpClientType == nil {
|
||||
return
|
||||
}
|
||||
call := node.(*ast.CallExpr)
|
||||
if !isHTTPFuncOrMethodOnClient(f, call) {
|
||||
return // the function call is not related to this check.
|
||||
@ -72,7 +68,7 @@ func isHTTPFuncOrMethodOnClient(f *File, expr *ast.CallExpr) bool {
|
||||
if res.Len() != 2 {
|
||||
return false // the function called does not return two values.
|
||||
}
|
||||
if ptr, ok := res.At(0).Type().(*types.Pointer); !ok || !types.Identical(ptr.Elem(), httpResponseType) {
|
||||
if ptr, ok := res.At(0).Type().(*types.Pointer); !ok || !isNamedType(ptr.Elem(), "net/http", "Response") {
|
||||
return false // the first return type is not *http.Response.
|
||||
}
|
||||
if !types.Identical(res.At(1).Type().Underlying(), errorType) {
|
||||
@ -85,11 +81,11 @@ func isHTTPFuncOrMethodOnClient(f *File, expr *ast.CallExpr) bool {
|
||||
return ok && id.Name == "http" // function in net/http package.
|
||||
}
|
||||
|
||||
if types.Identical(typ, httpClientType) {
|
||||
if isNamedType(typ, "net/http", "Client") {
|
||||
return true // method on http.Client.
|
||||
}
|
||||
ptr, ok := typ.(*types.Pointer)
|
||||
return ok && types.Identical(ptr.Elem(), httpClientType) // method on *http.Client.
|
||||
return ok && isNamedType(ptr.Elem(), "net/http", "Client") // method on *http.Client.
|
||||
}
|
||||
|
||||
// blockStmtFinder is an ast.Visitor that given any ast node can find the
|
||||
|
@ -161,7 +161,7 @@ func checkTest(fn *ast.FuncDecl, prefix string, report reporter) {
|
||||
type reporter func(format string, args ...interface{})
|
||||
|
||||
// checkTestFunctions walks Test, Benchmark and Example functions checking
|
||||
// malformed names, wrong signatures and examples documenting inexistent
|
||||
// malformed names, wrong signatures and examples documenting nonexistent
|
||||
// identifiers.
|
||||
func checkTestFunctions(f *File, node ast.Node) {
|
||||
if !strings.HasSuffix(f.name, "_test.go") {
|
||||
|
@ -19,11 +19,9 @@ import (
|
||||
var stdImporter types.Importer
|
||||
|
||||
var (
|
||||
errorType *types.Interface
|
||||
stringerType *types.Interface // possibly nil
|
||||
formatterType *types.Interface // possibly nil
|
||||
httpResponseType types.Type // possibly nil
|
||||
httpClientType types.Type // possibly nil
|
||||
errorType *types.Interface
|
||||
stringerType *types.Interface // possibly nil
|
||||
formatterType *types.Interface // possibly nil
|
||||
)
|
||||
|
||||
func inittypes() {
|
||||
@ -35,12 +33,16 @@ func inittypes() {
|
||||
if typ := importType("fmt", "Formatter"); typ != nil {
|
||||
formatterType = typ.Underlying().(*types.Interface)
|
||||
}
|
||||
if typ := importType("net/http", "Response"); typ != nil {
|
||||
httpResponseType = typ
|
||||
}
|
||||
if typ := importType("net/http", "Client"); typ != nil {
|
||||
httpClientType = typ
|
||||
}
|
||||
|
||||
// isNamedType reports whether t is the named type path.name.
|
||||
func isNamedType(t types.Type, path, name string) bool {
|
||||
n, ok := t.(*types.Named)
|
||||
if !ok {
|
||||
return false
|
||||
}
|
||||
obj := n.Obj()
|
||||
return obj.Name() == name && obj.Pkg() != nil && obj.Pkg().Path() == path
|
||||
}
|
||||
|
||||
// importType returns the type denoted by the qualified identifier
|
||||
|
Loading…
Reference in New Issue
Block a user