encoding/openapi: fix title handling regression

This regression was a result of forgetting to unskip the
def_openapi test in the move to v0.3, which allowed the
regression to be introduced by 304a3e0e to go unnoticed.

This partially unwinds 304a3e0e: it still assumes the main
operation is based on Value, but if available, it also stores
the Instance so that its meta information can be extracted.

In principle all information available in the Instance is also
available in the auxiliary structures of the Value (conjuncts).
But for now this is an easier approach.

The tests have a few changes as a result. The updated meta
data is correct. Furthermore there are additional file comments
at the top. It is debatable whether the latter is desirable or not,
but we'll leave it for now, as it is the current behavior.

Change-Id: Iaf40a9e525ff582e24ab4bc9fe690a40fa146559
Reviewed-on: https://cue-review.googlesource.com/c/cue/+/9066
Reviewed-by: CUE cueckoo <cueckoo@gmail.com>
Reviewed-by: Paul Jolly <paul@myitcv.org.uk>
diff --git a/cmd/cue/cmd/common.go b/cmd/cue/cmd/common.go
index cbe713e..1b51472 100644
--- a/cmd/cue/cmd/common.go
+++ b/cmd/cue/cmd/common.go
@@ -169,7 +169,8 @@
 type iterator interface {
 	scan() bool
 	value() cue.Value
-	file() *ast.File // may return nil
+	instance() *cue.Instance // may return nil
+	file() *ast.File         // may return nil
 	err() error
 	close()
 	id() string
@@ -186,11 +187,12 @@
 	return i.i < len(i.a) && i.e == nil
 }
 
-func (i *instanceIterator) close()           {}
-func (i *instanceIterator) err() error       { return i.e }
-func (i *instanceIterator) value() cue.Value { return i.a[i.i].Value() }
-func (i *instanceIterator) file() *ast.File  { return nil }
-func (i *instanceIterator) id() string       { return i.a[i.i].Dir }
+func (i *instanceIterator) close()                  {}
+func (i *instanceIterator) err() error              { return i.e }
+func (i *instanceIterator) value() cue.Value        { return i.a[i.i].Value() }
+func (i *instanceIterator) instance() *cue.Instance { return i.a[i.i] }
+func (i *instanceIterator) file() *ast.File         { return nil }
+func (i *instanceIterator) id() string              { return i.a[i.i].Dir }
 
 type streamingIterator struct {
 	r    *cue.Runtime
@@ -239,8 +241,9 @@
 	return i
 }
 
-func (i *streamingIterator) file() *ast.File  { return i.f }
-func (i *streamingIterator) value() cue.Value { return i.v }
+func (i *streamingIterator) file() *ast.File         { return i.f }
+func (i *streamingIterator) value() cue.Value        { return i.v }
+func (i *streamingIterator) instance() *cue.Instance { return nil }
 
 func (i *streamingIterator) id() string {
 	if i.inst != nil {
@@ -333,7 +336,8 @@
 	return true
 }
 
-func (i *expressionIter) file() *ast.File { return nil }
+func (i *expressionIter) file() *ast.File         { return nil }
+func (i *expressionIter) instance() *cue.Instance { return nil }
 
 func (i *expressionIter) value() cue.Value {
 	if len(i.expr) == 0 {
diff --git a/cmd/cue/cmd/def.go b/cmd/cue/cmd/def.go
index edba0e6..5b7040d 100644
--- a/cmd/cue/cmd/def.go
+++ b/cmd/cue/cmd/def.go
@@ -60,13 +60,15 @@
 	iter := b.instances()
 	defer iter.close()
 	for i := 0; iter.scan(); i++ {
+		var err error
 		if f := iter.file(); f != nil {
-			err := e.EncodeFile(f)
-			exitOnErr(cmd, err, true)
+			err = e.EncodeFile(f)
+		} else if i := iter.instance(); i != nil {
+			err = e.EncodeInstance(iter.instance())
 		} else {
-			err := e.Encode(iter.value())
-			exitOnErr(cmd, err, true)
+			err = e.Encode(iter.value())
 		}
+		exitOnErr(cmd, err, true)
 	}
 	exitOnErr(cmd, iter.err(), true)
 	return nil
diff --git a/cmd/cue/cmd/testdata/script/def_openapi.txt b/cmd/cue/cmd/testdata/script/def_openapi.txt
index d56adf5..1cf3ab7 100644
--- a/cmd/cue/cmd/testdata/script/def_openapi.txt
+++ b/cmd/cue/cmd/testdata/script/def_openapi.txt
@@ -1,5 +1,3 @@
-skip 'fix comments and value printing'
-
 cue def openapi+cue: expect-cue-out -o -
 
 cue def foo.cue -o openapi:-
@@ -255,11 +253,14 @@
 }
 -- expect-cue3 --
 // My OpenAPI
+
+// My OpenAPI2
 package foo
 
 info: {
-	title:   string | *_|_
-	version: *"v1alpha1" | string}
+	title:   (*"My OpenAPI" | string) & (*"My OpenAPI2" | string)
+	version: (*"v1alpha1" | string) & (*"v1alpha1" | string)
+}
 #Bar: {
 	foo: #Foo
 	...
diff --git a/internal/encoding/encoder.go b/internal/encoding/encoder.go
index 764d482..40db53f 100644
--- a/internal/encoding/encoder.go
+++ b/internal/encoding/encoder.go
@@ -45,6 +45,7 @@
 	encValue     func(cue.Value) error
 	autoSimplify bool
 	concrete     bool
+	instance     *cue.Instance
 }
 
 // IsConcrete reports whether the output is required to be concrete.
@@ -80,7 +81,10 @@
 		// TODO: get encoding options
 		cfg := &openapi.Config{}
 		e.interpret = func(v cue.Value) (*ast.File, error) {
-			i := internal.MakeInstance(v).(*cue.Instance)
+			i := e.instance
+			if i == nil {
+				i = internal.MakeInstance(v).(*cue.Instance)
+			}
 			return openapi.Generate(i, cfg)
 		}
 	// case build.JSONSchema:
@@ -205,6 +209,15 @@
 	return e.encodeFile(f, e.interpret)
 }
 
+// EncodeInstance is as Encode, but stores instance information. This should
+// all be retrievable from the value itself.
+func (e *Encoder) EncodeInstance(v *cue.Instance) error {
+	e.instance = v
+	err := e.Encode(v.Value())
+	e.instance = nil
+	return err
+}
+
 func (e *Encoder) Encode(v cue.Value) error {
 	e.autoSimplify = true
 	if e.interpret != nil {