
#exp:aliasv2
#no-coverage

-- cue.mod/module.cue --
module: "test.example"

language: version: "v0.15.0"

-- a.cue --
package foo

// Simple field alias
X=a: {
	foo: 1
	bar: X.foo + 2 @test(eq, 3)
}

// Multiple aliases
Y=b: {
	data: 42
}
Z=c: {
	val: Y.data @test(eq, 42)
}
zref: Z.val @test(eq, 42)
-- b.cue --
package foo

// Nested aliases
outer: {
	Inner=middle: {
		Leaf=deep: {
			value: 1
		}
		ref: Leaf.value @test(eq, 1)
	}
	ref2: Inner.deep.value @test(eq, 1)
}
-- c.cue --
package foo

// With constraints
OptField=a?: {
	value: 1
}
optRef: OptField.value

ReqField=b!: {
	value: 2
}
reqRef: ReqField.value
-- d.cue --
// Already has postfix alias experiment, so do not do any changes.
@experiment(aliasv2)

package foo

a~X: {
	foo: 1
}
ref: X.foo
-- e.cue --
package foo

// Pattern constraints with old alias syntax
// Note: Old syntax does not support pattern constraint aliases
// This is just testing that regular fields work correctly
schema: {
	[Name=string]: {
		name: Name
	}
	Y=[Name=string]: {
		name: Name
		value: Y.name
	}
}
-- f.cue --
package foo

x:    "key"
name: "dyn"

// Dynamic fields with old alias syntax
DynAlias=(x): {
	field: 1
	ref: DynAlias.field
}

// Dynamic field with string literal
StrAlias=("foo"): {
	data: 2
	ref: StrAlias.data
}

// Dynamic field with interpolation
DynInterpAlias=("\(name)"): {
	val: 3
	ref: InterpAlias.val
}
dynRef: DynInterpAlias.val
// Just the interpolation
InterpAlias="\(name)": {
	val: 3
	ref: InterpAlias.val
}
-- g.cue --
package foo

// Value aliases - old syntax X={...}
// Should convert to let with self
valAlias: X={
	x: X.a @test(eq, 1)
	y: X.b @test(eq, 2)
	a: 1
	b: 2
}

computed: Y={
	data: Y.x + 10 @test(eq, 15)
	x: 5
}

// Nested value alias
nested: {
	inner: Z={
		value: Z.n * 2 @test(eq, 6)
		n: 3
	}
}

// Multiple fields with value aliases
multi: {
	first: A={
		val: A.base * 2 @test(eq, 20)
		base: 10
	}
	second: B={
		val: B.base * 3 @test(eq, 60)
		base: 20
	}
}
-- h.cue --
package foo

// Test value alias conversion when "self" is already in scope,
// such as via a field, let clause, or alias named "self".
// The generated "let X = self" may bind to the wrong "self"
// unless "__self" is used to refer to the builtin.

// Field named self in same struct
samestruct: X={
	i:    X.self @test(eq, 42)
	self: 42
}

// Field named self in enclosing struct
enclosingfield: {
	self: 42
	inner: X={
		i: X.a @test(eq, 1)
		a: 1
	}
}

// Let self in enclosing struct
enclosinglet: {
	let self = {z: 99}
	inner: X={
		i: X.a @test(eq, 1)
		a: 1
		j: self.z @test(eq, 99)
	}
}

// Field alias named self at same scope
aliassamescope: {
	self=bar: {
		data: 1
	}
	baz: self.data @test(eq, 1)
	valAlias: X={
		i: X.a @test(eq, 1)
		a: 1
	}
}

// Field alias named self in enclosing struct
aliasenclosing: {
	self=bar: {
		data: 1
	}
	baz: self.data @test(eq, 1)
	inner: {
		valAlias: X={
			i: X.a @test(eq, 1)
			a: 1
		}
	}
}
-- out/fixmod --
--- cue.mod/module.cue
module: "test.example"
language: {
	version: "v0.15.0"
}
--- a.cue
@experiment(aliasv2)

package foo

