# Test that a get go works for various "interesting" types,
# including those special cases that result in _ and string
# that are specifically mentioned in help get go.
#
# This test does not exercise with/without --local. Instead
# that is left for other tests, so that this test can focus
# on the various rules of get go.

# cue get go
cue get go --local ./...
cmp ./pkg3/pkg3_go_gen.cue ./pkg3/pkg3_go_gen.cue.golden
cmp ./pkg1/file1_go_gen.cue ./pkg1/file1_go_gen.cue.golden
cmp ./pkg1/alias_go_gen.cue ./pkg1/alias_go_gen.cue.golden
cmp ./pkg2/pkg2_go_gen.cue ./pkg2/pkg2_go_gen.cue.golden

# Verify dependencies did not change
cmp go.mod go.mod.golden

-- go.mod --
module example.com

go 1.14
-- go.mod.golden --
module example.com

go 1.14
-- cue.mod --
module: "example.com"
-- pkg1/alias.go --
package pkg1

import p3 "example.com/pkg3"

type MyBarzer = p3.Barzer
-- pkg1/file1.go --
/*
  block comment
*/
package pkg1

import (
	"encoding"
	"encoding/json"
	"time"

	p2 "example.com/pkg2"
)

// Foozer foozes a jaman.
type Foozer struct {
	Int    int
	String string

	Inline `json:",inline"`
	NoInline

	CustomJSON CustomJSON
	CustomYAML *CustomYAML
	AnyJSON    json.Marshaler
	AnyText    encoding.TextMarshaler

	Bar int `json:"bar,omitempty" cue:">10"`

	exclude int

	// Time is mapped to CUE's internal type.
	Time time.Time

	Barzer p2.Barzer

	Alias1 *MyBarzer

	Map    map[string]*CustomJSON
	Slice1 []int
	Slice2 []interface{}
	Slice3 *[]json.Unmarshaler
	Array1 [5]int
	Array2 [5]interface{}
	Array3 *[5]json.Marshaler

	Intf  Interface `protobuf:"varint,2,name=intf"`
	Intf2 interface{}
	Intf3 struct{ Interface }
	Intf4 interface{ Foo() }

	// Even though this struct as a type implements MarshalJSON, it is known
	// that it is really only implemented by the embedded field.
	Embed struct{ CustomJSON }

	Unsupported map[int]string
}

type Identifier string

const (
	internalIdentifier Identifier = "internal"
)

const _ = true

// appease linter
var _ = internalIdentifier

// Level gives an indication of the extent of stuff.
type Level int

const (
	/*
	  Block comment.
	   Indented.

	  Empty line before.
	*/
	Unknown Level = iota
	Low
	// Medium is neither High nor Low
	Medium
	High
)

type CustomJSON struct {
}

func (c *CustomJSON) MarshalJSON() ([]byte, error) {
	return nil, nil
}

type CustomYAML struct {
}

func (c CustomYAML) MarshalYAML() ([]byte, error) {
	return nil, nil
}

type localType int

const (
	localConst localType = 1

	_ = localConst // silence linter
)

type Inline struct {
	Kind string
}

type NoInline struct {
	Kind string
}

type Interface interface {
	Boomer() bool
}
-- pkg2/add.cue --
package pkgtwo

Barzer: {
	S: =~"cat$"
}
-- pkg2/pkg2.go --
// Package pkgtwo does other stuff.
package pkgtwo

import (
	"math/big"
	t "time"
)

// A Barzer barzes.
type Barzer struct {
	A int `protobuf:"varint,2," json:"a"`

	T t.Time
	B *big.Int
	C big.Int
	F big.Float `xml:",attr"`
	G *big.Float
	H bool `json:"-"`
	S string

	XY bool `json:"x-y"`

	Err error

	*Inline `json:",inline"`
}

const Perm = 0755

const Few = 3

const Couple int = 2

// LongStringConst ensures that we are using go/constant
// correctly for the exact value of a constant as opposed
// to a shortened version (relevant for strings)
const LongStringConst = "This is a really long string. Why are we using a long string? Because that way it ensures we are using go/constant.Value.ExactString() instead of go/constant.Value.String()"

type Inline struct{ A int }
-- pkg3/pkg3.go --
package pkg3

import pkgtwo "example.com/pkg2"

