Skip to content

Commit

Permalink
Keep go generated code from causing a collision
Browse files Browse the repository at this point in the history
Example:

```
   interface Persistent {
   }

   annotation persistent(interface, field) :Void;
```

The annotation `persistent` generates the following go code
(before this change):

   `const Persistent = uint64(0x...)`

After this change, the generated code for an annotation always appends
an underscore:

   `const Persistent_ = uint64(0x...)`

Discussed on capnproto#46,
capnproto/capnproto#323, as well as
a $Go.name() to rename the annotation in this repo, which is
essentially maintaining a fork of upstream capnp's persistent.capnp.

This removes the $Go.name(), as a small step toward removing
go-capnp's copies of capnp files.
  • Loading branch information
davidhubbard committed Aug 7, 2023
1 parent f60ed99 commit feb3238
Show file tree
Hide file tree
Showing 11 changed files with 83 additions and 77 deletions.
3 changes: 3 additions & 0 deletions capnpc-go/capnpc-go.go
Original file line number Diff line number Diff line change
@@ -1,4 +1,7 @@
/*
Copyright (c) 2013-2023 Sandstorm Development Group, Inc. and contributors
Licensed under the MIT License:
capnpc-go is the Cap'n proto code generator for Go. It reads a
CodeGeneratorRequest from stdin and for a file foo.capnp it writes
foo.capnp.go. This is usually invoked from `capnp compile -ogo`.
Expand Down
34 changes: 21 additions & 13 deletions capnpc-go/capnpc-go_test.go
Original file line number Diff line number Diff line change
@@ -1,3 +1,7 @@
/*
Copyright (c) 2013-2023 Sandstorm Development Group, Inc. and contributors
Licensed under the MIT License:
*/
package main

