Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Support relative include directives in .fbs #40

Open
wants to merge 1 commit into
base: main
Choose a base branch
from
Open
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
9 changes: 9 additions & 0 deletions test/integration/include-paths/cpp/main.cpp
Original file line number Diff line number Diff line change
@@ -0,0 +1,9 @@
#define CATCH_CONFIG_MAIN

#include "catch2/catch.hpp"
#include "objectbox.hpp"
#include "objectbox-model.h"
#include "schema.obx.hpp"
#include "shared/store-init.h"

using namespace obx;
34 changes: 34 additions & 0 deletions test/integration/include-paths/integration_test.go
Original file line number Diff line number Diff line change
@@ -0,0 +1,34 @@
/*
* Copyright (C) 2020 ObjectBox Ltd. All rights reserved.
* https://objectbox.io
*
* This file is part of ObjectBox Generator.
*
* ObjectBox Generator is free software: you can redistribute it and/or modify
* it under the terms of the GNU General Public License as published by
* the Free Software Foundation, either version 3 of the License, or
* (at your option) any later version.
* ObjectBox Generator is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU General Public License for more details.
*
* You should have received a copy of the GNU General Public License
* along with ObjectBox Generator. If not, see <http://www.gnu.org/licenses/>.
*/

package typeful

import (
"testing"

"github.com/objectbox/objectbox-generator/test/integration"
)

func TestCpp(t *testing.T) {
conf := &integration.CCppTestConf{
SchemaPath: "schema/schema.fbs",
}
defer conf.Cleanup()
conf.CommonExecute(t, integration.Cpp11)
}
1 change: 1 addition & 0 deletions test/integration/include-paths/schema/other/other.fbs
Original file line number Diff line number Diff line change
@@ -0,0 +1 @@
enum Values : uint { a, b }
3 changes: 3 additions & 0 deletions test/integration/include-paths/schema/schema.fbs
Original file line number Diff line number Diff line change
@@ -0,0 +1,3 @@
include "other/other.fbs";

table Entity { id: uint64; value: Values; }
37 changes: 21 additions & 16 deletions test/integration/integration.go
Original file line number Diff line number Diff line change
Expand Up @@ -109,6 +109,7 @@ func generateCCpp(t *testing.T, srcPath string, outDir string, cGenerator *cgene
type CCppTestConf struct {
Cmake *cmake.Cmake
Generator *cgenerator.CGenerator
SchemaPath string
}

func sourceExt(cpp bool) string {
Expand All @@ -122,7 +123,7 @@ func sourceExt(cpp bool) string {
// CommonExecute executes the integration with the simple/common setup
func (conf *CCppTestConf) CommonExecute(t *testing.T, lang cCppStandard) {
conf.CreateCMake(t, lang, "main."+sourceExt(lang.isCpp()))
conf.Generate(t, nil)
conf.Generate(t)
conf.Build(t)
conf.Run(t, nil)
}
Expand Down Expand Up @@ -177,24 +178,28 @@ func (conf *CCppTestConf) CreateCMake(t *testing.T, lang cCppStandard, mainFile
}
}

// Generate loads *.fbs files in the current dir (or the given schema file) and generates the code
func (conf *CCppTestConf) Generate(t *testing.T, schemas map[string]string) {
func (conf *CCppTestConf) WriteSchemas(t *testing.T, schemas map[string]string) string {
var srcPath string

if len(schemas) != 0 {
for name, content := range schemas {
// passing an empty name and content is a trick to having multiple schames to enable wildcard generation.
if len(name) == 0 && len(content) == 0 {
continue
}

srcPath = filepath.Join(conf.Cmake.ConfDir, name)
assert.NoErr(t, ioutil.WriteFile(srcPath, []byte(content), 0600))
}
if len(schemas) != 1 {
srcPath = filepath.Join(conf.Cmake.ConfDir, "*.fbs")
for name, content := range schemas {
// passing an empty name and content is a trick to having multiple schames to enable wildcard generation.
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Suggested change
// passing an empty name and content is a trick to having multiple schames to enable wildcard generation.
// passing an empty name and content is a trick to having multiple schemas to enable wildcard generation.

Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Maybe document this at function level so it's more obvious what adding an empty values map entry and no map entry does (not sure if here or at Generate)?

if len(name) == 0 && len(content) == 0 {
continue
}
} else {

srcPath = filepath.Join(conf.Cmake.ConfDir, name)
assert.NoErr(t, ioutil.WriteFile(srcPath, []byte(content), 0600))
}
if len(schemas) != 1 {
srcPath = filepath.Join(conf.Cmake.ConfDir, "*.fbs")
}
return srcPath
}

// Generate loads .fbs files specified by conf.SchemaPath and generates the code
func (conf *CCppTestConf) Generate(t *testing.T) {
var srcPath = conf.SchemaPath
if len(srcPath) == 0 {
srcPath = "*.fbs"
}

Expand Down
15 changes: 10 additions & 5 deletions test/integration/optional/integration_test.go
Original file line number Diff line number Diff line change
Expand Up @@ -78,19 +78,24 @@ func TestCppAndC(t *testing.T) {
conf := &integration.CCppTestConf{}
defer conf.Cleanup()
conf.CreateCMake(t, integration.Cpp17, "main.cpp")
conf.Generate(t, map[string]string{"rel.fbs": "table RelTarget {id: uint64;}"})
conf.SchemaPath = conf.WriteSchemas(t, map[string]string{"rel.fbs": "table RelTarget {id: uint64;}"})
conf.Generate(t)

conf.Generator = &cgenerator.CGenerator{Optional: "std::optional"}
conf.Generate(t, map[string]string{"std-optional.fbs": "table Optional {" + optionalSchemaFields + "}"})
conf.SchemaPath = conf.WriteSchemas(t, map[string]string{"std-optional.fbs": "table Optional {" + optionalSchemaFields + "}"})
conf.Generate(t)

conf.Generator = &cgenerator.CGenerator{Optional: "std::unique_ptr"}
conf.Generate(t, map[string]string{"std-unique_ptr.fbs": "table UniquePtr {" + optionalSchemaFields + "}"})
conf.SchemaPath = conf.WriteSchemas(t, map[string]string{"std-unique_ptr.fbs": "table UniquePtr {" + optionalSchemaFields + "}"})
conf.Generate(t)

conf.Generator = &cgenerator.CGenerator{Optional: "std::shared_ptr"}
conf.Generate(t, map[string]string{"std-shared_ptr.fbs": "table SharedPtr {" + optionalSchemaFields + "}"})
conf.SchemaPath = conf.WriteSchemas(t, map[string]string{"std-shared_ptr.fbs": "table SharedPtr {" + optionalSchemaFields + "}"})
conf.Generate(t)

conf.Generator = &cgenerator.CGenerator{PlainC: true, Optional: "ptr"}
conf.Generate(t, map[string]string{"c-ptr.fbs": "table PlainCPtr {" + optionalSchemaFields + "}"})
conf.SchemaPath = conf.WriteSchemas(t, map[string]string{"c-ptr.fbs": "table PlainCPtr {" + optionalSchemaFields + "}"})
conf.Generate(t)

conf.Build(t)
conf.Run(t, nil)
Expand Down
9 changes: 4 additions & 5 deletions test/integration/property-clear/property_clear_test.go
Original file line number Diff line number Diff line change
Expand Up @@ -44,10 +44,8 @@ func TestCpp(t *testing.T) {

// BEFORE start
conf.CreateCMake(t, integration.Cpp11, "step-1.cpp")
conf.Generate(t, map[string]string{"schema.fbs": `table EntityName {
id:uint64;
value:int;
}`})
conf.SchemaPath = conf.WriteSchemas(t, map[string]string{"schema.fbs": `table EntityName { id:uint64; value:int; }`})
conf.Generate(t)
modelJSONFile := generator.ModelInfoFile(conf.Cmake.ConfDir)
modelInfo, err := model.LoadModelFromJSONFile(modelJSONFile)
assert.NoErr(t, err)
Expand All @@ -69,11 +67,12 @@ func TestCpp(t *testing.T) {
modelInfo.Entities[0].Properties[1].Name, modelInfo.Entities[0].Properties[1].Id, newUid)
assert.NoErr(t, err)
conf.CreateCMake(t, integration.Cpp11, "step-2.cpp")
conf.Generate(t, map[string]string{"schema.fbs": `table EntityName {
conf.SchemaPath = conf.WriteSchemas(t, map[string]string{"schema.fbs": `table EntityName {
id:uint64;
` + "/// objectbox: uid=" + strconv.FormatInt(int64(newUid), 10) + `
value:int;
}`})
conf.Generate(t)
modelInfo, err = model.LoadModelFromJSONFile(modelJSONFile)
assert.NoErr(t, err)
assert.Eq(t, 1, len(modelInfo.Entities))
Expand Down
6 changes: 4 additions & 2 deletions test/integration/removes/remove_test.go
Original file line number Diff line number Diff line change
Expand Up @@ -47,7 +47,7 @@ func TestCpp(t *testing.T) {

// STEP-1 start
conf.CreateCMake(t, integration.Cpp11, "step-1.cpp")
conf.Generate(t, map[string]string{"": "", "schema.fbs": `
conf.SchemaPath = conf.WriteSchemas(t, map[string]string{"": "", "schema.fbs": `
/// This entity will be removed in step 2
/// objectbox:relation(to=EntityB,name=standaloneRel)
table EntityA {
Expand All @@ -64,6 +64,7 @@ table EntityB {
id:uint64;
name:string;
}`})
conf.Generate(t)
modelJSONFile := generator.ModelInfoFile(conf.Cmake.ConfDir)
modelInfo, err := model.LoadModelFromJSONFile(modelJSONFile)
assert.NoErr(t, err)
Expand Down Expand Up @@ -97,11 +98,12 @@ table EntityB {

// STEP-2 start
conf.CreateCMake(t, integration.Cpp11, "step-2.cpp")
conf.Generate(t, map[string]string{"": "", "schema.fbs": `
conf.SchemaPath = conf.WriteSchemas(t, map[string]string{"": "", "schema.fbs": `
table EntityB {
id:uint64;
name:string;
}`})
conf.Generate(t)
modelInfo, err = model.LoadModelFromJSONFile(modelJSONFile)
assert.NoErr(t, err)
assert.Eq(t, 1, len(modelInfo.Entities))
Expand Down
6 changes: 4 additions & 2 deletions test/integration/renames/rename_test.go
Original file line number Diff line number Diff line change
Expand Up @@ -48,10 +48,11 @@ func TestCpp(t *testing.T) {

// BEFORE RENAME start
conf.CreateCMake(t, integration.Cpp11, "step-1.cpp")
conf.Generate(t, map[string]string{"schema.fbs": `table OldEntityName {
conf.SchemaPath = conf.WriteSchemas(t, map[string]string{"schema.fbs": `table OldEntityName {
id:uint64;
oldPropertyName:int;
}`})
conf.Generate(t)
modelJSONFile := generator.ModelInfoFile(conf.Cmake.ConfDir)
modelInfo, err := model.LoadModelFromJSONFile(modelJSONFile)
assert.NoErr(t, err)
Expand All @@ -66,12 +67,13 @@ func TestCpp(t *testing.T) {

// AFTER RENAME start
conf.CreateCMake(t, integration.Cpp11, "step-2.cpp")
conf.Generate(t, map[string]string{"schema.fbs": "/// objectbox: uid=" + entityUid + `
conf.SchemaPath = conf.WriteSchemas(t, map[string]string{"schema.fbs": "/// objectbox: uid=" + entityUid + `
table NewEntityName {
id:uint64;
` + "/// objectbox: uid=" + propertyUid + `
newPropertyName:int;
}`})
conf.Generate(t)
modelInfo, err = model.LoadModelFromJSONFile(modelJSONFile)
assert.NoErr(t, err)
assert.Eq(t, 1, len(modelInfo.Entities))
Expand Down
6 changes: 5 additions & 1 deletion third_party/flatbuffers-c-bridge/src/flatbuffersc.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -44,8 +44,12 @@ FBS_bytes* fbs_schema_parse_file(const char* filename, const char** out_error) {
options.binary_schema_comments = true; // include doc comments in the binary schema

flatbuffers::Parser parser(options);
if (!parser.Parse(contents.c_str(), nullptr, filename)) {
{
std::string fileDir = flatbuffers::StripFileName(filename);
std::vector<const char *> includeDirs = {fileDir.c_str(), nullptr};
if (!parser.Parse(contents.c_str(), includeDirs.data(), filename)) {
throw std::runtime_error(parser.error_);
}
}

if (!parser.error_.empty()) {
Expand Down