// Copyright 2022 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 workspace

import (
	"sort"
	"testing"

	"github.com/google/go-cmp/cmp"
	"golang.org/x/tools/gopls/internal/lsp/protocol"
	. "golang.org/x/tools/gopls/internal/lsp/regtest"
)

func TestStandaloneFiles(t *testing.T) {
	const files = `
-- go.mod --
module mod.test

go 1.16
-- lib/lib.go --
package lib

const C = 0

type I interface {
	M()
}
-- lib/ignore.go --
//go:build ignore
// +build ignore

package main

import (
	"mod.test/lib"
)

const C = 1

type Mer struct{}
func (Mer) M()

func main() {
	println(lib.C + C)
}
`
	WithOptions(
		// On Go 1.17 and earlier, this test fails with
		// experimentalWorkspaceModule. Not investigated, as
		// experimentalWorkspaceModule will be removed.
		Modes(Default),
	).Run(t, files, func(t *testing.T, env *Env) {
		// Initially, gopls should not know about the standalone file as it hasn't
		// been opened. Therefore, we should only find one symbol 'C'.
		syms := env.WorkspaceSymbol("C")
		if got, want := len(syms), 1; got != want {
			t.Errorf("got %d symbols, want %d", got, want)
		}

		// Similarly, we should only find one reference to "C", and no
		// implementations of I.
		checkLocations := func(method string, gotLocations []protocol.Location, wantFiles ...string) {
			var gotFiles []string
			for _, l := range gotLocations {
				gotFiles = append(gotFiles, env.Sandbox.Workdir.URIToPath(l.URI))
			}
			sort.Strings(gotFiles)
			sort.Strings(wantFiles)
			if diff := cmp.Diff(wantFiles, gotFiles); diff != "" {
				t.Errorf("%s(...): unexpected locations (-want +got):\n%s", method, diff)
			}
		}

		env.OpenFile("lib/lib.go")
		env.Await(
			OnceMet(
				env.DoneWithOpen(),
				NoOutstandingDiagnostics(),
			),
		)

		// Replacing C with D should not cause any workspace diagnostics, since we
		// haven't yet opened the standalone file.
		env.RegexpReplace("lib/lib.go", "C", "D")
		env.Await(
			OnceMet(
				env.DoneWithChange(),
				NoOutstandingDiagnostics(),
			),
		)
		env.RegexpReplace("lib/lib.go", "D", "C")
		env.Await(
			OnceMet(
				env.DoneWithChange(),
				NoOutstandingDiagnostics(),
			),
		)

		refs := env.References("lib/lib.go", env.RegexpSearch("lib/lib.go", "C"))
		checkLocations("References", refs, "lib/lib.go")

		impls := env.Implementations("lib/lib.go", env.RegexpSearch("lib/lib.go", "I"))
		checkLocations("Implementations", impls) // no implementations

		// Opening the standalone file should not result in any diagnostics.
		env.OpenFile("lib/ignore.go")
		env.Await(
			OnceMet(
				env.DoneWithOpen(),
				NoOutstandingDiagnostics(),
			),
		)

		// Having opened the standalone file, we should find its symbols in the
		// workspace.
		syms = env.WorkspaceSymbol("C")
		if got, want := len(syms), 2; got != want {
			t.Fatalf("got %d symbols, want %d", got, want)
		}

		foundMainC := false
		var symNames []string
		for _, sym := range syms {
			symNames = append(symNames, sym.Name)
			if sym.Name == "main.C" {
				foundMainC = true
			}
		}
		if !foundMainC {
			t.Errorf("WorkspaceSymbol(\"C\") = %v, want containing main.C", symNames)
		}

		// We should resolve workspace definitions in the standalone file.
		file, _ := env.GoToDefinition("lib/ignore.go", env.RegexpSearch("lib/ignore.go", "lib.(C)"))
		if got, want := file, "lib/lib.go"; got != want {
			t.Errorf("GoToDefinition(lib.C) = %v, want %v", got, want)
		}

		// ...as well as intra-file definitions
		file, pos := env.GoToDefinition("lib/ignore.go", env.RegexpSearch("lib/ignore.go", "\\+ (C)"))
		if got, want := file, "lib/ignore.go"; got != want {
			t.Errorf("GoToDefinition(C) = %v, want %v", got, want)
		}
		wantPos := env.RegexpSearch("lib/ignore.go", "const (C)")
		if pos != wantPos {
			t.Errorf("GoToDefinition(C) = %v, want %v", pos, wantPos)
		}

		// Renaming "lib.C" to "lib.D" should cause a diagnostic in the standalone
		// file.
		env.RegexpReplace("lib/lib.go", "C", "D")
		env.Await(
			OnceMet(
				env.DoneWithChange(),
				env.DiagnosticAtRegexp("lib/ignore.go", "lib.(C)"),
			),
		)

		// Undoing the replacement should fix diagnostics
		env.RegexpReplace("lib/lib.go", "D", "C")
		env.Await(
			OnceMet(
				env.DoneWithChange(),
				NoOutstandingDiagnostics(),
			),
		)

		// Now that our workspace has no errors, we should be able to find
		// references and rename.
		refs = env.References("lib/lib.go", env.RegexpSearch("lib/lib.go", "C"))
		checkLocations("References", refs, "lib/lib.go", "lib/ignore.go")

		impls = env.Implementations("lib/lib.go", env.RegexpSearch("lib/lib.go", "I"))
		checkLocations("Implementations", impls, "lib/ignore.go")

		// Renaming should rename in the standalone package.
		env.Rename("lib/lib.go", env.RegexpSearch("lib/lib.go", "C"), "D")
		env.RegexpSearch("lib/ignore.go", "lib.D")
	})
}

func TestStandaloneFiles_Configuration(t *testing.T) {
	const files = `
-- go.mod --
module mod.test

go 1.18
-- lib.go --
package lib // without this package, files are loaded as command-line-arguments
-- ignore.go --
//go:build ignore
// +build ignore

package main

// An arbitrary comment.

func main() {}
-- standalone.go --
//go:build standalone
// +build standalone

package main

func main() {}
`

	WithOptions(
		Settings{
			"standaloneTags": []string{"standalone", "script"},
		},
	).Run(t, files, func(t *testing.T, env *Env) {
		env.OpenFile("ignore.go")
		env.OpenFile("standalone.go")

		env.Await(
			OnceMet(
				env.DoneWithOpen(),
				env.DiagnosticAtRegexp("ignore.go", "package (main)"),
				NoDiagnostics("standalone.go"),
			),
		)

		cfg := env.Editor.Config()
		cfg.Settings = map[string]interface{}{
			"standaloneTags": []string{"ignore"},
		}
		env.ChangeConfiguration(cfg)

		// TODO(golang/go#56158): gopls does not purge previously published
		// diagnostice when configuration changes.
		env.RegexpReplace("ignore.go", "arbitrary", "meaningless")

		env.Await(
			OnceMet(
				env.DoneWithChange(),
				NoDiagnostics("ignore.go"),
				env.DiagnosticAtRegexp("standalone.go", "package (main)"),
			),
		)
	})
}
