}
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.
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) {
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
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") {
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() {
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