// Copyright 2009 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 imports

import "io"

import (
	_ "io"
)

import _ "io"

import (
	"io"
	"io"
	"io"
)

import (
	"io"
	aLongRename "io"

	b "io"
)

import (
	"unrenamed"
	renamed "renameMe"
	. "io"
	_ "io"
	"io"
	. "os"
)

// no newlines between consecutive single imports, but
// respect extra line breaks in the source (at most one empty line)
import _ "io"
import _ "io"
import _ "io"

import _ "os"
import _ "os"
import _ "os"

import _ "fmt"
import _ "fmt"
import _ "fmt"

import "foo"	// a comment
import "bar"	// a comment

import (
	_ "foo"
	// a comment
	"bar"
	"foo"	// a comment
	"bar"	// a comment
)

// comments + renames
import (
	"unrenamed"	// a comment
	renamed "renameMe"
	. "io"		/* a comment */
	_ "io/ioutil"	// a comment
	"io"		// testing alignment
	. "os"
	// a comment
)

// a case that caused problems in the past (comment placement)
import (
	. "fmt"
	"io"
	"malloc"	// for the malloc count test only
	"math"
	"strings"
	"testing"
)

// more import examples
import (
	"xxx"
	"much_longer_name"	// comment
	"short_name"		// comment
)

import (
	_ "xxx"
	"much_longer_name"	// comment
)

import (
	mymath "math"
	"/foo/bar/long_package_path"	// a comment
)

import (
	"package_a"	// comment
	"package_b"
	my_better_c "package_c"	// comment
	"package_d"		// comment
	my_e "package_e"	// comment

	"package_a"	// comment
	"package_bb"
	"package_ccc"	// comment
	"package_dddd"	// comment
)

// at least one empty line between declarations of different kind
import _ "io"

var _ int

// at least one empty line between declarations of the same kind
// if there is associated documentation (was issue 2570)
type T1 struct{}

// T2 comment
type T2 struct {
}	// should be a two-line struct

// T3 comment
type T2 struct {
}	// should be a two-line struct

// printing of constant literals
const (
	_	= "foobar"
	_	= "a۰۱۸"
	_	= "foo६४"
	_	= "bar９８７６"
	_	= 0
	_	= 1
	_	= 123456789012345678890
	_	= 01234567
	_	= 0xcafebabe
	_	= 0.
	_	= .0
	_	= 3.14159265
	_	= 1e0
	_	= 1e+100
	_	= 1e-100
	_	= 2.71828e-1000
	_	= 0i
	_	= 1i
	_	= 012345678901234567889i
	_	= 123456789012345678890i
	_	= 0.i
	_	= .0i
	_	= 3.14159265i
	_	= 1e0i
	_	= 1e+100i
	_	= 1e-100i
	_	= 2.71828e-1000i
	_	= 'a'
	_	= '\000'
	_	= '\xFF'
	_	= '\uff16'
	_	= '\U0000ff16'
	_	= `foobar`
	_	= `foo
---
---
bar`
)

func _() {
	type _ int
	type _ *int
	type _ []int
	type _ map[string]int
	type _ chan int
	type _ func() int

	var _ int
	var _ *int
	var _ []int
	var _ map[string]int
	var _ chan int
	var _ func() int

	type _ struct{}
	type _ *struct{}
	type _ []struct{}
	type _ map[string]struct{}
	type _ chan struct{}
	type _ func() struct{}

	type _ interface{}
	type _ *interface{}
	type _ []interface{}
	type _ map[string]interface{}
	type _ chan interface{}
	type _ func() interface{}

	var _ struct{}
	var _ *struct{}
	var _ []struct{}
	var _ map[string]struct{}
	var _ chan struct{}
	var _ func() struct{}

	var _ interface{}
	var _ *interface{}
	var _ []interface{}
	var _ map[string]interface{}
	var _ chan interface{}
	var _ func() interface{}
}

// don't lose blank lines in grouped declarations
const (
	_	int	= 0
	_	float	= 1

	_	string	= "foo"

	_	= iota
	_

	// a comment
	_

	_
)

type (
	_	int
	_	struct{}

	_	interface{}

	// a comment
	_	map[string]int
)

var (
	_	int	= 0
	_	float	= 1

	_	string	= "foo"

	_	bool

	// a comment
	_	bool
)

// don't lose blank lines in this struct
type _ struct {
	String	struct {
		Str, Len int
	}
	Slice	struct {
		Array, Len, Cap int
	}
	Eface	struct {
		Typ, Ptr int
	}

	UncommonType	struct {
		Name, PkgPath int
	}
	CommonType	struct {
		Size, Hash, Alg, Align, FieldAlign, String, UncommonType int
	}
	Type	struct {
		Typ, Ptr int
	}
	StructField	struct {
		Name, PkgPath, Typ, Tag, Offset int
	}
	StructType	struct {
		Fields int
	}
	PtrType	struct {
		Elem int
	}
	SliceType	struct {
		Elem int
	}
	ArrayType	struct {
		Elem, Len int
	}

	Stktop	struct {
		Stackguard, Stackbase, Gobuf int
	}
	Gobuf	struct {
		Sp, Pc, G int
	}
	G	struct {
		Stackbase, Sched, Status, Alllink int
	}
}

// no blank lines in empty structs and interfaces, but leave 1- or 2-line layout alone
type _ struct{}
type _ struct {
}

type _ interface{}
type _ interface {
}

// no tabs for single or ungrouped decls
func _() {
	const xxxxxx = 0
	type x int
	var xxx int
	var yyyy float = 3.14
	var zzzzz = "bar"

	const (
		xxxxxx = 0
	)
	type (
		x int
	)
	var (
		xxx int
	)
	var (
		yyyy float = 3.14
	)
	var (
		zzzzz = "bar"
	)
}

// tabs for multiple or grouped decls
func _() {
	// no entry has a type
	const (
		zzzzzz	= 1
		z	= 2
		zzz	= 3
	)
	// some entries have a type
	const (
		xxxxxx			= 1
		x			= 2
		xxx			= 3
		yyyyyyyy	float	= iota
		yyyy			= "bar"
		yyy
		yy	= 2
	)
}

func _() {
	// no entry has a type
	var (
		zzzzzz	= 1
		z	= 2
		zzz	= 3
	)
	// no entry has a value
	var (
		_	int
		_	float
		_	string

		_	int	// comment
		_	float	// comment
		_	string	// comment
	)
	// some entries have a type
	var (
		xxxxxx		int
		x		float
		xxx		string
		yyyyyyyy	int	= 1234
		y		float	= 3.14
		yyyy			= "bar"
		yyy		string	= "foo"
	)
	// mixed entries - all comments should be aligned
	var (
		a, b, c			int
		x			= 10
		d			int			// comment
		y				= 20		// comment
		f, ff, fff, ffff	int	= 0, 1, 2, 3	// comment
	)
	// respect original line breaks
	var _ = []T{
		T{0x20, "Telugu"},
	}
	var _ = []T{
		// respect original line breaks
		T{0x20, "Telugu"},
	}
}

func _() {
	type (
		xxxxxx	int
		x	float
		xxx	string
		xxxxx	[]x
		xx	struct{}
		xxxxxxx	struct {
			_, _	int
			_	float
		}
		xxxx	chan<- string
	)
}

// alignment of "=" in consecutive lines (extended example from issue 1414)
const (
	umax	uint	= ^uint(0)		// maximum value for a uint
	bpu		= 1 << (5 + umax>>63)	// bits per uint
	foo
	bar	= -1
)

// typical enum
const (
	a	MyType	= iota
	abcd
	b
	c
	def
)

// excerpt from godoc.go
var (
	goroot		= flag.String("goroot", runtime.GOROOT(), "Go root directory")
	testDir		= flag.String("testdir", "", "Go root subdirectory - for testing only (faster startups)")
	pkgPath		= flag.String("path", "", "additional package directories (colon-separated)")
	filter		= flag.String("filter", "", "filter file containing permitted package directory paths")
	filterMin	= flag.Int("filter_minutes", 0, "filter file update interval in minutes; disabled if <= 0")
	filterDelay	delayTime	// actual filter update interval in minutes; usually filterDelay == filterMin, but filterDelay may back off exponentially
)

// formatting of structs
type _ struct{}

