encoding/jsonschema: use astutil.Sanitize to handle imports

Also prepares for Issue #378.

Change-Id: Ieff531fdf6d7bdfa1741c95e7ff87d31e39bf1a9
Reviewed-on: https://cue-review.googlesource.com/c/cue/+/6140
Reviewed-by: Marcel van Lohuizen <mpvl@golang.org>
diff --git a/encoding/jsonschema/decode.go b/encoding/jsonschema/decode.go
index f1c7f58..1e62b7a 100644
--- a/encoding/jsonschema/decode.go
+++ b/encoding/jsonschema/decode.go
@@ -21,11 +21,11 @@
 import (
 	"fmt"
 	"math/bits"
-	"sort"
 	"strings"
 
 	"cuelang.org/go/cue"
 	"cuelang.org/go/cue/ast"
+	"cuelang.org/go/cue/ast/astutil"
 	"cuelang.org/go/cue/errors"
 	"cuelang.org/go/cue/token"
 	"cuelang.org/go/internal"
@@ -41,19 +41,21 @@
 type decoder struct {
 	cfg *Config
 
-	errs    errors.Error
-	imports map[string]*ast.Ident
+	errs errors.Error
 
 	definitions []ast.Decl
 }
 
 // addImport registers
 func (d *decoder) addImport(pkg string) *ast.Ident {
-	ident, ok := d.imports[pkg]
-	if !ok {
-		ident = ast.NewIdent(pkg)
-		d.imports[pkg] = ident
+	spec := ast.NewImport(nil, pkg)
+	info, err := astutil.ParseImportSpec(spec)
+	if err != nil {
+		d.errf(cue.Value{}, "invalid import %q", pkg)
 	}
+	ident := ast.NewIdent(info.Ident)
+	ident.Node = spec
+
 	return ident
 }
 
@@ -90,23 +92,11 @@
 		}
 	}
 
-	var imports []string
-	for k := range d.imports {
-		imports = append(imports, k)
-	}
-	sort.Strings(imports)
-
-	if len(imports) > 0 {
-		x := &ast.ImportDecl{}
-		for _, p := range imports {
-			x.Specs = append(x.Specs, ast.NewImport(nil, p))
-		}
-		f.Decls = append(f.Decls, x)
-	}
-
 	f.Decls = append(f.Decls, a...)
 	f.Decls = append(f.Decls, d.definitions...)
 
+	_ = astutil.Sanitize(f)
+
 	return f
 }
 
diff --git a/encoding/jsonschema/jsonschema.go b/encoding/jsonschema/jsonschema.go
index 00027c6..9e81b73 100644
--- a/encoding/jsonschema/jsonschema.go
+++ b/encoding/jsonschema/jsonschema.go
@@ -41,10 +41,7 @@
 // The generated CUE schema is guaranteed to deem valid any value that is
 // a valid instance of the source JSON schema.
 func Extract(data *cue.Instance, cfg *Config) (f *ast.File, err error) {
-	d := &decoder{
-		cfg:     cfg,
-		imports: map[string]*ast.Ident{},
-	}
+	d := &decoder{cfg: cfg}
 
 	f = d.decode(data.Value())
 	if d.errs != nil {