// Copyright 2011 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 types_test

import (
	"fmt"
	"go/ast"
	"go/importer"
	"go/parser"
	"go/token"
	"internal/testenv"
	"sort"
	"testing"

	. "go/types"
)

type resolveTestImporter struct {
	importer ImporterFrom
	imported map[string]bool
}

func (imp *resolveTestImporter) Import(string) (*Package, error) {
	panic("should not be called")
}

func (imp *resolveTestImporter) ImportFrom(path, srcDir string, mode ImportMode) (*Package, error) {
	if mode != 0 {
		panic("mode must be 0")
	}
	if imp.importer == nil {
		imp.importer = importer.Default().(ImporterFrom)
		imp.imported = make(map[string]bool)
	}
	pkg, err := imp.importer.ImportFrom(path, srcDir, mode)
	if err != nil {
		return nil, err
	}
	imp.imported[path] = true
	return pkg, nil
}

func TestResolveIdents(t *testing.T) {
	testenv.MustHaveGoBuild(t)

	sources := []string{
		`
		package p
		import "fmt"
		import "math"
		const pi = math.Pi
		func sin(x float64) float64 {
			return math.Sin(x)
		}
		var Println = fmt.Println
		`,
		`
		package p
		import "fmt"
		type errorStringer struct { fmt.Stringer; error }
		func f() string {
			_ = "foo"
			return fmt.Sprintf("%d", g())
		}
		func g() (x int) { return }
		`,
		`
		package p
		import . "go/parser"
		import "sync"
		func h() Mode { return ImportsOnly }
		var _, x int = 1, 2
		func init() {}
		type T struct{ *sync.Mutex; a, b, c int}
		type I interface{ m() }
		var _ = T{a: 1, b: 2, c: 3}
		func (_ T) m() {}
		func (T) _() {}
		var i I
		var _ = i.m
		func _(s []int) { for i, x := range s { _, _ = i, x } }
		func _(x interface{}) {
			switch x := x.(type) {
			case int:
				_ = x
			}
			switch {} // implicit 'true' tag
		}
		`,
		`
		package p
		type S struct{}
		func (T) _() {}
		func (T) _() {}
		`,
		`
		package p
		func _() {
		L0:
		L1:
			goto L0
			for {
				goto L1
			}
			if true {
				goto L2
			}
		L2:
		}
		`,
	}

	pkgnames := []string{
		"fmt",
		"math",
	}

	// parse package files
	fset := token.NewFileSet()
	var files []*ast.File
	for i, src := range sources {
		f, err := parser.ParseFile(fset, fmt.Sprintf("sources[%d]", i), src, parser.DeclarationErrors)
		if err != nil {
			t.Fatal(err)
		}
		files = append(files, f)
	}

	// resolve and type-check package AST
	importer := new(resolveTestImporter)
	conf := Config{Importer: importer}
	uses := make(map[*ast.Ident]Object)
	defs := make(map[*ast.Ident]Object)
	_, err := conf.Check("testResolveIdents", fset, files, &Info{Defs: defs, Uses: uses})
	if err != nil {
		t.Fatal(err)
	}

	// check that all packages were imported
	for _, name := range pkgnames {
		if !importer.imported[name] {
			t.Errorf("package %s not imported", name)
		}
	}

	// check that qualified identifiers are resolved
	for _, f := range files {
		ast.Inspect(f, func(n ast.Node) bool {
			if s, ok := n.(*ast.SelectorExpr); ok {
				if x, ok := s.X.(*ast.Ident); ok {
					obj := uses[x]
					if obj == nil {
						t.Errorf("%s: unresolved qualified identifier %s", fset.Position(x.Pos()), x.Name)
						return false
					}
					if _, ok := obj.(*PkgName); ok && uses[s.Sel] == nil {
						t.Errorf("%s: unresolved selector %s", fset.Position(s.Sel.Pos()), s.Sel.Name)
						return false
					}
					return false
				}
				return false
			}
			return true
		})
	}

	for id, obj := range uses {
		if obj == nil {
			t.Errorf("%s: Uses[%s] == nil", fset.Position(id.Pos()), id.Name)
		}
	}

	// check that each identifier in the source is found in uses or defs or both
	var both []string
	for _, f := range files {
		ast.Inspect(f, func(n ast.Node) bool {
			if x, ok := n.(*ast.Ident); ok {
				var objects int
				if _, found := uses[x]; found {
					objects |= 1
					delete(uses, x)
				}
				if _, found := defs[x]; found {
					objects |= 2
					delete(defs, x)
				}
				if objects == 0 {
					t.Errorf("%s: unresolved identifier %s", fset.Position(x.Pos()), x.Name)
				} else if objects == 3 {
					both = append(both, x.Name)
				}
				return false
			}
			return true
		})
	}

	// check the expected set of idents that are simultaneously uses and defs
	sort.Strings(both)
	if got, want := fmt.Sprint(both), "[Mutex Stringer error]"; got != want {
		t.Errorf("simultaneous uses/defs = %s, want %s", got, want)
	}

	// any left-over identifiers didn't exist in the source
	for x := range uses {
		t.Errorf("%s: identifier %s not present in source", fset.Position(x.Pos()), x.Name)
	}
	for x := range defs {
		t.Errorf("%s: identifier %s not present in source", fset.Position(x.Pos()), x.Name)
	}

	// TODO(gri) add tests to check ImplicitObj callbacks
}
