encoding/openapi: add Info and DescriptorFunc features

Two settings added to Generator:

- Info adds the OpenAPI info section.
- DescriptorFunc allows for custom descriptions, given
  a value.

If the All API is used, an empty info section will be added
if the user hasn't given any. This is to reflect the fact
that info.version and info.title are required.

Issue #56

Change-Id: Ief29b40bf6be9c8026052588f6de9fb06d41095f
Reviewed-on: https://cue-review.googlesource.com/c/cue/+/2442
Reviewed-by: Marcel van Lohuizen <mpvl@golang.org>
diff --git a/encoding/openapi/build.go b/encoding/openapi/build.go
index 6b83e78..8224a71 100644
--- a/encoding/openapi/build.go
+++ b/encoding/openapi/build.go
@@ -35,6 +35,7 @@
 
 	expandRefs bool
 	nameFunc   func(inst *cue.Instance, path []string) string
+	descFunc   func(v cue.Value) string
 
 	schemas *OrderedMap
 
@@ -59,6 +60,7 @@
 		refPrefix:    "components/schema",
 		expandRefs:   g.ExpandReferences,
 		nameFunc:     g.ReferenceFunc,
+		descFunc:     g.DescriptionFunc,
 		schemas:      &OrderedMap{},
 		externalRefs: map[string]*externalType{},
 	}
@@ -148,11 +150,17 @@
 
 	if !isRef {
 		doc := []string{}
-		for _, d := range v.Doc() {
-			doc = append(doc, d.Text())
+		if b.ctx.descFunc != nil {
+			if str := b.ctx.descFunc(v); str != "" {
+				doc = append(doc, str)
+			}
+		} else {
+			for _, d := range v.Doc() {
+				doc = append(doc, d.Text())
+			}
 		}
 		if len(doc) > 0 {
-			str := strings.TrimSpace(strings.Join(doc, "\n"))
+			str := strings.TrimSpace(strings.Join(doc, "\n\n"))
 			schema.prepend("description", str)
 		}
 	}