cue-lang / cue

The home of the CUE language! Validate and define text-based and dynamic configuration
https://cuelang.org
Apache License 2.0
5.16k stars 297 forks source link

cue: FillPath breaks InlineImports #2301

Open verdverm opened 1 year ago

verdverm commented 1 year ago

The goal here is to programmaticly add a field to Value and then write it out with InlineImports.

What version of CUE are you using (cue version)?

0.5.0-beta.5

Does this issue reproduce with the latest stable release?

n/a ImportPaths is only in beta

What did you do?

exec go mod tidy
exec go run main.go
cmp stdout golden.stdout

-- main.go --
package main

import (
    "fmt"
    "os"

    "cuelang.org/go/cue"
    "cuelang.org/go/cue/cuecontext"
    "cuelang.org/go/cue/load"
    "cuelang.org/go/cue/format"
)

func checkErr(err error) {
    if err != nil {
        fmt.Println(err)
        os.Exit(1)
    }
}

func main() {

    // get value loaded up
    ctx := cuecontext.New()
    bis := load.Instances([]string{"input.cue"}, nil)
    val := ctx.BuildInstance(bis[0])

    // print without filling
    printVal(val)

    // fill a path
    val = val.FillPath(cue.ParsePath("MyModels.ID"), "abc123")

    // print after filling
    printVal(val)
}

func printVal(val cue.Value) {
    syn := val.Syntax(
        cue.InlineImports(true),
        cue.Docs(true),
        cue.Attributes(true),
        cue.Definitions(true),
        cue.Optional(true),
        cue.Hidden(true),
        cue.Concrete(false),
        cue.ResolveReferences(false),
    )

    src, err := format.Node(syn)
    checkErr(err)

    str := string(src)
    fmt.Println("==============")
    fmt.Println(str)
}

-- input.cue --
package main

import (
    "hof.io/dep"
)

MyModels: {
    Name: "MyModels"

    Models: [M=string]: dep.Model & { Name: M }
}

User: {
    Fields: {
        username: string
        email: string
    }
}

-- cue.mod/module.cue --
module: "hof.io/repro"

-- cue.mod/pkg/hof.io/dep/main.cue --
package dep

Model: {
    Name: string
    Fields: [string]: Field
}

Field: {
    Name: string
    Type: string
}

-- golden.stdout --
==============
package main

MyModels: {
    Name: "MyModels"
    Models: {
        [M=string]: MODEL & {
            Name: M
        }
    }
}
User: {
    Fields: {
        username: string
        email:    string
    }
}

//cue:path: "hof.io/dep".Model
let MODEL = {
    Name: string
    Fields: {
        [string]: {
            Name: string
            Type: string
        }
    }
}

==============
package main

MyModels: {
    Name: "MyModels"
    ID:   "abc123"
    Models: {
        [M=string]: MODEL & {
            Name: M
        }
    }
}
User: {
    Fields: {
        username: string
        email:    string
    }
}

//cue:path: "hof.io/dep".Model
let MODEL = {
    Name: string
    Fields: {
        [string]: {
            Name: string
            Type: string
        }
    }
}

-- go.mod --
module hof.io/repro

go 1.19

require cuelang.org/go v0.5.0-beta.5

What did you see instead?

> cmp stdout golden.stdout
--- stdout
+++ golden.stdout
@@ -28,13 +28,13 @@
 }

 ==============
-import "hof.io/dep"
+package main

 MyModels: {
        Name: "MyModels"
        ID:   "abc123"
        Models: {
-               [M=string]: dep.Model & {
+               [M=string]: MODEL & {
                        Name: M
                }
        }
@@ -46,3 +46,14 @@
        }
 }

+//cue:path: "hof.io/dep".Model
+let MODEL = {
+       Name: string
+       Fields: {
+               [string]: {
+                       Name: string
+                       Type: string
+               }
+       }
+}
+

FAIL: /tmp/testscript2700182166/repro.txt/script.txtar:3: stdout and golden.stdout differ

The full output looks like this, you can see the difference more clearly here

==============
package main

MyModels: {
    Name: "MyModels"
    Models: {
        [M=string]: MODEL & {
            Name: M
        }
    }
}
User: {
    Fields: {
        username: string
        email:    string
    }
}

//cue:path: "hof.io/dep".Model
let MODEL = {
    Name: string
    Fields: {
        [string]: {
            Name: string
            Type: string
        }
    }
}

==============
import "hof.io/dep"

MyModels: {
    Name: "MyModels"
    ID:   "abc123"
    Models: {
        [M=string]: dep.Model & {
            Name: M
        }
    }
}
User: {
    Fields: {
        username: string
        email:    string
    }
}
myitcv commented 1 year ago

Thanks for the report, @verdverm. Looks like a bug to me. Here is a simpler example which is a bit easier to understand:

What did you do?

go mod tidy
go run .
cmp stdout stdout.golden

-- cue.mod/module.cue --
module: "hof.io/repro"

-- cue.mod/pkg/hof.io/dep/main.cue --
package dep

Model: {
    Name: string
}
-- go.mod --
module hof.io/repro

go 1.19

require cuelang.org/go v0.5.0-beta.5
-- input.cue --
package main

import (
    "hof.io/dep"
)

MyModels: {
    Models: dep.Model
}
-- main.go --
package main

import (
    "fmt"

    "cuelang.org/go/cue"
    "cuelang.org/go/cue/cuecontext"
    "cuelang.org/go/cue/format"
    "cuelang.org/go/cue/load"
)

func main() {
    ctx := cuecontext.New()
    bis := load.Instances([]string{"input.cue"}, nil)
    val := ctx.BuildInstance(bis[0])

    formatVal := func() []byte {
        syn := val.Syntax(cue.InlineImports(true))
        src, err := format.Node(syn)
        if err != nil {
            panic(err)
        }
        return src
    }

    fmt.Printf("======== pre fill ==========\n%s\n", formatVal())
    val = val.FillPath(cue.ParsePath("MyModels.ID"), "abc123")
    fmt.Printf("======== post fill =========\n%s\n", formatVal())
}
-- stdout.golden --
======== pre fill ==========
package main

MyModels: {
    Models: {
        Name: string
    }
}

======== post fill =========
package main

MyModels: {
    Models: {
        Name: string
    }
    ID:     "abc123"
}

What did you expect to see?

Passing test

What did you see instead?

> go mod tidy
> go run .
[stdout]
======== pre fill ==========
package main

MyModels: {
        Models: {
                Name: string
        }
}

======== post fill =========
import "hof.io/dep"

MyModels: {
        Models: dep.Model
        ID:     "abc123"
}

> cmp stdout stdout.golden
--- stdout
+++ stdout.golden
@@ -8,10 +8,12 @@
 }

 ======== post fill =========
-import "hof.io/dep"
+package main

 MyModels: {
-       Models: dep.Model
+       Models: {
+               Name: string
+       }
        ID:     "abc123"
 }

FAIL: /tmp/testscript574378884/repro.txtar/script.txtar:3: stdout and stdout.golden differ
myitcv commented 1 year ago

Marking as v0.7.0 to prevent delaying v0.6.0, but @verdverm please say if this is a pressing issue.