encoding/openapi: support nested defintitions

This perpares for Protobuf remodeling, where the nested
definitions of protobufs are are also nested within the
corresponding CUE types.

- Use Dereference
- Get comments from definitions, not fields, if applicable
- Allow embedded closed disjunctions.
- Allow nested types.
- Don't expand array element references.

Note that this removes the simplification in the openapi.cue
test: nested closed structs were not handled correctly by
this optimization.

Change-Id: Ie6adf44b37ac72139e21539094df5a728a309bd1
Reviewed-on: https://cue-review.googlesource.com/c/cue/+/5405
Reviewed-by: Marcel van Lohuizen <mpvl@golang.org>
diff --git a/encoding/openapi/types.go b/encoding/openapi/types.go
index 3a82362..39f5c59 100644
--- a/encoding/openapi/types.go
+++ b/encoding/openapi/types.go
@@ -16,6 +16,7 @@
 
 import (
 	"fmt"
+	"strings"
 
 	"github.com/cockroachdb/apd/v2"
 
@@ -38,7 +39,6 @@
 	"bytes":  "binary",
 
 	"time.Time":                  "dateTime",
-	"time.Time ()":               "dateTime",
 	`time.Format ("2006-01-02")`: "date",
 
 	// TODO: if a format is more strict (e.g. using zeros instead of nines
@@ -54,11 +54,26 @@
 	default:
 		return ""
 	}
-	b, err := format.Node(v.Syntax(cue.Final()))
-	if err != nil {
-		return ""
+	var expr, arg string
+	op, a := v.Expr()
+	if op == cue.CallOp {
+		v = a[0]
+		if len(a) == 2 {
+			arg = fmt.Sprintf(" (%s)", a[1].Eval())
+		}
 	}
-	if s, ok := cueToOpenAPI[string(b)]; ok {
+	if inst, ref := v.Reference(); len(ref) > 0 {
+		expr = inst.ImportPath + "." + strings.Join(ref, ".")
+		expr += arg
+	} else {
+		// TODO: have some function to extract normalized builtin types.
+		b, err := format.Node(v.Syntax(cue.Final()))
+		if err != nil {
+			return ""
+		}
+		expr = string(b)
+	}
+	if s, ok := cueToOpenAPI[expr]; ok {
 		return s
 	}
 	s := fmt.Sprint(v)