Commit 9364c0e3 authored by Russ Cox's avatar Russ Cox

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: 's avatarIan Lance Taylor <iant@golang.org>
TryBot-Result: Gobot Gobot <gobot@golang.org>
parent c1e026a5
......@@ -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
......
Markdown is supported
0% or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment