// Copyright 2015 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 (
	"go/ast"
	"go/types"
	"strings"
	"unicode"
	"unicode/utf8"
)

func init() {
	register("tests",
		"check for common mistaken usages of tests/documentation examples",
		checkTestFunctions,
		funcDecl)
}

func isExampleSuffix(s string) bool {
	r, size := utf8.DecodeRuneInString(s)
	return size > 0 && unicode.IsLower(r)
}

func isTestSuffix(name string) bool {
	if len(name) == 0 {
		// "Test" is ok.
		return true
	}
	r, _ := utf8.DecodeRuneInString(name)
	return !unicode.IsLower(r)
}

func isTestParam(typ ast.Expr, wantType string) bool {
	ptr, ok := typ.(*ast.StarExpr)
	if !ok {
		// Not a pointer.
		return false
	}
	// No easy way of making sure it's a *testing.T or *testing.B:
	// ensure the name of the type matches.
	if name, ok := ptr.X.(*ast.Ident); ok {
		return name.Name == wantType
	}
	if sel, ok := ptr.X.(*ast.SelectorExpr); ok {
		return sel.Sel.Name == wantType
	}
	return false
}

func lookup(name string, scopes []*types.Scope) types.Object {
	for _, scope := range scopes {
		if o := scope.Lookup(name); o != nil {
			return o
		}
	}
	return nil
}

func extendedScope(pkg *Package) []*types.Scope {
	scopes := []*types.Scope{pkg.typesPkg.Scope()}

	pkgName := pkg.typesPkg.Name()
	if strings.HasPrefix(pkgName, "_test") {
		basePkg := strings.TrimSuffix(pkgName, "_test")
		for _, p := range pkg.typesPkg.Imports() {
			if p.Name() == basePkg {
				scopes = append(scopes, p.Scope())
				break
			}
		}
	}
	return scopes
}

func checkExample(fn *ast.FuncDecl, pkg *Package, report reporter) {
	fnName := fn.Name.Name
	if params := fn.Type.Params; len(params.List) != 0 {
		report("%s should be niladic", fnName)
	}
	if results := fn.Type.Results; results != nil && len(results.List) != 0 {
		report("%s should return nothing", fnName)
	}

	if filesRun && !includesNonTest {
		// The coherence checks between a test and the package it tests
		// will report false positives if no non-test files have
		// been provided.
		return
	}

	if fnName == "Example" {
		// Nothing more to do.
		return
	}

	var (
		exName = strings.TrimPrefix(fnName, "Example")
		elems  = strings.SplitN(exName, "_", 3)
		ident  = elems[0]
		obj    = lookup(ident, extendedScope(pkg))
	)
	if ident != "" && obj == nil {
		// Check ExampleFoo and ExampleBadFoo.
		report("%s refers to unknown identifier: %s", fnName, ident)
		// Abort since obj is absent and no subsequent checks can be performed.
		return
	}
	if len(elems) < 2 {
		// Nothing more to do.
		return
	}

	if ident == "" {
		// Check Example_suffix and Example_BadSuffix.
		if residual := strings.TrimPrefix(exName, "_"); !isExampleSuffix(residual) {
			report("%s has malformed example suffix: %s", fnName, residual)
		}
		return
	}

	mmbr := elems[1]
	if !isExampleSuffix(mmbr) {
		// Check ExampleFoo_Method and ExampleFoo_BadMethod.
		if obj, _, _ := types.LookupFieldOrMethod(obj.Type(), true, obj.Pkg(), mmbr); obj == nil {
			report("%s refers to unknown field or method: %s.%s", fnName, ident, mmbr)
		}
	}
	if len(elems) == 3 && !isExampleSuffix(elems[2]) {
		// Check ExampleFoo_Method_suffix and ExampleFoo_Method_Badsuffix.
		report("%s has malformed example suffix: %s", fnName, elems[2])
	}
}

func checkTest(fn *ast.FuncDecl, prefix string, report reporter) {
	// Want functions with 0 results and 1 parameter.
	if fn.Type.Results != nil && len(fn.Type.Results.List) > 0 ||
		fn.Type.Params == nil ||
		len(fn.Type.Params.List) != 1 ||
		len(fn.Type.Params.List[0].Names) > 1 {
		return
	}

	// The param must look like a *testing.T or *testing.B.
	if !isTestParam(fn.Type.Params.List[0].Type, prefix[:1]) {
		return
	}

	if !isTestSuffix(fn.Name.Name[len(prefix):]) {
		report("%s has malformed name: first letter after '%s' must not be lowercase", fn.Name.Name, prefix)
	}
}

type reporter func(format string, args ...interface{})

// checkTestFunctions walks Test, Benchmark and Example functions checking
// malformed names, wrong signatures and examples documenting inexistent
// identifiers.
func checkTestFunctions(f *File, node ast.Node) {
	if !strings.HasSuffix(f.name, "_test.go") {
		return
	}

	fn, ok := node.(*ast.FuncDecl)
	if !ok || fn.Recv != nil {
		// Ignore non-functions or functions with receivers.
		return
	}

	report := func(format string, args ...interface{}) { f.Badf(node.Pos(), format, args...) }

	switch {
	case strings.HasPrefix(fn.Name.Name, "Example"):
		checkExample(fn, f.pkg, report)
	case strings.HasPrefix(fn.Name.Name, "Test"):
		checkTest(fn, "Test", report)
	case strings.HasPrefix(fn.Name.Name, "Benchmark"):
		checkTest(fn, "Benchmark", report)
	}
}
