// 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)
}
