encoding/protobuf: provide default import path and short name

Put a proto file in googleapis.com by default if the
go_packagname is not provided.

googleapis.com without a subdomain is an invalid
domain and should thus be safe to use and will
always be resolved within a local pkg directory.
Alternatively, I could name it proto.cuelang.org
or proto.googleapis.com.

Note that the go_package mechanism is still
necessary to be able to determine a specific
destination of a package, for instance if it needs
to be merged with other CUE files within the same
directory (as the genoapi tool does).

Change-Id: I65484a0c940409b024160fa5d086bf27e3500894
Reviewed-on: https://cue-review.googlesource.com/c/cue/+/2820
Reviewed-by: Jason Wang <jasonwzm@google.com>
Reviewed-by: Marcel van Lohuizen <mpvl@golang.org>
diff --git a/encoding/protobuf/parse.go b/encoding/protobuf/parse.go
index 3c8713d..9647df4 100644
--- a/encoding/protobuf/parse.go
+++ b/encoding/protobuf/parse.go
@@ -101,16 +101,26 @@
 					failf(x.Position, "unquoting package filed: %v", err)
 				}
 				split := strings.Split(str, ";")
-				p.goPkgPath = split[0]
-				switch len(split) {
-				case 1:
-					p.goPkg = path.Base(str)
-				case 2:
-					p.goPkg = split[1]
+				switch {
+				case strings.Contains(split[0], "."):
+					p.cuePkgPath = split[0]
+					switch len(split) {
+					case 1:
+						p.shortPkgName = path.Base(str)
+					case 2:
+						p.shortPkgName = split[1]
+					default:
+						failf(x.Position, "unexpected ';' in %q", str)
+					}
+					p.file.Name = ast.NewIdent(p.shortPkgName)
+
+				case len(split) == 1:
+					p.shortPkgName = split[0]
+					p.file.Name = ast.NewIdent(p.shortPkgName)
+
 				default:
-					failf(x.Position, "unexpected ';' in %q", str)
+					failf(x.Position, "malformed go_package clause %s", str)
 				}
-				p.file.Name = ast.NewIdent(p.goPkg)
 				// name.AddComment(comment(x.Comment, true))
 				// name.AddComment(comment(x.InlineComment, false))
 			}
@@ -163,10 +173,10 @@
 
 	proto3 bool
 
-	id        string
-	protoPkg  string
-	goPkg     string
-	goPkgPath string
+	id           string
+	protoPkg     string
+	shortPkgName string
+	cuePkgPath   string
 
 	// w bytes.Buffer
 	file   *ast.File
@@ -187,6 +197,23 @@
 	pkg   *protoConverter
 }
 
+func (p *protoConverter) importPath() string {
+	if p.cuePkgPath == "" && p.protoPkg != "" {
+		dir := strings.Replace(p.protoPkg, ".", "/", -1)
+		p.cuePkgPath = path.Join("googleapis.com", dir)
+	}
+	return p.cuePkgPath
+}
+
+func (p *protoConverter) shortName() string {
+	if p.shortPkgName == "" && p.protoPkg != "" {
+		split := strings.Split(p.protoPkg, ".")
+		p.shortPkgName = split[len(split)-1]
+		p.file.Name = ast.NewIdent(p.shortPkgName)
+	}
+	return p.shortPkgName
+}
+
 func (p *protoConverter) toCUEPos(pos scanner.Position) token.Pos {
 	return p.tfile.Pos(pos.Offset, 0)
 }
@@ -297,7 +324,7 @@
 		}
 		if m, ok := p.scope[0][name[:i]]; ok {
 			if m.pkg != nil {
-				p.imported[m.pkg.goPkgPath] = true
+				p.imported[m.pkg.importPath()] = true
 				// TODO: do something more principled.
 			}
 			cueName := strings.Replace(name[i:], ".", "_", -1)
@@ -340,8 +367,8 @@
 	}
 
 	prefix := ""
-	if imp.goPkgPath != p.goPkgPath {
-		prefix = imp.goPkg + "."
+	if imp.importPath() != p.importPath() {
+		prefix = imp.shortName() + "."
 	}
 
 	pkgNamespace := strings.Split(imp.protoPkg, ".")
@@ -354,7 +381,7 @@
 			}
 			if _, ok := p.scope[0][ref]; !ok {
 				pkg := imp
-				if imp.goPkgPath == p.goPkgPath {
+				if imp.importPath() == p.importPath() {
 					pkg = nil
 				}
 				p.scope[0][ref] = mapping{prefix + k, "", pkg}