type Barzer = pkgtwo.Barzer
-- pkg1/alias_go_gen.cue --
// Code generated by cue get go. DO NOT EDIT.

//cue:generate cue get go example.com/pkg1

package pkg1

import "example.com/pkg2"

#MyBarzer: pkgtwo.#Barzer
-- pkg1/file1_go_gen.cue --
// Code generated by cue get go. DO NOT EDIT.

//cue:generate cue get go example.com/pkg1

// block comment
package pkg1

import (
 "time"
 p2 "example.com/pkg2:pkgtwo"
)

// Foozer foozes a jaman.
#Foozer: {
 Int:    int
 String: string

 #Inline
 NoInline:    #NoInline
 CustomJSON:  #CustomJSON
 CustomYAML?: null | #CustomYAML @go(,*CustomYAML)
 AnyJSON:     _                  @go(,json.Marshaler)
 AnyText:     string             @go(,encoding.TextMarshaler)
 bar?:        int & >10          @go(Bar)

 // Time is mapped to CUE's internal type.
 Time:    time.Time
 Barzer:  p2.#Barzer
 Alias1?: null | p2.#Barzer @go(,*p2.Barzer)
 Map: {[string]: null | #CustomJSON} @go(,map[string]*CustomJSON)
 Slice1: [...int] @go(,[]int)
 Slice2: [...] @go(,[]interface{})
 Slice3?: null | [...] @go(,*[]json.Unmarshaler)
 Array1:  5 * [int]    @go(,[5]int)
 Array2:  5 * [_]      @go(,[5]interface{})
 Array3?: null | 5*[_] @go(,*[5]json.Marshaler)
 Intf:    #Interface   @protobuf(2,varint,name=intf)
 Intf2:   _            @go(,interface{})
 Intf3: {
  Interface: #Interface
 } @go(,struct{Interface})
 Intf4: _ @go(,"interface{Foo()}")

 // Even though this struct as a type implements MarshalJSON, it is known
 // that it is really only implemented by the embedded field.
 Embed: {
  CustomJSON: #CustomJSON
 } @go(,struct{CustomJSON})
}

#Identifier: string // #enumIdentifier

#enumIdentifier:
 _#internalIdentifier

_#internalIdentifier: #Identifier & "internal"

// Level gives an indication of the extent of stuff.
#Level: int // #enumLevel

#enumLevel:
 #Unknown |
 #Low |
 #Medium |
 #High

// Block comment.
//  Indented.
//
// Empty line before.
#Unknown: #Level & 0
#Low:     #Level & 1

// Medium is neither High nor Low
#Medium: #Level & 2
#High:   #Level & 3

#CustomJSON: _

#CustomYAML: {
}

_#localType: int

_#localConst: _#localType & 1

#Inline: Kind: string

#NoInline: Kind: string

#Interface: _
-- pkg2/pkg2_go_gen.cue --
// Code generated by cue get go. DO NOT EDIT.

//cue:generate cue get go example.com/pkg2

// Package pkgtwo does other stuff.
package pkgtwo

import t "time"

// A Barzer barzes.
#Barzer: {
 a:     int @go(A) @protobuf(2,varint,)
 T:     t.Time
 B?:    null | int    @go(,*big.Int)
 C:     int           @go(,big.Int)
 F:     string        @go(,big.Float) @xml(,attr)
 G?:    null | string @go(,*big.Float)
 S:     string
 "x-y": bool @go(XY)
 Err:   _    @go(,error)

 #Inline
}

#Perm: 0o755

#Few: 3

#Couple: int & 2

#Inline: A: int
-- pkg3/pkg3_go_gen.cue --
// Code generated by cue get go. DO NOT EDIT.

//cue:generate cue get go example.com/pkg3

package pkg3

import "example.com/pkg2:pkgtwo"

#Barzer: pkgtwo.#Barzer

-- pkg1/alias_go_gen.cue.golden --
// Code generated by cue get go. DO NOT EDIT.

//cue:generate cue get go example.com/pkg1

package pkg1

import "example.com/pkg2"

#MyBarzer: pkgtwo.#Barzer
-- pkg1/file1_go_gen.cue.golden --
// Code generated by cue get go. DO NOT EDIT.

//cue:generate cue get go example.com/pkg1