type _ struct { /* this comment should be visible */
}

type _ struct {
	// this comment should be visible and properly indented
}

type _ struct {	// this comment must not change indentation
	f			int
	f, ff, fff, ffff	int
}

type _ struct {
	string
}

type _ struct {
	string	// comment
}

type _ struct {
	string "tag"
}

type _ struct {
	string "tag"	// comment
}

type _ struct {
	f int
}

type _ struct {
	f int	// comment
}

type _ struct {
	f int "tag"
}

type _ struct {
	f int "tag"	// comment
}

type _ struct {
	bool
	a, b, c			int
	int			"tag"
	ES				// comment
	float			"tag"	// comment
	f			int	// comment
	f, ff, fff, ffff	int	// comment
	g			float	"tag"
	h			float	"tag"	// comment
}

type _ struct {
	a, b,
	c, d		int	// this line should be indented
	u, v, w, x	float	// this line should be indented
	p, q,
	r, s	float	// this line should be indented
}

// difficult cases
type _ struct {
	bool		// comment
	text	[]byte	// comment
}

// formatting of interfaces
type EI interface{}

type _ interface {
	EI
}

type _ interface {
	f()
	fffff()
}

type _ interface {
	EI
	f()
	fffffg()
}

type _ interface {	// this comment must not change indentation
	EI				// here's a comment
	f()				// no blank between identifier and ()
	fffff()				// no blank between identifier and ()
	gggggggggggg(x, y, z int)	// hurray
}

// formatting of variable declarations
func _() {
	type day struct {
		n		int
		short, long	string
	}
	var (
		Sunday		= day{0, "SUN", "Sunday"}
		Monday		= day{1, "MON", "Monday"}
		Tuesday		= day{2, "TUE", "Tuesday"}
		Wednesday	= day{3, "WED", "Wednesday"}
		Thursday	= day{4, "THU", "Thursday"}
		Friday		= day{5, "FRI", "Friday"}
		Saturday	= day{6, "SAT", "Saturday"}
	)
}

// formatting of multi-line variable declarations
var a1, b1, c1 int	// all on one line

var a2, b2,
	c2 int	// this line should be indented

var (
	a3, b3,
	c3, d3		int	// this line should be indented
	a4, b4, c4	int	// this line should be indented
)

func _() {
	var privateKey2 = &Block{Type:	"RSA PRIVATE KEY",
		Headers:	map[string]string{},
		Bytes: []uint8{0x30, 0x82, 0x1, 0x3a, 0x2, 0x1, 0x0, 0x2,
			0x41, 0x0, 0xb2, 0x99, 0xf, 0x49, 0xc4, 0x7d, 0xfa, 0x8c,
			0xd4, 0x0, 0xae, 0x6a, 0x4d, 0x1b, 0x8a, 0x3b, 0x6a, 0x13,
			0x64, 0x2b, 0x23, 0xf2, 0x8b, 0x0, 0x3b, 0xfb, 0x97, 0x79,
		},
	}
}

func _() {
	var Universe = Scope{
		Names: map[string]*Ident{
			// basic types
			"bool":		nil,
			"byte":		nil,
			"int8":		nil,
			"int16":	nil,
			"int32":	nil,
			"int64":	nil,
			"uint8":	nil,
			"uint16":	nil,
			"uint32":	nil,
			"uint64":	nil,
			"float32":	nil,
			"float64":	nil,
			"string":	nil,

			// convenience types
			"int":		nil,
			"uint":		nil,
			"uintptr":	nil,
			"float":	nil,

			// constants
			"false":	nil,
			"true":		nil,
			"iota":		nil,
			"nil":		nil,

			// functions
			"cap":		nil,
			"len":		nil,
			"new":		nil,
			"make":		nil,
			"panic":	nil,
			"panicln":	nil,
			"print":	nil,
			"println":	nil,
		},
	}
}

// alignment of map composite entries
var _ = map[int]int{
	// small key sizes: always align even if size ratios are large
	a:			a,
	abcdefghabcdefgh:	a,
	ab:			a,
	abc:			a,
	abcdefgabcdefg:		a,
	abcd:			a,
	abcde:			a,
	abcdef:			a,

	// mixed key sizes: align when key sizes change within accepted ratio
	abcdefgh:		a,
	abcdefghabcdefg:	a,
	abcdefghij:		a,
	abcdefghijabcdefghijabcdefghijabcdefghijabcdefghijabcdefghijabcdefghij:	a,	// outlier - do not align with previous line
	abcdefghijabcdefghijabcdefghijabcdefghijabcdefghijabcdefghij:		a,	// align with previous line

	ab:	a,	// do not align with previous line
	abcde:	a,	// align with previous line
}

func _() {
	var _ = T{
		a,	// must introduce trailing comma
	}
}

// formatting of function results
func _() func()				{}
func _() func(int)			{ return nil }
func _() func(int) int			{ return nil }
func _() func(int) func(int) func()	{ return nil }

// formatting of consecutive single-line functions
func _()	{}
func _()	{}
func _()	{}

func _()	{}	// an empty line before this function
func _()	{}
func _()	{}

func _()		{ f(1, 2, 3) }
func _(x int) int	{ y := x; return y + 1 }
func _() int		{ type T struct{}; var x T; return x }

// these must remain multi-line since they are multi-line in the source
func _() {
	f(1, 2, 3)
}
func _(x int) int {
	y := x
	return y + 1
}
func _() int {
	type T struct{}
	var x T
	return x
}

// making function declarations safe for new semicolon rules
func _() { /* multi-line func because of comment */
}

func _() {
	/* multi-line func because block is on multiple lines */
}

// ellipsis parameters
func _(...int)
func _(...*int)
func _(...[]int)
func _(...struct{})
func _(bool, ...interface{})
func _(bool, ...func())
func _(bool, ...func(...int))
func _(bool, ...map[string]int)
func _(bool, ...chan int)

func _(b bool, x ...int)
func _(b bool, x ...*int)
func _(b bool, x ...[]int)
func _(b bool, x ...struct{})
func _(x ...interface{})
func _(x ...func())
func _(x ...func(...int))
func _(x ...map[string]int)
func _(x ...chan int)

// these parameter lists must remain multi-line since they are multi-line in the source
func _(bool,
	int) {
}
func _(x bool,
	y int) {
}
func _(x,
	y bool) {
}
func _(bool,	// comment
	int) {
}
func _(x bool,	// comment
	y int) {
}
func _(x,	// comment
	y bool) {
}
func _(bool,	// comment
	// comment
	int) {
}
func _(x bool,	// comment
	// comment
	y int) {
}
func _(x,	// comment
	// comment
	y bool) {
}
func _(bool,
	// comment
	int) {
}
func _(x bool,
	// comment
	y int) {
}
func _(x,
	// comment
	y bool) {
}
func _(x,	// comment
	y,	// comment
	z bool) {
}
func _(x,	// comment
	y,	// comment
	z bool) {
}
func _(x int,	// comment
	y float,	// comment
	z bool) {
}

// properly indent multi-line signatures
func ManageStatus(in <-chan *Status, req <-chan Request,
	stat chan<- *TargetInfo,
	TargetHistorySize int) {
}

func MultiLineSignature0(
	a, b, c int,
) {
}

func MultiLineSignature1(
	a, b, c int,
	u, v, w float,
) {
}

func MultiLineSignature2(
	a, b,
	c int,
) {
}

func MultiLineSignature3(
	a, b,
	c int, u, v,
	w float,
	x ...int) {
}

func MultiLineSignature4(
	a, b, c int,
	u, v,
	w float,
	x ...int) {
}

func MultiLineSignature5(
	a, b, c int,
	u, v, w float,
	p, q,
	r string,
	x ...int) {
}

// make sure it also works for methods in interfaces
type _ interface {
	MultiLineSignature0(
		a, b, c int,
	)

	MultiLineSignature1(
		a, b, c int,
		u, v, w float,
	)

	MultiLineSignature2(
		a, b,
		c int,
	)

	MultiLineSignature3(
		a, b,
		c int, u, v,
		w float,
		x ...int)

	MultiLineSignature4(
		a, b, c int,
		u, v,
		w float,
		x ...int)

	MultiLineSignature5(
		a, b, c int,
		u, v, w float,
		p, q,
		r string,
		x ...int)
}