import (
Expand Down Expand Up @@ -537,7 +541,7 @@ func TestPersistent(t *testing.T) {
break;
}
defer os.RemoveAll(dir)
genfname := filepath.Join(dir, test.fname+".go")
genfname := test.fname+".go"

data, err := readTestFile(test.fname)
if err != nil {
Expand All @@ -554,36 +558,39 @@ func TestPersistent(t *testing.T) {
t.Errorf("Reading code generator request %q: %v", test.fname, err)
continue
}
requestedFiles, err := req.RequestedFiles()
reqFiles, err := req.RequestedFiles()
if err != nil {
t.Errorf("Reading code generator request %q: RequestedFiles: %v", test.fname, err)
continue
}
if requestedFiles.Len() < 1 {
t.Errorf("Reading code generator request %q: %d RequestedFiles", test.fname, requestedFiles.Len())
if reqFiles.Len() < 1 {
t.Errorf("Reading code generator request %q: %d RequestedFiles", test.fname, reqFiles.Len())
continue
}
nodes, err := buildNodeMap(req)
if err != nil {
t.Errorf("buildNodeMap %q: %v", test.fname, err)
continue
}
g := newGenerator(requestedFiles.At(0).Id(), nodes, test.opts)
if err := g.defineFile(); err != nil {
t.Errorf("defineFile %q %+v: %v", test.fname, test.opts, err)
g := newGenerator(reqFiles.At(0).Id(), nodes, test.opts)
err = g.defineFile()
if err != nil {
reqFname, _ := reqFiles.At(0).Filename()
t.Errorf("defineFile %q %+v: file %q: %v", test.fname, test.opts, reqFname, err)
continue
}
src := g.generate()
err = os.WriteFile(genfname, []byte(src), 0660)
genfpath := filepath.Join(dir, genfname)
err = os.WriteFile(genfpath, []byte(src), 0660)
if err != nil {
t.Fatalf("Writing generated code %q: %v", genfname, err)
t.Fatalf("Writing generated code %q: %v", genfpath, err)
break
}

// Relies on persistent-simple.capnp with $Go.package("") that
// is not "main" so `go build` skips writing an executable.
// Relies on persistent-simple.capnp with $Go.package("persistent_simple")
// not being ("main"). Thus `go build` skips writing an executable.
args := []string{
"build", "-C", dir, test.fname+".go",
"build", "-C", dir, genfname,
}
cmd := exec.Command("go", args...)
cmd.Stdin = strings.NewReader("")
Expand All @@ -594,9 +601,10 @@ func TestPersistent(t *testing.T) {
if err = cmd.Run(); err != nil {
if gotcode, ok := err.(*exec.ExitError); ok {
exitcode := gotcode.ExitCode()
t.Errorf("exitcode:%d", exitcode)
t.Errorf("go %+v exitcode:%d", args, exitcode)
t.Errorf("sout:\n%s", sout.String())
t.Errorf("serr:\n%s", serr.String())
//t.Errorf("\n%s:\n%s", genfname, src)
continue
} else {
t.Errorf("go %+v: %v", args, err)
Expand Down
8 changes: 7 additions & 1 deletion capnpc-go/nodes.go
Original file line number Diff line number Diff line change
Expand Up @@ -257,7 +257,13 @@ func resolveName(nodes nodeMap, n *node, base, name string, file *node) error {
}
name = parseAnnotations(na).Rename(name)
if base == "" {
n.Name = strings.Title(name)
if n.Which() == schema.Node_Which_annotation {
// Keep Annotation from colliding with another node that only
// differs in capitalization (see: persistent.capnp)
n.Name = strings.Title(name) + "_"
} else {
n.Name = strings.Title(name)
}
} else {
n.Name = base + "_" + name
}
Expand Down
16 changes: 9 additions & 7 deletions capnpc-go/testdata/persistent-simple.capnp
Original file line number Diff line number Diff line change
@@ -1,4 +1,4 @@
# Copyright (c) 2023
# Copyright (c) 2023 Sandstorm Development Group, Inc. and contributors
# Licensed under the MIT License:
#
# Permission is hereby granted, free of charge, to any person obtaining a copy
Expand All @@ -19,17 +19,19 @@
# OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
# THE SOFTWARE.

using Cxx = import "/capnp/c++.capnp";
using Go = import "/go.capnp";
using Go = import "go.capnp";

@0xbcfe42e3392b05a8;

$Cxx.namespace("test_regen");
$Go.package("test_regen");
$Go.import("foo/test_regen");
$Go.package("persistent_simple");
$Go.import("capnproto.org/go/capnp/v3/capnpc-go/testdata/persistent-simple");

# defining any "interface" fails with "persistent-simple.capnp.out.go:49:33: undefined: context"
interface Persistent {
call @0 () -> ();
}

annotation persistent(interface, field) :Void;

struct ThisStructOnlyNeededToGetImportsToWork {
value @0 :Int64;
}
Binary file modified capnpc-go/testdata/persistent-simple.capnp.out
Binary file not shown.
12 changes: 6 additions & 6 deletions std/capnp/compat/json/json.capnp.go

Some generated files are not rendered by default. Learn more about how customized files appear on GitHub.

4 changes: 2 additions & 2 deletions std/capnp/cxx/c++.capnp.go

Some generated files are not rendered by default. Learn more about how customized files appear on GitHub.

2 changes: 1 addition & 1 deletion std/capnp/persistent.capnp
Original file line number Diff line number Diff line change
Expand Up @@ -108,7 +108,7 @@ interface Persistent@0xc8cb212fcd9f5691(SturdyRef, Owner) {
}
}

annotation persistent(interface, field) :Void $Go.name("PersistentAnnotation");
annotation persistent(interface, field) :Void;
# Apply this annotation to interfaces for objects that will always be persistent, instead of
# extending the Persistent capability, since the correct type parameters to Persistent depend on
# the realm, which is orthogonal to the interface type and therefore should not be defined
Expand Down
56 changes: 27 additions & 29 deletions std/capnp/persistent/persistent.capnp.go

Some generated files are not rendered by default. Learn more about how customized files appear on GitHub.

11 changes: 0 additions & 11 deletions std/fixups.patch
Original file line number Diff line number Diff line change
Expand Up @@ -38,14 +38,3 @@

interface @17 :Void;
# The only interface value that can be represented statically is "null", whose methods always
--- a/capnp/persistent.capnp 2021-10-21 15:12:33.501158612 -0400
+++ b/capnp/persistent.capnp 2021-10-21 15:13:31.930030219 -0400
@@ -108,7 +108,7 @@
}
}

-annotation persistent(interface, field) :Void;
+annotation persistent(interface, field) :Void $Go.name("PersistentAnnotation");
# Apply this annotation to interfaces for objects that will always be persistent, instead of
# extending the Persistent capability, since the correct type parameters to Persistent depend on
# the realm, which is orthogonal to the interface type and therefore should not be defined
14 changes: 7 additions & 7 deletions std/go/go.capnp.go

Some generated files are not rendered by default. Learn more about how customized files appear on GitHub.

0 comments on commit feb3238

Please sign in to comment.