// block comment
package pkg1

import (
	"time"
	p2 "example.com/pkg2:pkgtwo"
)

// Foozer foozes a jaman.
#Foozer: {
	Int:    int
	String: string

	#Inline
	NoInline:    #NoInline
	CustomJSON:  #CustomJSON
	CustomYAML?: null | #CustomYAML @go(,*CustomYAML)
	AnyJSON:     _                  @go(,json.Marshaler)
	AnyText:     string             @go(,encoding.TextMarshaler)
	bar?:        int & >10          @go(Bar)

	// Time is mapped to CUE's internal type.
	Time:    time.Time
	Barzer:  p2.#Barzer
	Alias1?: null | p2.#Barzer @go(,*p2.Barzer)
	Map: {[string]: null | #CustomJSON} @go(,map[string]*CustomJSON)
	Slice1: [...int] @go(,[]int)
	Slice2: [...] @go(,[]interface{})
	Slice3?: null | [...] @go(,*[]json.Unmarshaler)
	Array1:  5 * [int]    @go(,[5]int)
	Array2:  5 * [_]      @go(,[5]interface{})
	Array3?: null | 5*[_] @go(,*[5]json.Marshaler)
	Intf:    #Interface   @protobuf(2,varint,name=intf)
	Intf2:   _            @go(,interface{})
	Intf3: {
		Interface: #Interface
	} @go(,struct{Interface})
	Intf4: _ @go(,"interface{Foo()}")

	// Even though this struct as a type implements MarshalJSON, it is known
	// that it is really only implemented by the embedded field.
	Embed: {
		CustomJSON: #CustomJSON
	} @go(,struct{CustomJSON})
}

#Identifier: string // #enumIdentifier

#enumIdentifier:
	_#internalIdentifier

_#internalIdentifier: #Identifier & "internal"

// Level gives an indication of the extent of stuff.
#Level: int // #enumLevel

#enumLevel:
	#Unknown |
	#Low |
	#Medium |
	#High

// Block comment.
//  Indented.
//
// Empty line before.
#Unknown: #Level & 0
#Low:     #Level & 1

// Medium is neither High nor Low
#Medium: #Level & 2
#High:   #Level & 3

#CustomJSON: _

#CustomYAML: {
}

_#localType: int

_#localConst: _#localType & 1

#Inline: Kind: string

#NoInline: Kind: string

#Interface: _
-- pkg2/add_gen.cue.golden --
// Code generated by cue get go. DO NOT EDIT.

//cue:generate cue get go example.com/pkg2

// Copyright 2019 CUE Authors
//
// Licensed under the Apache License, Version 2.0 (the "License");
// you may not use this file except in compliance with the License.
// You may obtain a copy of the License at
//
//     http://www.apache.org/licenses/LICENSE-2.0
//
// Unless required by applicable law or agreed to in writing, software
// distributed under the License is distributed on an "AS IS" BASIS,
// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
// See the License for the specific language governing permissions and
// limitations under the License.

package pkgtwo

Barzer: {
 S: =~"cat$"
}
-- pkg2/pkg2_go_gen.cue.golden --
// Code generated by cue get go. DO NOT EDIT.

//cue:generate cue get go example.com/pkg2

// Package pkgtwo does other stuff.
package pkgtwo

import t "time"

// A Barzer barzes.
#Barzer: {
	a:     int @go(A) @protobuf(2,varint,)
	T:     t.Time
	B?:    null | int    @go(,*big.Int)
	C:     int           @go(,big.Int)
	F:     string        @go(,big.Float) @xml(,attr)
	G?:    null | string @go(,*big.Float)
	S:     string
	"x-y": bool @go(XY)
	Err:   _    @go(,error)

	#Inline
}

#Perm: 0o755

#Few: 3

#Couple: int & 2

#LongStringConst: "This is a really long string. Why are we using a long string? Because that way it ensures we are using go/constant.Value.ExactString() instead of go/constant.Value.String()"

#Inline: A: int
-- pkg3/pkg3_go_gen.cue.golden --
// Code generated by cue get go. DO NOT EDIT.

//cue:generate cue get go example.com/pkg3

package pkg3

import "example.com/pkg2:pkgtwo"

#Barzer: pkgtwo.#Barzer
