Unverified Commit 0eb7b3be authored by Robert's avatar Robert Committed by GitHub

[Go] Namespaced imports fix (#5097)

Track and emit required FlatBuffers namespace imports in generated Go code.

Update Go code generator by moving most functionality into the generator class, to facilitate namespace tracking. (Note that the git diff in this combined commit may appear large due to this refactoring, but very little code was actually changed.)
Update Go code generator by tracking namespace imports when generating FlatBuffers code.
Update Go code generator by emitting package imports to correctly reference code in other FlatBuffers namespaces.
Create Go test that checks the usage of InParentNamespace objects (as defined in the example schema).
Create Docker test that checks the Go language port.
Fixes #4883
Fixes #3927

Individual commits:

* remove "static" from soon-to-be method functions
* move almost all functions into class as methods
* set current namespace and emit package names if needed
* track imported namespaces
* parent namespaces work
* docker test for go ^1.11
* update base image name for go docker test
* remove cerr debugging
* formatting fixes
* re-run generate_code.sh
* explicitly test namespace imports and usage
parent a821b156
This diff is collapsed.
......@@ -26,10 +26,13 @@ go_src=${go_path}/src
# Copy flatbuffer Go files to their own package directories to compile the
# test binary:
mkdir -p ${go_src}/MyGame/Example
mkdir -p ${go_src}/MyGame/Example2
mkdir -p ${go_src}/github.com/google/flatbuffers/go
mkdir -p ${go_src}/flatbuffers_test
cp -a MyGame/*.go ./go_gen/src/MyGame/
cp -a MyGame/Example/*.go ./go_gen/src/MyGame/Example/
cp -a MyGame/Example2/*.go ./go_gen/src/MyGame/Example2/
# do not compile the gRPC generated files, which are not tested by go_test.go
# below, but have their own test.
rm ./go_gen/src/MyGame/Example/*_grpc.go
......
......@@ -4,6 +4,8 @@ package Example
import (
flatbuffers "github.com/google/flatbuffers/go"
MyGame "MyGame"
)
/// an example documentation comment: monster object
......@@ -516,12 +518,12 @@ func (rcv *Monster) VectorOfDoublesLength() int {
return 0
}
func (rcv *Monster) ParentNamespaceTest(obj *InParentNamespace) *InParentNamespace {
func (rcv *Monster) ParentNamespaceTest(obj *MyGame.InParentNamespace) *MyGame.InParentNamespace {
o := flatbuffers.UOffsetT(rcv._tab.Offset(72))
if o != 0 {
x := rcv._tab.Indirect(o + rcv._tab.Pos)
if obj == nil {
obj = new(InParentNamespace)
obj = new(MyGame.InParentNamespace)
}
obj.Init(rcv._tab.Bytes, x)
return obj
......
FROM golang:1.11-stretch as base
WORKDIR /code
ADD . .
RUN cp flatc_debian_stretch flatc
WORKDIR /code/tests
RUN go version
RUN ./GoTest.sh
......@@ -17,7 +17,9 @@
package main
import (
mygame "MyGame" // refers to generated code
example "MyGame/Example" // refers to generated code
"bytes"
"flag"
"fmt"
......@@ -111,6 +113,9 @@ func TestAll(t *testing.T) {
// Check Builder.CreateByteVector
CheckCreateByteVector(t.Fatalf)
// Check a parent namespace import
CheckParentNamespace(t.Fatalf)
// If the filename of the FlatBuffers file generated by the Java test
// is given, check that Go code can read it, and that Go code
// generates an identical buffer when used to create the example data:
......@@ -1444,6 +1449,54 @@ func CheckCreateByteVector(fail func(string, ...interface{})) {
}
}
func CheckParentNamespace(fail func(string, ...interface{})) {
var empty, nonempty []byte
// create monster with an empty parent namespace field
{
builder := flatbuffers.NewBuilder(0)
example.MonsterStart(builder)
m := example.MonsterEnd(builder)
builder.Finish(m)
empty = make([]byte, len(builder.FinishedBytes()))
copy(empty, builder.FinishedBytes())
}
// create monster with a non-empty parent namespace field
{
builder := flatbuffers.NewBuilder(0)
mygame.InParentNamespaceStart(builder)
pn := mygame.InParentNamespaceEnd(builder)
example.MonsterStart(builder)
example.MonsterAddParentNamespaceTest(builder, pn)
m := example.MonsterEnd(builder)
builder.Finish(m)
nonempty = make([]byte, len(builder.FinishedBytes()))
copy(nonempty, builder.FinishedBytes())
}
// read monster with empty parent namespace field
{
m := example.GetRootAsMonster(empty, 0)
if m.ParentNamespaceTest(nil) != nil {
fail("expected nil ParentNamespaceTest for empty field")
}
}
// read monster with non-empty parent namespace field
{
m := example.GetRootAsMonster(nonempty, 0)
if m.ParentNamespaceTest(nil) == nil {
fail("expected non-nil ParentNamespaceTest for non-empty field")
}
}
}
// Include simple random number generator to ensure results will be the
// same cross platform.
// http://en.wikipedia.org/wiki/Park%E2%80%93Miller_random_number_generator
......
......@@ -4,6 +4,8 @@ package NamespaceA
import (
flatbuffers "github.com/google/flatbuffers/go"
NamespaceC "NamespaceC"
)
type SecondTableInA struct {
......@@ -26,12 +28,12 @@ func (rcv *SecondTableInA) Table() flatbuffers.Table {
return rcv._tab
}
func (rcv *SecondTableInA) ReferToC(obj *TableInC) *TableInC {
func (rcv *SecondTableInA) ReferToC(obj *NamespaceC.TableInC) *NamespaceC.TableInC {
o := flatbuffers.UOffsetT(rcv._tab.Offset(4))
if o != 0 {
x := rcv._tab.Indirect(o + rcv._tab.Pos)
if obj == nil {
obj = new(TableInC)
obj = new(NamespaceC.TableInC)
}
obj.Init(rcv._tab.Bytes, x)
return obj
......
......@@ -4,6 +4,8 @@ package NamespaceA
import (
flatbuffers "github.com/google/flatbuffers/go"
NamespaceA__NamespaceB "NamespaceA/NamespaceB"
)
type TableInFirstNS struct {
......@@ -26,12 +28,12 @@ func (rcv *TableInFirstNS) Table() flatbuffers.Table {
return rcv._tab
}
func (rcv *TableInFirstNS) FooTable(obj *TableInNestedNS) *TableInNestedNS {
func (rcv *TableInFirstNS) FooTable(obj *NamespaceA__NamespaceB.TableInNestedNS) *NamespaceA__NamespaceB.TableInNestedNS {
o := flatbuffers.UOffsetT(rcv._tab.Offset(4))
if o != 0 {
x := rcv._tab.Indirect(o + rcv._tab.Pos)
if obj == nil {
obj = new(TableInNestedNS)
obj = new(NamespaceA__NamespaceB.TableInNestedNS)
}
obj.Init(rcv._tab.Bytes, x)
return obj
......@@ -51,12 +53,12 @@ func (rcv *TableInFirstNS) MutateFooEnum(n EnumInNestedNS) bool {
return rcv._tab.MutateInt8Slot(6, n)
}
func (rcv *TableInFirstNS) FooStruct(obj *StructInNestedNS) *StructInNestedNS {
func (rcv *TableInFirstNS) FooStruct(obj *NamespaceA__NamespaceB.StructInNestedNS) *NamespaceA__NamespaceB.StructInNestedNS {
o := flatbuffers.UOffsetT(rcv._tab.Offset(8))
if o != 0 {
x := o + rcv._tab.Pos
if obj == nil {
obj = new(StructInNestedNS)
obj = new(NamespaceA__NamespaceB.StructInNestedNS)
}
obj.Init(rcv._tab.Bytes, x)
return obj
......
......@@ -4,6 +4,8 @@ package NamespaceC
import (
flatbuffers "github.com/google/flatbuffers/go"
NamespaceA "NamespaceA"
)
type TableInC struct {
......@@ -26,12 +28,12 @@ func (rcv *TableInC) Table() flatbuffers.Table {
return rcv._tab
}
func (rcv *TableInC) ReferToA1(obj *TableInFirstNS) *TableInFirstNS {
func (rcv *TableInC) ReferToA1(obj *NamespaceA.TableInFirstNS) *NamespaceA.TableInFirstNS {
o := flatbuffers.UOffsetT(rcv._tab.Offset(4))
if o != 0 {
x := rcv._tab.Indirect(o + rcv._tab.Pos)
if obj == nil {
obj = new(TableInFirstNS)
obj = new(NamespaceA.TableInFirstNS)
}
obj.Init(rcv._tab.Bytes, x)
return obj
......@@ -39,12 +41,12 @@ func (rcv *TableInC) ReferToA1(obj *TableInFirstNS) *TableInFirstNS {
return nil
}
func (rcv *TableInC) ReferToA2(obj *SecondTableInA) *SecondTableInA {
func (rcv *TableInC) ReferToA2(obj *NamespaceA.SecondTableInA) *NamespaceA.SecondTableInA {
o := flatbuffers.UOffsetT(rcv._tab.Offset(6))
if o != 0 {
x := rcv._tab.Indirect(o + rcv._tab.Pos)
if obj == nil {
obj = new(SecondTableInA)
obj = new(NamespaceA.SecondTableInA)
}
obj.Init(rcv._tab.Bytes, x)
return obj
......
Markdown is supported
0% or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment