These tests check that postfix completions do and do not show up in certain
cases. Tests for the postfix completion contents are implemented as ad-hoc
integration tests.

-- flags --
-ignore_extra_diags

-- go.mod --
module golang.org/lsptests/snippets

go 1.18

-- postfix.go --
package snippets

import (
	"strconv"
)

func _() {
	var foo []int
	foo.append //@rank(re"() \\/\\/", postfixAppend)

	[]int{}.append //@complete(re"() \\/\\/")

	[]int{}.last //@complete(re"() \\/\\/")


	foo.copy //@rank(re"() \\/\\/", postfixCopy)

	var s struct{ i []int }
	s.i.copy //@rank(re"() \\/\\/", postfixCopy)

	var _ []int = s.i.copy //@complete(re"() \\/\\/")

	var blah func() []int
	blah().append //@complete(re"() \\/\\/")
}

func _() {
	/* append! */ //@item(postfixAppend, "append!", "append and re-assign slice", "snippet")
	/* copy! */ //@item(postfixCopy, "copy!", "duplicate slice", "snippet")
	/* for! */ //@item(postfixFor, "for!", "range over slice by index", "snippet")
	/* forr! */ //@item(postfixForr, "forr!", "range over slice by index and value", "snippet")
	/* last! */ //@item(postfixLast, "last!", "s[len(s)-1]", "snippet")
	/* len! */ //@item(postfixLen, "len!", "len(s)", "snippet")
	/* print! */ //@item(postfixPrint, "print!", "print to stdout", "snippet")
	/* range! */ //@item(postfixRange, "range!", "range over slice", "snippet")
	/* reverse! */ //@item(postfixReverse, "reverse!", "reverse slice", "snippet")
	/* sort! */ //@item(postfixSort, "sort!", "sort.Slice()", "snippet")
	/* var! */ //@item(postfixVar, "var!", "assign to variable", "snippet")
	/* ifnotnil! */ //@item(postfixIfNotNil, "ifnotnil!", "if expr != nil", "snippet")

	var foo []int
	foo. //@complete(re"() \\/\\/", postfixAppend, postfixCopy, postfixFor, postfixForr, postfixIfNotNil, postfixLast, postfixLen, postfixPrint, postfixRange, postfixReverse, postfixSort, postfixVar)
	foo = nil

	foo.append //@snippet(re"() \\/\\/", postfixAppend, "foo = append(foo, $0)")
	foo.copy //snippet(re"() \\/\\/", postfixCopy, "fooCopy := make([]int, len(foo))\ncopy($fooCopy, foo)\n")
	foo.fo //@snippet(re"() \\/\\/", postfixFor, "for ${1:} := range foo {\n\t$0\n}")
	foo.forr //@snippet(re"() \\/\\/", postfixForr, "for ${1:}, ${2:} := range foo {\n\t$0\n}")
	foo.last //@snippet(re"() \\/\\/", postfixLast, "foo[len(foo)-1]")
	foo.len //@snippet(re"() \\/\\/", postfixLen, "len(foo)")
	foo.print //@snippet(re"() \\/\\/", postfixPrint, `fmt.Printf("foo: %v\n", foo)`)
	foo.rang //@snippet(re"() \\/\\/", postfixRange, "for ${1:}, ${2:} := range foo {\n\t$0\n}")
	foo.reverse //@snippet(re"() \\/\\/", postfixReverse, "slices.Reverse(foo)")
	foo.sort //@snippet(re"() \\/\\/", postfixSort, "sort.Slice(foo, func(i, j int) bool {\n\t$0\n})")
	foo.va //@snippet(re"() \\/\\/", postfixVar, "${1:} := foo")
	foo.ifnotnil //@snippet(re"() \\/\\/", postfixIfNotNil, "if foo != nil {\n\t$0\n}")
}

func _() {
	/* for! */ //@item(postfixForMap, "for!", "range over map by key", "snippet")
	/* forr! */ //@item(postfixForrMap, "forr!", "range over map by key and value", "snippet")
	/* range! */ //@item(postfixRangeMap, "range!", "range over map", "snippet")
	/* clear! */ //@item(postfixClear, "clear!", "clear map contents", "snippet")
	/* keys! */ //@item(postfixKeys, "keys!", "create slice of keys", "snippet")

	var foo map[int]int
	foo. //@complete(re"() \\/\\/", postfixClear, postfixForMap, postfixForrMap, postfixIfNotNil, postfixKeys, postfixLen, postfixPrint, postfixRangeMap, postfixVar)

	foo = nil

	foo.fo //@snippet(re"() \\/\\/", postfixFor, "for ${1:} := range foo {\n\t$0\n}")
	foo.forr //@snippet(re"() \\/\\/", postfixForr, "for ${1:}, ${2:} := range foo {\n\t$0\n}")
	foo.rang //@snippet(re"() \\/\\/", postfixRange, "for ${1:}, ${2:} := range foo {\n\t$0\n}")
	foo.clear //@snippet(re"() \\/\\/", postfixClear, "for k := range foo {\n\tdelete(foo, k)\n}\n")
	foo.keys //@snippet(re"() \\/\\/", postfixKeys, "keys := make([]int, 0, len(foo))\nfor k := range foo {\n\tkeys = append(keys, k)\n}\n")
}

func _() {
	/* for! */ //@item(postfixForChannel, "for!", "range over channel", "snippet")
	/* range! */ //@item(postfixRangeChannel, "range!", "range over channel", "snippet")

	var foo chan int
	foo. //@complete(re"() \\/\\/", postfixForChannel, postfixIfNotNil, postfixLen, postfixPrint, postfixRangeChannel, postfixVar)

	foo = nil

	foo.fo //@snippet(re"() \\/\\/", postfixForChannel, "for ${1:} := range foo {\n\t$0\n}")
	foo.rang //@snippet(re"() \\/\\/", postfixRangeChannel, "for ${1:} := range foo {\n\t$0\n}")
}

type T struct {
	Name string
}

func _() (string, T, map[string]string, error) {
	/* iferr! */ //@item(postfixIfErr, "iferr!", "check error and return", "snippet")
	/* variferr! */ //@item(postfixVarIfErr, "variferr!", "assign variables and check error", "snippet")
	/* var! */ //@item(postfixVars, "var!", "assign to variables", "snippet")

	strconv.Atoi("32"). //@complete(re"() \\/\\/", postfixIfErr, postfixPrint, postfixVars, postfixVarIfErr)

	var err error
	err.iferr //@snippet(re"() \\/\\/", postfixIfErr, "if err != nil {\n\treturn \"\", T{}, nil, ${1:}\n}\n")

	strconv.Atoi("32").iferr //@snippet(re"() \\/\\/", postfixIfErr, "if _, err := strconv.Atoi(\"32\"); err != nil {\n\treturn \"\", T{}, nil, ${1:}\n}\n")

	strconv.Atoi("32").variferr //@snippet(re"() \\/\\/", postfixVarIfErr, "${1:}, ${2:} := strconv.Atoi(\"32\")\nif ${2:} != nil {\n\treturn \"\", T{}, nil, ${3:}\n}\n")

	// test function return multiple errors
	var foo func() (error, error)
	foo().iferr //@snippet(re"() \\/\\/", postfixIfErr, "if _, err := foo(); err != nil {\n\treturn \"\", T{}, nil, ${1:}\n}\n")
	foo().variferr //@snippet(re"() \\/\\/", postfixVarIfErr, "${1:}, ${2:} := foo()\nif ${2:} != nil {\n\treturn \"\", T{}, nil, ${3:}\n}\n")

	// test function just return error
	var bar func() error
	bar().iferr //@snippet(re"() \\/\\/", postfixIfErr, "if err := bar(); err != nil {\n\treturn \"\", T{}, nil, ${1:}\n}\n")
	bar().variferr //@snippet(re"() \\/\\/", postfixVarIfErr, "${1:} := bar()\nif ${1:} != nil {\n\treturn \"\", T{}, nil, ${2:}\n}\n")
}

func _(){
	/* tostring! */ //@item(postfixToString, "tostring!", "[]byte to string", "snippet")
	var bs []byte
	bs. //@complete(re"() \\/\\/", postfixAppend, postfixCopy, postfixFor, postfixForr, postfixIfNotNil, postfixLast, postfixLen, postfixPrint, postfixRange, postfixReverse, postfixSort, postfixToString, postfixVar)
	bs = nil

	/* tobytes! */ //@item(postfixToBytes, "tobytes!", "string to []byte", "snippet")
	/* split! */ //@item(postfixSplit, "split!", "split string", "snippet")
	var s string
	s. //@complete(re"() \\/\\/", postfixPrint, postfixSplit, postfixToBytes, postfixVar)
	s = ""

	/* tostring! */ //@item(postfixIntToString, "tostring!", "int to string", "snippet")
	var i int
	i. //@complete(re"() \\/\\/", postfixPrint, postfixIntToString, postfixVar)
	i = 0
}
