cmd/cue/cmd: fix import paths for go get

Correctly look up the package path.

Also: escape identifiers if needed.

Fixes #115

Change-Id: I0dd0afbd51e68b9a021e84c08d762be87ebbee6b
Reviewed-on: https://cue-review.googlesource.com/c/cue/+/3342
Reviewed-by: Marcel van Lohuizen <mpvl@golang.org>
diff --git a/cmd/cue/cmd/get_go.go b/cmd/cue/cmd/get_go.go
index 437a8e8..7414e63 100644
--- a/cmd/cue/cmd/get_go.go
+++ b/cmd/cue/cmd/get_go.go
@@ -31,6 +31,7 @@
 	"strconv"
 	"strings"
 
+	cueast "cuelang.org/go/cue/ast"
 	"cuelang.org/go/cue/format"
 	"cuelang.org/go/cue/parser"
 	cuetoken "cuelang.org/go/cue/token"
@@ -253,7 +254,7 @@
 	cmap       ast.CommentMap
 	pkg        *packages.Package
 	consts     map[string][]string
-	pkgNames   map[string]string
+	pkgNames   map[string]pkgInfo
 	usedInFile map[string]bool
 	indent     int
 
@@ -261,6 +262,11 @@
 	exclude    string
 }
 
+type pkgInfo struct {
+	id   string
+	name string
+}
+
 func (e *extractor) logf(format string, args ...interface{}) {
 	if flagVerbose.Bool(e.cmd) {
 		fmt.Fprintf(e.stderr, format+"\n", args...)
@@ -405,17 +411,23 @@
 
 		e.cmap = ast.NewCommentMap(p.Fset, f, f.Comments)
 
-		e.pkgNames = map[string]string{}
+		e.pkgNames = map[string]pkgInfo{}
 		e.usedInFile = map[string]bool{}
 
 		for _, spec := range f.Imports {
-			key, _ := strconv.Unquote(spec.Path.Value)
-			if spec.Name != nil {
-				e.pkgNames[key] = spec.Name.Name
-			} else {
-				// TODO: incorrect, should be name of package clause
-				e.pkgNames[key] = path.Base(key)
+			pkgPath, _ := strconv.Unquote(spec.Path.Value)
+			pkg := p.Imports[pkgPath]
+
+			info := pkgInfo{id: pkgPath, name: pkg.Name}
+			if path.Base(pkgPath) != pkg.Name {
+				info.id += ":" + pkg.Name
 			}
+
+			if spec.Name != nil {
+				info.name = spec.Name.Name
+			}
+
+			e.pkgNames[pkgPath] = info
 		}
 
 		hasEntries := false
@@ -454,11 +466,11 @@
 		if len(pkgs) > 0 {
 			fmt.Fprintln(w, "import (")
 			for _, s := range pkgs {
-				name := e.pkgNames[s]
-				if p.Imports[s].Name == name {
-					fmt.Fprintf(w, "%q\n", s)
+				info := e.pkgNames[s]
+				if p.Imports[s].Name == info.name {
+					fmt.Fprintf(w, "%q\n", info.id)
 				} else {
-					fmt.Fprintf(w, "%v %q\n", name, s)
+					fmt.Fprintf(w, "%v %q\n", info.name, info.id)
 				}
 			}
 			fmt.Fprintln(w, ")")
@@ -828,7 +840,7 @@
 		switch obj.Type().String() {
 		case "time.Time":
 			e.usedInFile["time"] = true
-			fmt.Fprint(e.w, e.pkgNames[obj.Pkg().Path()], ".", obj.Name())
+			fmt.Fprint(e.w, e.pkgNames[obj.Pkg().Path()].name, ".", obj.Name())
 			return
 
 		case "math/big.Int":
@@ -846,8 +858,8 @@
 			}
 		}
 		if pkg := obj.Pkg(); pkg != nil {
-			if name := e.pkgNames[pkg.Path()]; name != "" {
-				fmt.Fprint(e.w, name, ".")
+			if info := e.pkgNames[pkg.Path()]; info.name != "" {
+				fmt.Fprint(e.w, info.name, ".")
 				e.usedPkg(pkg.Path())
 			}
 		}
@@ -962,6 +974,9 @@
 		if name == "-" {
 			continue
 		}
+		if x, _ := cueast.QuoteIdent(name); x != name {
+			name = strconv.Quote(name)
+		}
 		e.newLine()
 		kind := cuetoken.COLON
 		if e.isOptional(tag) {
@@ -972,8 +987,8 @@
 		// Add field tag to convert back to Go.
 		typeName := f.Type().String()
 		// simplify type names:
-		for path, name := range e.pkgNames {
-			typeName = strings.Replace(typeName, path+".", name+".", -1)
+		for path, info := range e.pkgNames {
+			typeName = strings.Replace(typeName, path+".", info.name+".", -1)
 		}
 		typeName = strings.Replace(typeName, e.pkg.Types.Path()+".", "", -1)
 
diff --git a/cmd/cue/cmd/testdata/code/go/pkg2/add.cue b/cmd/cue/cmd/testdata/code/go/pkg2/add.cue
index e1721e8..1c60023 100644
--- a/cmd/cue/cmd/testdata/code/go/pkg2/add.cue
+++ b/cmd/cue/cmd/testdata/code/go/pkg2/add.cue
@@ -12,7 +12,7 @@
 // See the License for the specific language governing permissions and
 // limitations under the License.
 
-package pkg2
+package pkgtwo
 
 Barzer: {
 	S: =~"cat$"
diff --git a/cmd/cue/cmd/testdata/code/go/pkg2/pkg2.go b/cmd/cue/cmd/testdata/code/go/pkg2/pkg2.go
index 42195d8..1fd4b8d 100644
--- a/cmd/cue/cmd/testdata/code/go/pkg2/pkg2.go
+++ b/cmd/cue/cmd/testdata/code/go/pkg2/pkg2.go
@@ -12,8 +12,8 @@
 // See the License for the specific language governing permissions and
 // limitations under the License.
 
-// Package pkg2 does other stuff.
-package pkg2
+// Package pkgtwo does other stuff.
+package pkgtwo
 
 import (
 	"math/big"
@@ -32,6 +32,8 @@
 	H bool `json:"-"`
 	S string
 
+	XY bool `json:"x-y"`
+
 	Err error
 }
 
diff --git a/cmd/cue/cmd/testdata/pkg/cuelang.org/go/cmd/cue/cmd/testdata/code/go/pkg1/file1_go_gen.cue b/cmd/cue/cmd/testdata/pkg/cuelang.org/go/cmd/cue/cmd/testdata/code/go/pkg1/file1_go_gen.cue
index 14b6774..9b3f184 100644
--- a/cmd/cue/cmd/testdata/pkg/cuelang.org/go/cmd/cue/cmd/testdata/code/go/pkg1/file1_go_gen.cue
+++ b/cmd/cue/cmd/testdata/pkg/cuelang.org/go/cmd/cue/cmd/testdata/code/go/pkg1/file1_go_gen.cue
@@ -5,7 +5,7 @@
 package pkg1
 
 import (
-	p2 "cuelang.org/go/cmd/cue/cmd/testdata/code/go/pkg2"
+	p2 "cuelang.org/go/cmd/cue/cmd/testdata/code/go/pkg2:pkgtwo"
 	"time"
 )
 
diff --git a/cmd/cue/cmd/testdata/pkg/cuelang.org/go/cmd/cue/cmd/testdata/code/go/pkg2/add_gen.cue b/cmd/cue/cmd/testdata/pkg/cuelang.org/go/cmd/cue/cmd/testdata/code/go/pkg2/add_gen.cue
index 9cb7264..cd02e88 100644
--- a/cmd/cue/cmd/testdata/pkg/cuelang.org/go/cmd/cue/cmd/testdata/code/go/pkg2/add_gen.cue
+++ b/cmd/cue/cmd/testdata/pkg/cuelang.org/go/cmd/cue/cmd/testdata/code/go/pkg2/add_gen.cue
@@ -16,7 +16,7 @@
 // See the License for the specific language governing permissions and
 // limitations under the License.
 
-package pkg2
+package pkgtwo
 
 Barzer: {
 	S: =~"cat$"
diff --git a/cmd/cue/cmd/testdata/pkg/cuelang.org/go/cmd/cue/cmd/testdata/code/go/pkg2/pkg2_go_gen.cue b/cmd/cue/cmd/testdata/pkg/cuelang.org/go/cmd/cue/cmd/testdata/code/go/pkg2/pkg2_go_gen.cue
index 8d2a0c2..3ba6fb0 100644
--- a/cmd/cue/cmd/testdata/pkg/cuelang.org/go/cmd/cue/cmd/testdata/code/go/pkg2/pkg2_go_gen.cue
+++ b/cmd/cue/cmd/testdata/pkg/cuelang.org/go/cmd/cue/cmd/testdata/code/go/pkg2/pkg2_go_gen.cue
@@ -2,8 +2,8 @@
 
 //cue:generate cue get go cuelang.org/go/cmd/cue/cmd/testdata/code/go/pkg2
 
-// Package pkg2 does other stuff.
-package pkg2
+// Package pkgtwo does other stuff.
+package pkgtwo
 
 import (
 	t "time"
@@ -11,14 +11,15 @@
 
 // A Barzer barzes.
 Barzer :: {
-	a:   int @go(A) @protobuf(2,varint,)
-	T:   t.Time
-	B:   null | int    @go(,*big.Int)
-	C:   int           @go(,big.Int)
-	F:   string        @go(,big.Float) @xml(,attr)
-	G:   null | string @go(,*big.Float)
-	S:   string
-	Err: _ @go(,error)
+	a:     int @go(A) @protobuf(2,varint,)
+	T:     t.Time
+	B:     null | int    @go(,*big.Int)
+	C:     int           @go(,big.Int)
+	F:     string        @go(,big.Float) @xml(,attr)
+	G:     null | string @go(,*big.Float)
+	S:     string
+	"x-y": bool @go(XY)
+	Err:   _    @go(,error)
 }
 
 Perm :: 0o755