// Simple field alias
a~(X): {
	foo: 1
	bar: X.foo + 2 @test(eq, 3)
}

// Multiple aliases
b~(Y): {
	data: 42
}
c~(Z): {
	val: Y.data @test(eq, 42)
}
zref: Z.val @test(eq, 42)
--- b.cue
@experiment(aliasv2)

package foo

// Nested aliases
outer: {
	middle~(Inner): {
		deep~(Leaf): {
			value: 1
		}
		ref: Leaf.value @test(eq, 1)
	}
	ref2: Inner.deep.value @test(eq, 1)
}
--- c.cue
@experiment(aliasv2)

package foo

// With constraints
a~(OptField)?: {
	value: 1
}
optRef: OptField.value
b~(ReqField)!: {
	value: 2
}
reqRef: ReqField.value
--- d.cue
// Already has postfix alias experiment, so do not do any changes.
@experiment(aliasv2)

package foo

a~(X): {
	foo: 1
}
ref: X.foo
--- e.cue
@experiment(aliasv2)

package foo

// Pattern constraints with old alias syntax
// Note: Old syntax does not support pattern constraint aliases
// This is just testing that regular fields work correctly
schema: {
	[string]~(Name,_): {
		name: Name
	}
	[string]~(Name,Y): {
		name:  Name
		value: Y.name
	}
}
--- f.cue
@experiment(aliasv2)

package foo

x:    "key"
name: "dyn"

// Dynamic fields with old alias syntax
(x)~(DynAlias): {
	field: 1
	ref:   DynAlias.field
}

// Dynamic field with string literal
("foo")~(StrAlias): {
	data: 2
	ref:  StrAlias.data
}

// Dynamic field with interpolation
("\(name)")~(DynInterpAlias): {
	val: 3
	ref: InterpAlias.val
}
dynRef: DynInterpAlias.val
// Just the interpolation
"\(name)"~(InterpAlias): {
	val: 3
	ref: InterpAlias.val
}
--- g.cue
@experiment(aliasv2)

package foo

// Value aliases - old syntax X={...}
// Should convert to let with self
valAlias: {
	let X = self
	x: X.a @test(eq, 1)
	y: X.b @test(eq, 2)
	a: 1
	b: 2
}

computed: {
	let Y = self
	data: Y.x + 10 @test(eq, 15)
	x:    5
}

// Nested value alias
nested: {
	inner: {
		let Z = self
		value: Z.n * 2 @test(eq, 6)
		n:     3
	}
}

// Multiple fields with value aliases
multi: {
	first: {
		let A = self
		val:  A.base * 2 @test(eq, 20)
		base: 10
	}
	second: {
		let B = self
		val:  B.base * 3 @test(eq, 60)
		base: 20
	}
}
--- h.cue
@experiment(aliasv2)

package foo

// Test value alias conversion when "self" is already in scope,
// such as via a field, let clause, or alias named "self".
// The generated "let X = self" may bind to the wrong "self"
// unless "__self" is used to refer to the builtin.

// Field named self in same struct
samestruct: {
	let X = __self
	i:    X.self @test(eq, 42)
	self: 42
}

// Field named self in enclosing struct
enclosingfield: {
	self: 42
	inner: {
		let X = __self
		i: X.a @test(eq, 1)
		a: 1
	}
}

// Let self in enclosing struct
enclosinglet: {
	let self = {z: 99}
	inner: {
		let X = __self
		i: X.a @test(eq, 1)
		a: 1
		j: self.z @test(eq, 99)
	}
}

// Field alias named self at same scope
aliassamescope: {
	bar~(self): {
		data: 1
	}
	baz: self.data @test(eq, 1)
	valAlias: {
		let X = __self
		i: X.a @test(eq, 1)
		a: 1
	}
}

// Field alias named self in enclosing struct
aliasenclosing: {
	bar~(self): {
		data: 1
	}
	baz: self.data @test(eq, 1)
	inner: {
		valAlias: {
			let X = __self
			i: X.a @test(eq, 1)
			a: 1
		}
	}
}
